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

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

自动实时图像生成

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

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

  • 配置 ImageGenerationConfigurationstream 属性,告诉 Kinesis Video Streams 如何创建图像以及将图像发送到何处。

  • 添加图像生成标签 — Kinesis Video Streams 仅使用带有图像生成标签的片段生成图像。这些标签是在使用 Kinesis Video Streams Producer 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为的新文件。使用要使用的值更新占位符值。有关支持的最大值和最小值,请参阅 UpdateImageGenerationConfigurationAPI。

    { "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. 验证配置设置。使用为您的直播调用 DescribeImageGenerationConfiguration API。 AWS CLI

    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 Video Streams Producer SDK 上传媒体时,您可以使用putKinesisVideoEventMetadata方法将图像生成标签添加到要标记的每个片段。当使用包含该keyframe标志的帧调putFrame用新片段时,就会开始一个新的片段。

如果您上传的是预先录制的视频,则该视频的上传速度可能与其录制速度不同,具体取决于您的网络速度。如果您想根据视频的原始时间戳定期生成图像,我们建议您使用制作人时间戳来配置图像生成,而不是使用基于 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. 每个片段都需要以片段 (eofr) 结尾。此语句说,每当收到一个新的关键帧(表示下一帧的开始)时,在将下一帧添加到流中eofr之前放一个。

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

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

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

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

使用样本添加图像生成标签

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

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

有关此示例应用程序的更多信息,请参阅中的 Amazon Kinesis Video Streams CPP Producer GStreamer 、Plugin 和 JNI 自述文件。 GitHub

亚马逊 S3 对象路径(图片)

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

ImagePrefix_AccountID_StreamName_ImageTimecode_RandomID.file-extension

对象路径元素的定义如下:

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

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

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

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

  • RandomID-随机指南。

  • 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 请求。