View a markdown version of this page

自动实时图像生成 - Amazon Kinesis Video Streams

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

自动实时图像生成

亚马逊 Kinesis Video Streams 提供转码和交付图像的功能。Kinesis Video Streams 自动从视频数据中实时提取图像,并将图像传输到您指定的 Amazon S3 存储桶。实现实时、自动的图像提取涉及以下步骤:

  • 创建 S3 存储桶以接收生成的图像。

  • 配置ImageGenerationConfiguration直播属性,告知 Kinesis Video Streams 如何创建图像以及将它们发送到何处。

  • 添加图像生成标签 — Kinesis Video Streams 仅使用带有图像生成标签的片段生成图像。这些标签是在使用 Kinesis 视频流制作器 SDK 以及该putKinesisVideoEventMetadata方法上传视频时添加的。

以下过程提供了完成每个步骤的说明。

如果您使用客户管理的密钥,请确保执行PutMedia调用的角色(上传者)具有加密和解密数据以及访问 Amazon S3 存储桶所需的以下权限。

  • kms:Encrypt

  • kms:GenerateDataKey

  • kms:Decrypt

  • s3:PutObject

有关更多信息,请参阅 如何开始使用服务器端加密?

配置生成的图像目的地
  1. 创建用于发送图像的 S3 目标存储桶。

    按照亚马逊 S3 用户指南创建亚马逊 S3 存储桶。

    记下存储桶的 URI,在下一步更新直播的图像生成配置时需要使用该URI。

  2. 验证您是否已 AWS CLI 安装和配置。有关更多信息,请参阅版本 2 的AWS Command Line Interface 用户指南

  3. 使用以下内容作为输入创建一个名update-image-generation-input.json为的新文件。使用要使用的值更新占位符值。有关支持的最大值和最小值,请参阅 UpdateImageGenerationConfiguration API。

    { "StreamName": "demo-stream", "ImageGenerationConfiguration": { "Status": "ENABLED", "DestinationConfig": { "DestinationRegion": "us-east-1", "Uri": "s3://my-bucket-name" }, "SamplingInterval": 200, "ImageSelectorType": "PRODUCER_TIMESTAMP", "Format": "JPEG", "FormatConfig": { "JPEGQuality": "80" }, "WidthPixels": 320, "HeightPixels": 240 } }
  4. 使用 UpdateImageGenerationConfiguration API 更新直播的图像生成配置,并附加 JSON 文件作为输入,如以下命令所示。请注意,文件路径指向当前目录中的文件。

    aws kinesisvideo update-image-generation-configuration \ --cli-input-json file://./update-image-generation-input.json
  5. 成功后,将返回一个空响应,并且您的终端中不会打印任何内容。

    注意

    更新映像生成配置后,启动图像生成工作流程至少需要 1 分钟。等待至少 1 分钟,然后再将视频上传到您的直播。

  6. 验证配置设置。使用调 AWS CLI 用直播DescribeImageGenerationConfiguration的 API。

    aws kinesisvideo describe-image-generation-configuration \ --stream-name "demo-stream"

Kinesis Video Streams 将仅为带有图像生成标签的片段生成和交付图像。与 Amazon S3 图像生成标签一起提供的任何其他片段元数据将另存为 Amazon S3 元数据。

注意

图像生成标签是指片段元数据标签,而不是流级标签。

重要

图像生成标签计入片段元数据标签限制。有关更多信息,请参阅 流式传输元数据服务配额

以下是使用该mkvinfo实用程序的片段元数据标签结构的示例。图像生成标签是一个 MKV 简单标签,其密钥为AWS_KINESISVIDEO_IMAGE_GENERATION但没有值。有关更多信息,请参阅 Matroska 文档中的视频标签示例。

|+ Tags | + Tag | // MANDATORY: Predefined MKV tag to trigger image generation for the fragment | + Simple | + Name: AWS_KINESISVIDEO_IMAGE_GENERATION | // OPTIONAL: S3 prefix which will be set as prefix for generated image. | + Simple | + Name: AWS_KINESISVIDEO_IMAGE_PREFIX | + String: image_prefix_in_s3 // 256 bytes max | // OPTIONAL: Key value pairs that will be persisted as S3 Image object metadata. | + Simple | + Name: CUSTOM_KEY_1 // Max 128 bytes | + String: CUSTOM_VALUE_1 // Max 256 bytes | + Simple | + Name: CUSTOM_KEY_2 // Max 128 bytes | + String: CUSTOM_VALUE_2 // Max 256 bytes

向片段添加图像生成标签

Kinesis Video Streams 仅为带有图像生成标签的片段生成和交付图像。Kinesis Video Streams 可识别这些特殊的 MKV 标签,并根据视频流的图像处理配置启动图像生成工作流程。

使用 Kinesis 视频流制作器 SDK 上传媒体时,您可以使用该putKinesisVideoEventMetadata方法将图像生成标签添加到要标记的每个片段中。使用包含putFramekeyframe标志的帧调用新片段时开始。

如果您上传的是预先录制的视频,则该视频的上传速度可能与录制的速率不同,具体取决于您的网络速度。如果您想根据视频的原始时间戳定期生成图像,我们建议您使用制作者时间戳来配置图像生成,而不是使用根据 Amazon Kinesis Video Streams 接收视频的速率生成的服务器时间戳。

要查看此代码的完整示例,请参阅中的VideoOnlyRealtimeStreamingSample代码示例 GitHub。

// Setup sample frame MEMSET(frameBuffer, 0x00, frameSize); frame.frameData = frameBuffer; frame.version = FRAME_CURRENT_VERSION; frame.trackId = DEFAULT_VIDEO_TRACK_ID; frame.duration = HUNDREDS_OF_NANOS_IN_A_SECOND / DEFAULT_FPS_VALUE; frame.decodingTs = defaultGetTime(); // current time frame.presentationTs = frame.decodingTs; Frame eofr = EOFR_FRAME_INITIALIZER; while(defaultGetTime() > streamStopTime) { frame.index = frameIndex; frame.flags = fileIndex % DEFAULT_KEY_FRAME_INTERVAL == 0 ? FRAME_FLAG_KEY_FRAME : FRAME_FLAG_NONE; frame.size = SIZEOF(frameBuffer); CHK_STATUS(readFrameData(&frame, frameFilePath)); // 1. End the previous fragment if (frame.flags == FRAME_FLAG_KEY_FRAME && !firstFrame) { putKinesisVideoFrame(streamHandle, &eofr); } // 2. putFrame call CHK_STATUS(putKinesisVideoFrame(streamHandle, &frame)); if (frame.flags == FRAME_FLAG_KEY_FRAME) { // 3. Adding the image generation tag CHK_STATUS(putKinesisVideoEventMetadata(streamHandle, STREAM_EVENT_TYPE_IMAGE_GENERATION, NULL);) // 4. Adding fragment metadata for (n = 1; n <= 5; n++) { SNPRINTF(metadataKey, METADATA_MAX_KEY_LENGTH, "SAMPLE_KEY_%d", n); SNPRINTF(metadataValue, METADATA_MAX_VALUE_LENGTH, "SAMPLE_VALUE_%d", frame.index + n); CHK_STATUS(putKinesisVideoFragmentMetadata(streamHandle, metadataKey, metadataValue, FALSE)); } } defaultThreadSleep(frame.duration); frame.decodingTs += frame.duration; frame.presentationTs = frame.decodingTs; frameIndex++; fileIndex++; fileIndex = fileIndex % NUMBER_OF_FRAME_FILES; firstFrame = TRUE; } // 5. End the final fragment putKinesisVideoFrame(streamHandle, &eofr);

用于设置示例帧的示例代码的元素解释如下:

  1. 每个片段都需要以 fragment (eofr) 结尾。该语句说,每当接收到一个新的关键帧(这表示下一帧的开始)时,在将下一帧添加到流中eofr之前,先放一个。

  2. 将当前帧放入直播中。

  3. 添加图像生成标签。可以在调用之后和调用之前的任何时间putFrame(keyFrame)调用该putKinesisVideoEventMetadata方法putFrame(eofr)。每个片段最多只能调用一次。由于每个片段只有一个关键帧,为简单起见,我们此时将其命名。检查的返回putKinesisVideoEventMetadata值是否有成功码 (0)。

  4. 添加其他自定义片段元数据,Kinesis Video Streams 会将其转换为 Amazon S3 对象元数据。

  5. 结束此上传会话中的最后一个片段。

使用示例添加图像生成标签

如果您想使用命令行选项来添加图像生成标签,则可以kvs_gstreamer_audio_video_sample在 C++ 制作器 SDK 中使用。通过添加-e image-e both参数来启用此功能,如以下示例所示。

./kvs_gstreamer_audio_video_sample stream-name \ -f video-to-upload.mp4 \ -e both

有关此示例应用程序的更多信息,请参阅中的亚马逊 Kinesis Video Streams CPP 制作器、GStreamer 插件和 JNI 自述文件。 GitHub

Amazon S3 对象路径(图片)

S3 对象路径描述了已配置的 S3 存储桶上生成的映像的交付位置。它使用以下格式:

ImagePrefix_AccountID_StreamName_ImageTimecode_RandomID.file-extension

对象路径元素定义如下:

  • ImagePrefix-AWS_KINESISVIDEO_IMAGE_PREFIX 如果存在,则为的值。

  • AccountID-创建直播时使用的 AWS 账户 ID。

  • StreamName-生成图像的流的名称。

  • ImageTimecode-生成图像的片段中的纪元时间码(以毫秒为单位)。

  • RandomID-随机 GUID。

  • file-extension-基于请求的图像格式的 JPG 或 PNG。

在此示例中,生成图像的对象路径如下所示:

111122223333_demo-stream_16907729324_f20f9add-75e7-4399-a30f-fc7aefb1bab7.jpg

检索图像元数据

您可以使用 S3 控制台或 CLI 检索生成的图像的元数据。

Kinesis Video Streams 设置片段编号、制作者和服务器时间戳以及所生成图像的内容类型元数据,全部格式化为 Amazon S3 对象元数据。如果存在任何其他 MKV 标签,这些标签也将作为 Amazon S3 对象元数据添加。以下示例显示如何使用 Amazon S3 头部对象 API 命令检索对象元数据。响应包括 Kinesis Video Streams 创建的元数据。

aws s3api head-object --bucket my-bucket-name --key 111122223333_demo-stream_1690707290324_f20f9add-7e57-4399-a30f-fc7aefb1bab7.jpg { "AcceptRanges": "bytes", "LastModified": "2023-07-30T08:54:51+00:00", "ContentLength": 22693, "ETag": "\"63e03cb6d57f77e2db984c1d344b1083\"", "ContentType": "image/jpeg", "ServerSideEncryption": "AES256", "Metadata": { "aws_kinesisvideo_producer_timestamp": "1690707290324", "aws_kinesisvideo_server_timestamp": "1690707289209", "aws_kinesisvideo_fragment_number": "91343852333182036507421233921329142742245756394" } }

有关 S3 对象元数据的更多信息,请参阅https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingMetadata.html

用于防范限制的 Amazon S3 URI 建议

如果您向 Amazon S3 写入数千张图像,则存在限制的风险。有关更多信息,请参阅 S3 前缀放置请求限制

Amazon S3 前缀以每秒 3,500 个 PUT 请求的 PUT 限制开始,并将随着时间的推移逐渐增加唯一前缀的上限。避免使用日期和时间作为 Amazon S3 前缀。时间编码的数据一次只能影响一个前缀,并且还会定期更改,从而使先前的前缀放大无效。

为了实现更快、更一致的 Amazon S3 扩展,我们建议在 Amazon S3 目标 URI 中添加随机前缀,例如十六进制代码或 UUID。例如,十六进制代码前缀自然会将您的请求随机拆分为 16 个不同的前缀(每个唯一十六进制字符的前缀),这将允许在 Amazon S3 自动扩展后每秒发出 56,000 个 PUT 请求。