簡體   English   中英

在Opencv中處理相機流,並使用FFMPEG將其推送到RTMP(NGINX RTMP模塊)上

[英]Processing Camera stream in Opencv, pushing it over RTMP (NGINX RTMP Module) using FFMPEG

輸出視頻: https : //youtu.be/VxfoBQjoY6E

說明:

我要:在Opencv中處理攝像機流,並將其推送到RTMP服務器。 我已經設置了NGINX(RTMP模塊),並且已經使用RTMP(Flash Player)和HLS測試了流視頻。

我正在循環讀取幀,並在python中使用“子進程”執行ffmpeg命令。 這是我正在使用的命令:

command = [ffmpeg,
    '-y',
    '-f', 'rawvideo',
    '-vcodec','rawvideo',
    '-pix_fmt', 'bgr24',
    '-s', dimension,
    '-i', '-',
    '-c:v', 'libx264',
    '-pix_fmt', 'yuv420p',
    '-preset', 'ultrafast',
    '-f', 'flv',
    'rtmp://10.10.10.80/live/mystream']


import subprocess as sp
...
proc = sp.Popen(command, stdin=sp.PIPE,shell=False)
...
proc.stdin.write(frame.tostring()) #frame is read using opencv

問題:

我可以看到流正常,但是它會凍結並經常恢復。 這是FFMPEG終端日志的輸出:

Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
frame=  117 fps= 16 q=22.0 size=     344kB time=00:00:04.04 bitrate= 697.8kbits/s speed=0.543x   

最后提到速度。 我相信應該接近1倍。 我不確定如何實現這一目標。

而且我與服務器位於同一網絡上,如果需要,我可以發布python代碼。 需要一些ffmpeg專家給我一些建議。

編輯

我輸入的fps實際上是〜3。 使用'-use_wallclock_as_timestamps', '1'我可以在日志中看到速度接近1倍。 但是HLS的直播時間大約有2分鍾的延遲,因此暫停並停止。 克里斯的建議部分起作用。 我不確定問題出在哪里,我開始相信這與nginx-rtmp模塊有關。

這是最終的輸出,左邊是flash,右邊是hls。 我在最后顯示了ffmpeg選項。 https://youtu.be/jsm6XNFOUE4

在流傳輸原始視頻(如您)或從MJPEG來源傳輸視頻時,我遇到過類似的問題。 ffmpeg有兩個輸入選項可以嘗試使其保持1倍的速度:

選項1

ffmpeg -re -i <rest of input options>

-re告訴ffmpeg以本機輸入速率讀取

選項2

ffmpeg -use_wallclock_as_timestamps 1 -i <rest of input options>

-use_wallclock_as_timestamps告訴ffmepg在進入每個幀時僅獲取它們,獲取系統時間,並為其添加時間戳。 我發現當速度降低時,此選項最有效。

不管

確保以恆定幀速率編碼。 當幀率變化時,ffmpeg可能會有點挑剔,因此在輸出選項上,使用-r 25 (將25替換為所需的輸出幀率)來強制ffmpeg使用靜態幀率

我認為最簡單的方法是使用MoviePy模塊(我發現很棒)。 看一下MoviePy Video Writer 它應該寫入本地文件,但是您也可以將其與rtmp流一起使用,方法是在命令末尾添加-f flv以指定輸出格式。 要將幀寫入流,只需使用write_frame(your_frame)方法。 對我來說效果很好

我遇到了同樣的問題,發現ffmpeg無法自動填補空白,因此當您以3 fps的速率喂ffmpeg時,客戶端仍將以25 fps的速度播放,因此客戶端需要先緩存很多幀,然后再播放以高速移動,然后停止再次緩存幀

所以很容易在使用以下代碼填充ffmpeg時填補空白

timeStart = get_time_seconds()
count = 0
some loop:
  frame = getimage()
  targetCount = (get_time_seconds()-timeStart)*25
  repeatCount = targetCount - count
  loop for repeatCount times:
     proc.stdin.write(frame.tostring()) 
  count = targetCount 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM