Ubuntu服务器Python调用ffmpeg推流5分钟中断,Bash运行正常如何解决?
问题原因
你使用subprocess.Popen启动ffmpeg进程时,指定了stdout=subprocess.PIPE和stderr=subprocess.PIPE捕获进程输出,但后续代码从未读取这两个管道的内容。Linux系统的管道默认缓冲区大小有限,ffmpeg运行过程中持续输出的日志会逐步填满缓冲区,缓冲区满后ffmpeg的写操作会被系统阻塞,无法继续发送推流数据,最终导致连接超时中断。
直接在Bash中执行ffmpeg命令时,输出直接打印到终端,不存在缓冲区堆满的问题,因此可以正常运行,该问题和你猜测的网络超时、bufsize参数无关。
修复方案
根据你是否需要留存ffmpeg运行日志,可选择对应方案:
- 方案1:不需要保留ffmpeg输出日志,直接将输出重定向到空设备,关闭管道捕获
修改subprocess.Popen参数即可:
process = subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- 方案2:需要留存ffmpeg日志,新增独立线程读取管道内容,避免缓冲区堆积
完整示例代码如下:
import time import subprocess import os import threading def read_output(pipe): # 循环读取管道内容,可自行修改将内容写入日志文件 for line in iter(pipe.readline, b''): print(line.decode('utf-8', errors='ignore')) if __name__ == "__main__": file = '/root/app2/m4.avi' command = [ 'ffmpeg', '-re', '-nostdin', '-i', file, '-vcodec', 'libx264', '-preset:v', 'medium', '-b:v', '3000k','-maxrate', '10000k','-bufsize', '200000k', '-acodec', 'aac', '-f', 'flv', 'rtmp://live.twitch.tv/app/live______', ] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 启动两个子线程分别读取标准输出和标准错误 threading.Thread(target=read_output, args=(process.stdout,), daemon=True).start() threading.Thread(target=read_output, args=(process.stderr,), daemon=True).start() st=time.time() while time.time()-st<100*60: print(time.time()-st) time.sleep(1)
- 临时缓解方案:给ffmpeg命令添加
-loglevel error参数,仅输出错误级别的日志,减少日志产生量。该方案仅能延长中断时间,无法彻底解决问题。
内容的提问来源于stack exchange,提问作者George Pavlov
相关产品推荐
相关产品推荐

