2014-02-11 44 views
0

我有一個RTSP流,我需要重新流爲HLS。當RTSP數據流出現故障時(例如,攝像機斷開),我放置一個藍屏,讓用戶知道攝像機已脫機。 HLS分段器單獨運行,在端口22200上偵聽傳入數據包。從Popen內部(扭曲)timer.LoopingCall()失速運行ffmpeg

在Python代碼本質歸結爲:

import psutil, subprocess as sb 
from twisted.internet import reactor, task 
from cameraControls import camStatus, camURL 
ffOn = False 
psRef = False 
def monitor(): 
print "TIMER TICK" 
if camStatus()=='ON' and not ffOn: #camera just came online 
    cmd = ["ffmpeg", "-i", camURL, "-codec", "copy", "-f", "mpegts", "udp://127.0.0.1:22200"] 
    ps = sb.Popen(cmd,stderr=sb.PIPE) 
    psRef=ps 
#check the stream: 
psmon = psutil.Process(psRef.pid) 
if psmon.status!=psutil.STATUS_RUNNING: 
    print "FFMPEG STOPPED" 

tmr = task.LoopingCall(monitor) 
tmr.start(2) 
reactor.run() 

正常工作5-6分鐘,然後我看到視頻失速,如果我檢查的ffmpeg的CPU使用率它顯示0, ffmpeg輸出不會改變,就像暫停一樣。但是psmon.status顯示爲正在運行,並且計時器仍在運行(我在命令行中看到「TIMER TICK」消息每2秒鐘彈出一次)

如果我只是從命令行運行ffmpeg命令python)然後它工作幾個小時沒有問題

確實有人知道,如果扭曲的反應堆是拖延進程嗎?或者它是子進程.Popen本身的問題?或計時器本身有問題(即使它得到'監視'功能)?我有其他定時器也運行在同一個reactor(相同的線程),這可能是一個問題嗎?

回答

0

發現問題:問題是stderr = subprocess.PIPE。當ffmpeg運行幾個分鐘,它fi放棄了管道,並且由於沒有ps.communicate()來清除它,所以最終這個過程停滯不前。解決這個 2最簡單的方法:

讀取來自管的輸出:

ps = subprocess.Popen(cmd,stderr=sb.PIPE)  
ps.communicate() 

或所有的輸出發送到/ dev/null的:

devnul = open(os.devnull,"w") #this is multiplatform, rather than hardocding "/dev/null" 
ps = sb.Popen(cmd,stderr=devnul) 
#.... 
#some other code here, eventually kill the process maybe 
#.... 
devnul.close() 

(假設子被導入爲某人)