将原始 OpenCV 图像通过管道传输到 FFmpeg

新手上路,请多包涵

这是一个使用 OpenCV 的 python 绑定读取网络摄像头的相当简单的示例:

 '''capture.py'''
import cv, sys
cap = cv.CaptureFromCAM(0)                    # 0 is for /dev/video0
while True :
    if not cv.GrabFrame(cap) : break
    frame = cv.RetrieveFrame(cap)
    sys.stdout.write( frame.tostring() )

现在我想将输出通过管道传输到 ffmpeg,如下所示:

 $ 蟒蛇捕获.py | ffmpeg -f image2pipe -pix_fmt bgr8 -i - -s 640x480 foo.avi

可悲的是,我无法完全正确地使用 ffmpeg 魔法咒语并且它失败了

  libavutil 50.15。 1 / 50.15。 1个
  libavcodec 52.72。 2 / 52.72。 2个
  libav 格式 52.64。 2 / 52.64。 2个
  libavdevice 52. 2. 0 / 52. 2. 0
  libavfilter 1.19。 0 / 1.19。 0
  libswscale 0.11。 0 / 0.11。 0
  libpostproc 51. 2. 0 / 51. 2. 0
将 #0,avi 输出到“out.avi”:
    流 #0.0:视频:flv、yuv420p、640x480、q=2-31、19660 kb/s、90k tbn、30 tbc
[image2pipe @ 0x1508640]达到max_analyze_duration
[image2pipe @ 0x1508640]根据比特率估计持续时间,这可能不准确
输入 #0,image2pipe,来自“管道:”:
  持续时间:N/A,比特率:N/A
    流 #0.0:视频:0x0000、bgr8、25 fps、25 tbr、25 tbn、25 tbc
swScaler:0x0 -> 640x480 是无效的缩放维度

  • 捕获的帧肯定是 640x480。
  • 我很确定 OpenCV 图像类型 (IplImage) 的像素顺序是 GBR,每个通道一个字节。至少,这似乎是从相机里出来的。

我不是 ffmpeg 专家。有没有人成功地做到了这一点?

原文由 BrianTheLion 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

花了很多时间,但我使用 FFmpeg rawvideo demuxer 解决了这个问题:

 python capture.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - foo.avi

由于原始视频中没有标头指定假定的视频参数,因此用户必须指定它们才能正确解码数据:

  • -framerate 设置输入视频帧率。默认值为 25。
  • -pixel_format 设置输入视频像素格式。默认值为 yuv420p。
  • -video_size 设置输入视频大小。没有默认值,因此必须明确指定此值。

对于高级用户来说,这里有一些额外的东西。同样的事情,但使用 VLC 将实时输出流式传输到网络,Flash 格式:

 python capture.py | cvlc --demux=rawvideo --rawvid-fps=30 --rawvid-width=320 --rawvid-height=240  --rawvid-chroma=RV24 - --sout "#transcode{vcodec=h264,vb=200,fps=30,width=320,height=240}:std{access=http{mime=video/x-flv},mux=ffmpeg{mux=flv},dst=:8081/stream.flv}"

编辑:使用 ffmpeg 和 ffserver 创建一个 webm 流

python capture.py | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 640x480 -framerate 25 -i - http://localhost:8090/feed1.ffm

原文由 BrianTheLion 发布,翻译遵循 CC BY-SA 3.0 许可协议

我有点晚了,但是我强大的 VidGear Python 库 可以在任何平台上自动将 OpenCV 帧流水线化到 FFmpeg 中。这是一个基本的 python 示例:

 # import libraries
from vidgear.gears import WriteGear
import cv2

output_params = {"-vcodec":"libx264", "-crf": 0, "-preset": "fast"} #define (Codec,CRF,preset) FFmpeg tweak parameters for writer

stream = cv2.VideoCapture(0) #Open live webcam video stream on first index(i.e. 0) device

writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params) #Define writer with output filename 'Output.mp4'

# infinite loop
while True:

    (grabbed, frame) = stream.read()
    # read frames

    # check if frame empty
    if not is grabbed:
        #if True break the infinite loop
        break


    # {do something with frame here}
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # write a modified frame to writer
    writer.write(gray)

    # Show output window
    cv2.imshow("Output Frame", frame)

    key = cv2.waitKey(1) & 0xFF
    # check for 'q' key-press
    if key == ord("q"):
        #if 'q' key-pressed break out
        break

cv2.destroyAllWindows()
# close output window

stream.release()
# safely close video stream
writer.close()
# safely close writer

来源: https ://abhitronix.github.io/vidgear/latest/gears/writegear/compression/usage/#using-compression-mode-with-opencv

您可以查看 VidGear Docs 以获得更高级的应用程序和功能。

希望有帮助!

原文由 abhiTronix 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题