我正在使用python来做一些基本的图像处理,并想扩展它来逐帧处理视频。
我从一个服务器上获取了一个blob格式的视频-- .webm编码--并将其作为一个字节字符串(b'\x1aE\xdf\xa3\xa3B\x86\x81\x01B\xf7\x81\x01B\xf2\x81\x04B\xf3\x81\x08B\x82\x88matroskaB\x87\x81\x04B\x85\x81\x02\x18S\x80g\x01\xff\xff\xff\xff\xff\xff\xff\x15I\xa9f\x99*\xd7\xb1\x83\x0fB@M\x80\x86ChromeWA\x86Chrome\x16T\xaek\xad\xae\xab\xd7\x81\x01s\xc5\x87\x04\xe8\xfc\x16\t^\x8c\x83\x81\x01\x86\x8fV_MPEG4/ISO/AVC\xe0\x88\xb0\x82\x02\x80\xba\x82\x01\xe0\x1fC\xb6u\x01\xff\xff\xff\xff\xff\xff ...
)保存在python中。
我知道有cv.VideoCapture
,它几乎可以完成我所需要的。问题是我必须先将文件写入磁盘,然后再加载它。将字符串 Package 到IOStream中,并将其馈送到某个进行解码的函数中,看起来会更干净。
在python中有没有一种干净的方法来完成这一任务,或者是写入磁盘并再次加载它才是可行的方法?
3条答案
按热度按时间6psbrbz91#
根据this帖子,您不能使用
cv.VideoCapture
在内存流中进行解码。您可以通过“管道”将流解码为FFmpeg。
解决方案有点复杂,而写入磁盘要简单得多,而且可能是更干净的解决方案。
我正在发布一个使用FFmpeg(和FFprobe)的解决方案。
有针对FFmpeg的Python绑定,但解决方案是使用subprocess模块将FFmpeg作为外部应用程序执行。
(The Python绑定在FFmpeg上运行良好,但到FFprobe的管道却不行)。
我使用的是Windows 10,我将
ffmpeg.exe
和ffprobe.exe
放在执行文件夹中(您也可以设置执行路径)。对于Windows,请下载最新的(静态喜欢的)稳定版本。
我创建了一个独立的示例,它执行以下操作:
如果事先知道解决方案,您可以跳过此部分。
FFprobe的管道使解决方案比它应该具有的更复杂。
stdin
进行解码,并从stdout
管道读取解码后的原始帧。写入
stdin
使用Python线程分块完成。(The使用
stdin
和stdout
而不是命名管道的原因是为了与Windows兼容)。管道架构:
代码如下:
备注:
例如(在Linux中):
'/usr/bin/ffmpeg -i pipe: -f rawvideo -pix_fmt bgr24 -an -sn pipe:'
cyej8jka2#
在Rotem写下答案两年后,现在有一种更干净/更简单的方法使用ImageIO来完成此任务。
ffmpeg
,您可以使用以下命令生成测试视频以尝试此示例:ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30 testsrc.webm
*要使用它,您需要ffmpeg后端(它实现了一个类似于Rotem所提出的解决方案):
pip install imageio[ffmpeg]
在回应Rotem的评论有点解释:
上面的代码片段使用
imageio==2.16.0
。v3 API是一个即将推出的面向用户的API,它简化了阅读操作。该API从imageio==2.10.0
开始可用,但是,在2.16.0之前的版本中,您必须使用import imageio as iio
,并使用iio.v3.imiter
和iio.v3.imread
。读取视频字节的能力已经永远存在了(〉5年,而且还在计数),但(正如我刚刚意识到的)从来没有直接记录下来...所以我很快就会为此添加一个PR ™:)
在ImageIO(v2 API)的旧版本(在v2.9.0上测试)上,您仍然可以读取视频字节字符串;但是,这稍微有点冗长:
watbbzwu3#
有一种Python方法可以通过使用
decord
包来完成此操作。您可以在decord github repo中了解有关
decord
的更多信息。您可以在mmaction repo中了解有关视频IO的更多信息。请参阅
DecordInit
了解如何使用decord IO。