[英]Pipe raw OpenCV images to FFmpeg
這是一個使用 OpenCV 的 python 綁定讀取 web 攝像頭的相當簡單的示例:
'''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() )
現在我想要 pipe output 到 ffmpeg,如下所示:
$ python capture.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 libavformat 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 Output #0, avi, to 'out.avi': Stream #0.0: Video: flv, yuv420p, 640x480, q=2-31, 19660 kb/s, 90k tbn, 30 tbc [image2pipe @ 0x1508640]max_analyze_duration reached [image2pipe @ 0x1508640]Estimating duration from bitrate, this may be inaccurate Input #0, image2pipe, from 'pipe:': Duration: N/A, bitrate: N/A Stream #0.0: Video: 0x0000, bgr8, 25 fps, 25 tbr, 25 tbn, 25 tbc swScaler: 0x0 -> 640x480 is invalid scaling dimension
我不是 ffmpeg 大師。 有沒有人成功地做到了這一點?
花了很多時間,但我使用 FFmpeg rawvideo demuxer解決了這個問題:
python capture.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - foo.avi
由於原始視頻中沒有 header 指定假定的視頻參數,因此用戶必須指定它們才能正確解碼數據:
-framerate
設置輸入視頻幀率。 默認值為 25。-pixel_format
設置輸入視頻像素格式。 默認值為 yuv420p。-video_size
設置輸入視頻大小。 沒有默認值,因此必須明確指定此值。對於高級用戶,這里有一些額外的東西。 同樣的事情,但使用 VLC 到 stream 現場 output 到 web,ZBF2C44E6FC095156FZECB9 格式:BF1
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 stream
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
您可以查看VidGear Docs以獲得更高級的應用程序和功能。
希望有幫助!
我花了一個小時才弄清楚默認情況下,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。 確保您指定的幀速率高於來自 pipe 的幀速率,否則視頻將開始滯后
python videoCapture.py | ffplay -f rawvideo -pix_fmt bgr24 -s 640x480 -framerate 40 -i -
不確定這是 Mac OS 特定的還是 python3 特定的,但我需要將框架轉換為字符串才能為我工作,如下所示:
sys.stdout.write(str(frame.tostring()))
如果你通過bgr8 OpenCV幀,你仍然需要在-pix_fmt bgr24
中設置-pix_fmt bgr24。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.