将原始的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,如下所示:

$ python capture.py | ffmpeg -f image2pipe -pix_fmt bgr8 -i -s 640x480 foo.avi

遗憾的是,我不能很好地使用ffmpeg魔法咒语,

失败了<>之前libavutil 50.15。1/50.15。1libavcodec 52.72。2/52.72。2libavformat 52.64。2/52.64。2libavdevice 52。2. 0/52。2. 0libavfilter 1.19。0/1.19。0libswscale 0.11。0/0.11。0libpostproc 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,来自'pipe:'持续时间:无,比特率:无流#0.0:视频:0x0000, bgr8, 25 fps, 25 tbr, 25 tbn, 25 tbcswScaler: 0x0 -> 640x480是无效的缩放尺寸之前
  • 捕获的帧绝对是640x480。
  • 我很确定OpenCV图像类型(IplImage)的像素顺序是GBR,每个通道一个字节。至少,这似乎是来自相机。

我不是ffmpeg专家。有人成功地做到了吗?

花了一堆摆弄,但我找到了使用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将实时输出流式传输到web, 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

我有点晚了,但是我强大的 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获取更多高级应用程序和功能。

希望有帮助!

不确定这是Mac os特定的,还是python3特定的,但我需要将框架转换为字符串,以便为我工作,像这样:

sys.stdout.write(str(frame.tostring()))

花了我一个小时才弄清楚,默认情况下,windows管道不是二进制的。这会导致一些字节(特别是换行符)被修改/省略,并且由于帧大小不是恒定的,因此生成的视频会缓慢移动。

为了解决这个问题,修改后的python文件:
"""
videoCapture.py
"""
import cv2, sys
import time
if sys.platform == "win32":
    import os, msvcrt
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
cap = cv2.VideoCapture(0)                    # 0 is for /dev/video0
while True :
    ret, frm = cap.read()
    sys.stdout.write( frm.tostring() )

要测试原始视频的管道是否成功,使用ffplay。确保指定的帧率高于管道输出的帧率,否则视频将开始延迟

python videoCapture.py | ffplay -f rawvideo -pix_fmt bgr24 -s 640x480 -framerate 40 -i -

如果你传递bgr8 OpenCV帧,你仍然需要在FFmpeg管道中设置-pix_fmt bgr24

相关内容

  • 没有找到相关文章

最新更新