【发布时间】:2021-10-26 18:01:25
【问题描述】:
我想从磁盘上的 H264 流中提取 JPEG 帧。提取需要尽可能快以满足我的实时要求。
到目前为止,我一直在使用ffmpeg-python lib,它只是ffmpeg 的python 包装器。这是一个代码sn-p:
out, _ = (
ffmpeg
.input('./5sec.h264')
.filter('select', 'gte(n,{})'.format(144))
.output('pipe:', vframes=1, format='image2', vcodec='h264')
.run(capture_stdout=True)
)
这会将 jpeg 输出到标准输出,通过一些努力我可以将其读入我的程序中。
但是,随着我使用越来越大的流文件,获取 JPEG 的提取时间会增加。我认为查找时间会保持不变,因为 ffmpeg 已高度优化?
是否有固定时间的解决方案从磁盘上的 h264(甚至 mjpeg)格式流中查找和返回帧?
编辑:
这是我在没有 python 包装器的情况下使用的命令:
ffmpeg -i 5sec.h264 -frames:v 1 -filter:v "select=gte(n\,25)" -f image2 frame.jpg
这里是输出:
ffmpeg version 4.1.6-1~deb10u1+rpt2 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 8 (Raspbian 8.3.0-6+rpi1)
configuration: --prefix=/usr --extra-version='1~deb10u1+rpt2' --toolchain=hardened --incdir=/usr/include/arm-linux-gnueabihf --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-omx-rpi --enable-mmal --enable-neon --enable-rpi --enable-vout-drm --enable-v4l2-request --enable-libudev --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared --libdir=/usr/lib/arm-linux-gnueabihf --cpu=arm1176jzf-s --arch=arm
libavutil 56. 22.100 / 56. 22.100
libavcodec 58. 35.100 / 58. 35.100
libavformat 58. 20.100 / 58. 20.100
libavdevice 58. 5.100 / 58. 5.100
libavfilter 7. 40.101 / 7. 40.101
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 3.100 / 5. 3.100
libswresample 3. 3.100 / 3. 3.100
libpostproc 55. 3.100 / 55. 3.100
Input #0, h264, from '5sec.h264':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p(progressive), 640x480, 25 fps, 25 tbr, 1200k tbn, 50 tbc
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (native))
Press [q] to stop, [?] for help
[swscaler @ 0x1a25390] deprecated pixel format used, make sure you did set range correctly
Output #0, image2, to 'frame.jpg':
Metadata:
encoder : Lavf58.20.100
Stream #0:0: Video: mjpeg, yuvj420p(pc), 640x480, q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc
Metadata:
encoder : Lavc58.35.100 mjpeg
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
frame= 1 fps=0.4 q=6.8 Lsize=N/A time=00:00:01.04 bitrate=N/A speed=0.467x
video:63kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
注意,实现的 FPS 为 0.4。当我将请求的帧增加到第 125 帧而不是第 25 帧时,FPS 下降到 0.1。
【问题讨论】:
-
暂时忘记包装器,直到您首先获得普通的 ffmpeg 工作。显示正在执行的实际 ffmpeg 命令,并复制并粘贴 ffmpeg 日志中的所有文本。
-
好的,现在包括这些。
-
当输入视频是原始 h264 流时,我认为您无法获得恒定的时间。这是因为原始 h264 流是不可搜索(例如:您不能使用
ffmpeg -ss 00:00:03 -i 5sec.h264... 搜索到第三秒并从那里开始提取帧)。因此,FFmpeg 会读取从文件开头到所需帧的所有帧。使用像5sec.mp4这样的容器我可以解决它。但是快速搜索只针对一个关键帧,所以你这取决于输入的“GOP大小”。 -
我使用以下命令将 5sec 转换为 .mp4:
ffmpeg -framerate 25 -i 5sec.h264 -c copy 5sec.mp4在 mp4 文件上使用我原来的 ffmpeg 命令会产生相同的查找时间到第 125 帧:ffmpeg -i 5sec.mp4 -frames:v 1 -filter:v "select=gte(n\,25)" -f image2 frame2.jpg。还是很慢!
标签: python ffmpeg video-streaming video-processing h.264