使用 Python 解析和渲染 Kinesis Video Streams 并获取输入帧的图像表示

Using Python to parse and render Kinesis Video Streams and get an image representation of the input frame

我已经设置了一个管道,我在其中将视频实时流式传输到 Kinesis Video Stream (KVS),后者将帧发送到 Amazon Rekognition 进行人脸识别,后者进一步将它们发送到 Kinesis Data Stream (KDS)。最后,KDS 将结果发送到 lambda。

对于一个已经进行了人脸识别的帧,我得到了如下格式的JSON:https://docs.aws.amazon.com/rekognition/latest/dg/streaming-video-kinesis-output-reference.html

我的目标是: 使用这个 JSON,我想以某种方式获得由 KVS 记录的帧的图像表示。

我尝试了什么:

这个 JSON 为我提供了片段编号。

我用这个片段号码打电话给 get_media_for_fragment_list

上面调用returns一个名为Payload的key作为响应。

我一直在尝试以某种方式将此有效载荷渲染成图像。

然而,我每次都没有这样做,因为我不知道如何理解这个有效载荷并对其进行解码。

以下是代码片段。

    def getFrameFromFragment(fragment):
         client = boto3.client('kinesis-video-archived-media',endpoint_url=data_endpoint_for_kvs)
         response = client.get_media_for_fragment_list(
             StreamName='kvs1',
             Fragments=[
                fragment,
             ]
         )
         payload = response['Payload']
         print(payload.read())

如何使用此负载获取图像?

我知道 Java 中存在的解析器:https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/examples-renderer.html

但是,我想知道 Python 中的解决方案。

如果我的问题陈述有误或没有意义,请随时向我询问有关此问题的更多信息。

感谢您的帮助。 :)

您获取的负载是 MKV 格式:https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_reader_GetMediaForFragmentList.html#API_reader_GetMediaForFragmentList_ResponseSyntax。要获取图像,您只需要获取该片段中的关键帧并将其转换为图像即可。

GetMedia返回的是MKV打包格式的码流。首先,您需要使用一些 Python 库从 MKV 格式中提取帧 (https://github.com/vi/mkvparse or alike). Next, your stream is likely to be encoded. For example H264. You will also need to decode the frame in order to get the actual bitmap of the image if that's what you need. There are few software based decoders seem to be available for Python: https://github.com/DaWelter/h264decoder

虽然我不熟悉这些项目。

使用以下代码接收payload后,

kvs_stream = kvs_video_client.get_media(
                 StreamARN="ARN", 
                 StartSelector= 
                              {'StartSelectorType':'FRAGMENT_NUMBER',
                               'AfterFragmentNumber': decoded_json_from_stream['InputInformation']['KinesisVideo']['FragmentNumber']
                              }
                                       )

可以使用,

 frame = kvs_stream['Payload'].read()

接收以从有效载荷中获取帧。现在你可以打开一个 mvi 文件并将这个帧写入它,然后使用 openCV 从这个 mvi 文件中提取一个特定的帧。

with open('/tmp/stream.avi', 'wb') as f:
                f.write(frame)
                cap = cv2.VideoCapture(file.mvi)
                #use frame for further processing

可以使用以下代码片段。此外,您可以使用 .read() 方法修改您在一轮中获取的数据以进一步优化。然后您可以根据您的要求制作视频 fname

client = boto3.client('kinesis-video-media', endpoint_url=dataEndPoint)
response = client.get_media(
                    StreamARN=streamARN,
                    StartSelector={
                            'StartSelectorType': 'FRAGMENT_NUMBER',
                            'AfterFragmentNumber': fragmentID}
                    )
fname = '/tmp/'+fragmentID+'-'+serverTimestamp+'.webm'
with open(fname, 'wb+') as f:
    chunk = response['Payload'].read(1024*8)
    while chunk:
        f.write(chunk)
        chunk = response['Payload'].read(1024*8)
return fname