【问题标题】:How to read MKV bytes as video?如何将 MKV 字节读取为视频?
【发布时间】:2019-07-10 14:27:43
【问题描述】:

我正在接收以字节为单位的 MKV 视频片段。我需要在不将视频保存在磁盘中的情况下拍摄第一帧以供以后处理。对于图像的类似问题,我使用 OpenCV 或 PIL 并且一切正常,但是,我无法对视频数据执行相同的操作。有什么技巧可以将视频从字节读取到内存对象,以便以后使用 OpenCV 或其他库进行处理?

【问题讨论】:

标签: python opencv video-encoding mkv


【解决方案1】:

由于我没有您的 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。

【讨论】:

  • 我很高兴它对你有用。祝你的项目好运,记住,问题(和答案)是免费的,所以如果你遇到困难,请回来。
  • [matroska,webm @ 0x562fad8b1cc0] 文件提前结束 [matroska,webm @ 0x562fad8b1cc0] 找不到流 0 的编解码器参数(视频:h264,无,1280x720):未指定的像素格式 考虑增加值对于“analyzeduration”和“probesize”选项
  • 流映射:Stream #0:0 -> #0:0 (h264 (native) -> rawvideo (native)) 按 [q] 停止,[?] 寻求帮助 无法确定格式输入流 0:0 后 EOF 错误将过滤器标记为已完成转换失败!
  • 当我读取 MKV 字节图像 imageio.get_reader(BytesIO(content), 'ffmpeg') 时出现上述错误。或者这仅适用于视频文件
  • @Varun_Rathinam 如果您有问题,请以正常方式提问。免费。如果您想显示两个问题之间的关系,可以单击此问题下的share,并添加指向新问题的链接。
【解决方案2】:

马克·塞切尔说得对;不过 - 在 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

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")

【讨论】:

    猜你喜欢
    • 2020-06-22
    • 2021-08-15
    • 2018-03-20
    • 2020-07-27
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    相关资源
    最近更新 更多