在(扭曲的)定时器内从Popen运行ffmpeg.LoopingCall()暂停



我有一个RTSP流,需要作为HLS重新流式传输。当RTSP流中断时(例如,相机断开连接),我会放一个蓝色屏幕,让用户知道相机脱机了。HLS分段器单独运行,在端口22200上侦听传入的数据包。

在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显示为正在运行,计时器仍在运行(我看到命令行中每隔2秒就会弹出一条"timer TICK"消息。

如果我只是从命令行(而不是从python)运行ffmpeg命令,那么它可以工作几个小时,没有问题。

有人知道扭曲的反应堆是否在拖延这个过程吗?还是子流程。Popen本身的问题?或者计时器本身出现了故障(即使它进入了"监视器"功能)?我有其他定时器也在同一个反应器(同一个线程)中运行,这可能是个问题吗?

发现问题:问题是stderr=subprocess。管道。当ffmpeg运行几分钟时,它会填充管道,并且由于没有ps.communicate()来清除它,因此最终进程会停止。解决此问题的两种最简单方法:

从管道读取输出:

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()

(假设子流程作为sb导入)