0

我有一个 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 命令,那么它可以工作几个小时没问题。

有人知道扭曲的反应堆是否正在停止这个过程吗?还是 subprocess.Popen 本身的问题?或者计时器本身以某种方式出现故障(即使它进入了“监控”功能)?我有其他计时器也在同一个反应器(同一个线程)中运行,这可能是一个问题吗?

4

1 回答 1

0

发现问题:问题是stderr=subprocess.PIPE。当 ffmpeg 运行几分钟时,它会填满管道,并且由于没有 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()

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

于 2014-02-14T14:52:34.223 回答