将视频和数据流同时实时映射到一个子流程管道
我需要在 OpenCV/Python 中同时实时处理视频流和 klvdata 流。我正在使用 FFMPEG 读取文件或流,因为 OpenCV 不保留 klvdata。我使用 subprocess 模块将数据传递给 OpenCV。
我的问题是我不知道如何将视频和 klvdata 同时映射到同一个子进程管道?
我的代码:
#!/usr/bin/env python3
import sys, json, klvdata;
from subprocess import PIPE
import subprocess as sp
import cv2
import numpy
command = ['ffmpeg',
'-i', 'DayFlight.mpg',
'-map', '0:0',
'-map', '0:d',
'-pix_fmt', 'bgr24',
'-c:v', 'rawvideo',
'-an','-sn',
'-f', 'image2pipe', '-',
'-c:d', 'copy',
'-f','data',
]
pipe = sp.Popen(command, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, bufsize=10**8)
while True:
raw_image = pipe.stdout.read(1280*720*3)
image = numpy.fromstring(raw_image, dtype='uint8')
image = image.reshape((720,1280,3))
if image is not None:
cv2.imshow('Video', image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
for packet in klvdata.StreamParser(pipe.stdout):
metadata = packet.MetadataList()
print(metadata)
pipe.stdout.flush()
cv2.destroyAllWindows()
产生以下错误:
Traceback (most recent call last):
File "test_cv.py", line 32, in <module>
metadata = packet.MetadataList()
AttributeError: 'UnknownElement' object has no attribute 'MetadataList'
非常感谢任何帮助。
I need to process the video stream and the klvdata streams simultaneously in real-time in OpenCV/Python. I'm using FFMPEG to read the file or stream as OpenCV does not retain the klvdata. I pass the data to OpenCV with the subprocess module.
My problem is I cannot figure out how to map both the video and klvdata to the same subprocess pipe simultaneously?
My code:
#!/usr/bin/env python3
import sys, json, klvdata;
from subprocess import PIPE
import subprocess as sp
import cv2
import numpy
command = ['ffmpeg',
'-i', 'DayFlight.mpg',
'-map', '0:0',
'-map', '0:d',
'-pix_fmt', 'bgr24',
'-c:v', 'rawvideo',
'-an','-sn',
'-f', 'image2pipe', '-',
'-c:d', 'copy',
'-f','data',
]
pipe = sp.Popen(command, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, bufsize=10**8)
while True:
raw_image = pipe.stdout.read(1280*720*3)
image = numpy.fromstring(raw_image, dtype='uint8')
image = image.reshape((720,1280,3))
if image is not None:
cv2.imshow('Video', image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
for packet in klvdata.StreamParser(pipe.stdout):
metadata = packet.MetadataList()
print(metadata)
pipe.stdout.flush()
cv2.destroyAllWindows()
Produces the below error:
Traceback (most recent call last):
File "test_cv.py", line 32, in <module>
metadata = packet.MetadataList()
AttributeError: 'UnknownElement' object has no attribute 'MetadataList'
Any help is greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了分割视频和数据,我们可以将视频流映射到stderr管道,并将KLV数据流映射到stdout管道。
在我的以下答案中,使用了相同的技术来分离视频和音频。
当每个视频帧都有私有KLV数据(按顺序同步)时,视频帧和相应数据之间的精确同步相对简单。
Day Flight.mpg 示例文件的数据包要少得多比帧,并且使用建议的解决方案不可能实现精确的同步(我认为使用管道方法不可能)。
我们仍然可以应用一些粗略同步 - 假设数据和帧是在时间接近的情况下读取的。
分割视频和数据的建议方法:
视频和数据在两个单独的线程中读取:
根据 Wikipedia,KLV 格式没有明确定义:
在示例视频中,密钥长度为 16 字节,但不能保证...
从 stdout 管道读取 KLV 数据:
当从管道读取数据时(以类似实时的方式),我们需要知道预期读取的字节数。
这迫使我们对 KLV 数据进行部分解析:
读取完密钥、长度和数据后,我们就有了一个“KLV数据包”,我们可以发送到KLV数据解析器。
以下是与
Day Flight.mpg
示例输入文件配合使用的代码示例:上面的代码将数据保存到
data.bin
(用于测试)。data.bin
可用于一致性检查。执行 FFmpeg CLI 提取数据流:
验证
raw.bin
和data.bin
文件是否相同。For splitting the video and data, we may map the video stream to
stderr
pipe and map the KLV data stream to tostdout
pipe.The same technique is used for separating video and audio in my following answer.
Accurate synchronization between the the video frame and the corresponding data is relatively simple when each video frame has private KLV data (synchronize by sequential order).
The Day Flight.mpg sample file has much fewer data packets than frames, and accurate synchronization is not possible using the suggested solution (I don't think it is possible using the pipes approach).
We may still apply some coarse synchronization - assume the data and the frame are read in time proximity.
Suggested way for splitting the video and the data:
The video and the data are read in two separate threads:
According to Wikipedia, the KLV format is not well defined:
In the sample video, the key length is 16 bytes, but it is not guaranteed...
Reading the KLV data from stdout pipe:
When reading data from a pipe (in real-time like manner), we need to know the expected number of bytes to read.
That forces us to do partial parsing of the KLV data:
After reading the key, length and data, we have one "KLV data packet", we can send to the KLV data parser.
Here is a code sample that woks with
Day Flight.mpg
sample input file:The above code saves the data to
data.bin
(for testing).data.bin
may be used for consistency check.Execute FFmpeg CLI for extracting the data stream:
Verify that
raw.bin
anddata.bin
files are equal.