如何访问 Kinesis Video Streams 数据 - Amazon Connect

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

如何访问 Kinesis Video Streams 数据

你必须具备开发者技能才能使用 Kinesis Video Streams 数据。使用本节中的步骤和代码示例与发送到 Kinesis Video Streams 的客户音频数据进行交互。

开始使用示例

有一个示例项目可以帮助您开始使用 Amazon Connect 直播音频和使用 Amazon Transcribe 进行实时转录。 GitHub 请参阅 Amazon Connect 实时转录 Lambda

该项目提供了代码示例和功能齐全的 Lambda 函数。它们可以帮助你开始使用 Kinesis Video Streams 和 Amazon Transcribe 捕获和转录 Amazon Connect 电话。

您可以在此项目中使用 Lambda 函数来创建其他解决方案,例如:

  • 在 IVR 中捕获音频。

  • 向客服提供实时转录。

  • 为 Amazon Connect 创建语音信箱解决方案。

构建您自己的实现

您可能希望实现前面所述示例提供的解决方案之外的其他解决方案。如果是,本节介绍如何对 Kinesis Video Streams 进行正确的 API 调用,以便您可以从头开始构建自己的解决方案。

  1. 前往此 GitHub 页面,阅读有关 Amazon Connect 实时转录 Lambda 项目的信息。

  2. 选择 deployment 文件夹,然后下载 cloudformation.template

  3. 使用以下 Java 类示例,这些类是使用适用于 Java 的AWS SDK 在 Kinesis 视频解析器库之上构建的。

    • lmsDemo — 是一个带有调用 lmsExample 的主方法的类。

    • lmsExam ple — 类似于 Kinesis Video Streams 解析器库中提供的示例。它从指定的 Kinesis Video Streams 获取具有指定片段编号的媒体。此代码示例包括帧处理以分隔音轨。

    • LMSFrameProcessor — 由 LmsExample 调用,将来自 Kinesis Video Streams 的数据保存到指定的输出流。使用文件输出流将输出保存到文件。此代码示例还包括帧处理以分隔音轨。

  4. 使用 Audacity 或其他音频工具以导入 .raw 音频文件,此类文件采用 16 位有符号的 PCM Mono 格式。

访问 Kinesis Video Streams 数据的代码示例

LMSDemo.java

package com.amazonaws.kinesisvideo.parser.demo; import com.amazonaws.auth.AWSSessionCredentials; import com.amazonaws.auth.AWSSessionCredentialsProvider; import com.amazonaws.kinesisvideo.parser.examples.LMSExample; import com.amazonaws.regions.Regions; import java.io.FileOutputStream; import java.io.IOException; public class LMSDemo { public static void main(String args[]) throws InterruptedException, IOException { LMSExample example = new LMSExample(Regions.US_WEST_2, "<<StreamName>>", "<<FragmentNumber>>", new AWSSessionCredentialsProvider() { @Override public AWSSessionCredentials getCredentials() { return new AWSSessionCredentials() { @Override public String getSessionToken() { return "<<AWSSessionToken>>"; } @Override public String getAWSAccessKeyId() { return "<<AWSAccessKey>>"; } @Override public String getAWSSecretKey() { return "<<AWSSecretKey>>"; } }; } @Override public void refresh() { } }, new FileOutputStream("<<FileName>>.raw")); example.execute(); } }

LMSExample.java

package com.amazonaws.kinesisvideo.parser.examples; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.kinesisvideo.parser.ebml.MkvTypeInfos; import com.amazonaws.kinesisvideo.parser.mkv.MkvDataElement; import com.amazonaws.kinesisvideo.parser.mkv.MkvElementVisitException; import com.amazonaws.kinesisvideo.parser.mkv.MkvElementVisitor; import com.amazonaws.kinesisvideo.parser.mkv.MkvEndMasterElement; import com.amazonaws.kinesisvideo.parser.mkv.MkvStartMasterElement; import com.amazonaws.kinesisvideo.parser.utilities.FragmentMetadataVisitor; import com.amazonaws.kinesisvideo.parser.utilities.FrameVisitor; import com.amazonaws.kinesisvideo.parser.utilities.LMSFrameProcessor; import com.amazonaws.regions.Regions; import com.amazonaws.services.kinesisvideo.model.StartSelector; import com.amazonaws.services.kinesisvideo.model.StartSelectorType; import java.io.Closeable; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class LMSExample extends KinesisVideoCommon { private final ExecutorService executorService; private GetMediaProcessingArguments getMediaProcessingArguments; private final StreamOps streamOps; private final OutputStream outputStreamFromCustomer; private final OutputStream outputStreamToCustomer; private final String fragmentNumber; public LMSExample(Regions region, String streamName, String fragmentNumber, AWSCredentialsProvider credentialsProvider, OutputStream outputStreamFromCustomer, OutputStream outputStreamToCustomer) throws IOException { super(region, credentialsProvider, streamName); this.streamOps = new StreamOps(region, streamName, credentialsProvider); this.executorService = Executors.newFixedThreadPool(2); this.outputStreamFromCustomer = outputStreamFromCustomer; this.outputStreamToCustomer = outputStreamToCustomer; this.fragmentNumber = fragmentNumber; } public void execute () throws InterruptedException, IOException { getMediaProcessingArguments = GetMediaProcessingArguments.create(outputStreamFromCustomer, outputStreamToCustomer); try (GetMediaProcessingArguments getMediaProcessingArgumentsLocal = getMediaProcessingArguments) { //Start a GetMedia worker to read and process data from the Kinesis Video Stream. GetMediaWorker getMediaWorker = GetMediaWorker.create(getRegion(), getCredentialsProvider(), getStreamName(), new StartSelector().withStartSelectorType(StartSelectorType.FRAGMENT_NUMBER).withAfterFragmentNumber(fragmentNumber), streamOps.amazonKinesisVideo, getMediaProcessingArgumentsLocal.getFrameVisitor()); executorService.submit(getMediaWorker); //Wait for the workers to finish. executorService.shutdown(); executorService.awaitTermination(120, TimeUnit.SECONDS); if (!executorService.isTerminated()) { System.out.println("Shutting down executor service by force"); executorService.shutdownNow(); } else { System.out.println("Executor service is shutdown"); } } finally { outputStream.close(); } } private static class LogVisitor extends MkvElementVisitor { private final FragmentMetadataVisitor fragmentMetadataVisitor; private LogVisitor(FragmentMetadataVisitor fragmentMetadataVisitor) { this.fragmentMetadataVisitor = fragmentMetadataVisitor; } public long getFragmentCount() { return fragmentCount; } private long fragmentCount = 0; @Override public void visit(MkvStartMasterElement startMasterElement) throws MkvElementVisitException { if (MkvTypeInfos.EBML.equals(startMasterElement.getElementMetaData().getTypeInfo())) { fragmentCount++; System.out.println("Start of segment"); } } @Override public void visit(MkvEndMasterElement endMasterElement) throws MkvElementVisitException { if (MkvTypeInfos.SEGMENT.equals(endMasterElement.getElementMetaData().getTypeInfo())) { System.out.println("End of segment"); } } @Override public void visit(MkvDataElement dataElement) throws MkvElementVisitException { } } private static class GetMediaProcessingArguments implements Closeable { public FrameVisitor getFrameVisitor() { return frameVisitor; } private final FrameVisitor frameVisitor; public GetMediaProcessingArguments(FrameVisitor frameVisitor) { this.frameVisitor = frameVisitor; } public static GetMediaProcessingArguments create(OutputStream outputStreamFromCustomer, OutputStream outputStreamToCustomer) throws IOException { //Fragment metadata visitor to extract Kinesis Video fragment metadata from the GetMedia stream. FragmentMetadataVisitor fragmentMetadataVisitor = FragmentMetadataVisitor.create(); //A visitor used to log as the GetMedia stream is processed. LogVisitor logVisitor = new LogVisitor(fragmentMetadataVisitor); //A composite visitor to encapsulate the three visitors. FrameVisitor frameVisitor = FrameVisitor.create(LMSFrameProcessor.create(outputStreamFromCustomer, outputStreamToCustomer, fragmentMetadataVisitor)); return new GetMediaProcessingArguments(frameVisitor); } @Override public void close() throws IOException { } } }

LMSFrameProcessor .java

package com.amazonaws.kinesisvideo.parser.utilities; import com.amazonaws.kinesisvideo.parser.mkv.Frame; import com.amazonaws.kinesisvideo.parser.utilities.FragmentMetadataVisitor; import com.amazonaws.kinesisvideo.parser.utilities.MkvTrackMetadata; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; public class LMSFrameProcessor implements FrameVisitor.FrameProcessor { private OutputStream outputStreamFromCustomer; private OutputStream outputStreamToCustomer; private FragmentMetadataVisitor fragmentMetadataVisitor; protected LMSFrameProcessor(OutputStream outputStreamFromCustomer, OutputStream outputStreamToCustomer, FragmentMetadataVisitor fragmentMetadataVisitor) { this.outputStreamFromCustomer = outputStreamFromCustomer; this.outputStreamToCustomer = outputStreamToCustomer; } public static LMSFrameProcessor create(OutputStream outputStreamFromCustomer, OutputStream outputStreamToCustomer, FragmentMetadataVisitor fragmentMetadataVisitor) { return new LMSFrameProcessor(outputStreamFromCustomer, outputStreamToCustomer, fragmentMetadataVisitor); } @Override public void process(Frame frame, MkvTrackMetadata trackMetadata) { saveToOutPutStream(frame); } private void saveToOutPutStream(final Frame frame) { ByteBuffer frameBuffer = frame.getFrameData(); long trackNumber = frame.getTrackNumber(); MkvTrackMetadata metadata = fragmentMetadataVisitor.getMkvTrackMetadata(trackNumber); String trackName = metadata.getTrackName(); try { byte[] frameBytes = new byte[frameBuffer.remaining()]; frameBuffer.get(frameBytes); if (Strings.isNullOrEmpty(trackName) || "AUDIO_FROM_CUSTOMER".equals(trackName)) { outputStreamFromCustomer.write(frameBytes); } else if ("AUDIO_TO_CUSTOMER".equals(trackName)) { outputStreamToCustomer.write(frameBytes); } else { // Unknown track name. Not writing to output stream. } } catch (IOException e) { e.printStackTrace(); } } }