如何将MKV字节读取为视频?

4

我收到了MKV视频的一部分字节数据。我需要提取其中的第一帧,以供后续处理,但不需要将整个视频保存到磁盘中。对于类似的图像问题,我使用OpenCV或PIL,一切都很好,但是我无法在视频数据上使用相同的方法。您有什么提示可以将视频从字节中读入内存对象中,以便我可以在以后使用OpenCV或其他库进行处理?


我在读取MKV文件时也遇到了问题。我已经发起了一个单独的线程(https://dev59.com/P7noa4cB1Zd3GeqPJRH2)。 - Varun_Rathinam
2个回答

6

由于我没有你的 bytes 缓存,我只是用 ffmpeg 创建了一个 MKV 视频文件,像这样:

ffmpeg -i SomeVideo.avi -f matroska -vcodec libx264 video.mkv

然后我使用以下命令安装了imageio

pip install imageio

然后我将整个MKV视频加载到内存中,所以我有一个看起来几乎与您在变量content中接收的bytes对象相同的东西:

import imageio

# Get bytes of MKV video
with open('video.mkv', 'rb') as file: 
    content = file.read()

现在我应该已经设置好了,看起来和你一样。作为参考,content 的前几个字节如下:

b'\x1aE\xdf\xa3\x01\x00\x00\x00\x00\x00\x00#B\x86\x81\x01B\xf7\x81\x01'

那么,让我们继续。

# Wrap the content in a BytesIO and get an ffmpeg reader to read it 
vid = imageio.get_reader(BytesIO(content),  'ffmpeg')

我现在可以像这样打印每个帧的平均值:
for num, image in enumerate(vid.iter_data()): 
    print(image.mean())

或者获取元数据并按以下方式打印:
metadata = vid.get_meta_data()                                                             

print(metadata)

{'plugin': 'ffmpeg',
 'nframes': 750,
 'ffmpeg_version': '4.1 built with Apple LLVM version 10.0.0 (clang-1000.11.45.5)',
 'fps': 25.0,
 'source_size': (1280, 720),
 'size': (1280, 720),
 'duration': 30.0}

关键词: Python, 视频, 帧, 单帧, FFmpeg, imageio, 单独帧, BytesIO, 字节, MKV, Matroska。


1
很高兴它对你起作用了。祝你的项目好运,记住,提问(和回答)是免费的,所以如果你遇到困难,随时回来问吧。 - Mark Setchell
[matroska,webm @ 0x562fad8b1cc0] 文件过早结束 [matroska,webm @ 0x562fad8b1cc0] 找不到流0(视频:h264,none,1280x720)的编解码器参数:未指定像素格式 请考虑增加“analyzeduration”和“probesize”选项的值 - Varun_Rathinam
流映射: 流#0:0 -> #0:0 (h264 (native) -> rawvideo (native)) 按[q]停止,[?]获取帮助 无法在EOF后确定输入流0:0的格式 标记过滤器为完成时出错 转换失败! - Varun_Rathinam
以上错误是因为我读取了一个MKV字节图像imageio.get_reader(BytesIO(content), 'ffmpeg')。这只适用于视频文件吗? - Varun_Rathinam
1
@Varun_Rathinam 如果你有问题,请以正常的方式提问。这是免费的。如果你想展示两个问题之间的关系,可以在此问题下点击“分享”并添加一个链接到你的新问题。 - Mark Setchell
我有一个单独的问题。你能帮忙回答这个问题吗?(https://dev59.com/P7noa4cB1Zd3GeqPJRH2) - Varun_Rathinam

0

Mark Setchell说得没错,但是在2022年,你不必再一路降到get_reader来完成这个操作了。

设置:

创建一个测试视频:

ffmpeg -f lavfi -i testsrc -t 5 testsrc.mkv

创建一个MKV字节字符串
from pathlib import Path

mkv_bytes = Path("testsrc.mkv").read_bytes()

读取第一帧:

ImageIO<2.15.0

import imageio as iio

req = iio.core.Request(mkv_bytes, "r")

# note: this is a bit of a hack, see
# https://github.com/imageio/imageio/issues/686
req._extension = ".mkv"

first_frame = iio.imread(req)

ImageIO>2.15.0(本周发布 - W6 2022)

import imageio as iio

first_frame = iio.v3.imread(mkv_bytes, format_hint=".mkv")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接