import os import subprocess import time import re from setting import RTMP_URL, CAM_NAME, AUDIO_DEVICE, FONT_PATH # --- 配置参数 --- # 替换为你的 ffmpeg 命令(建议先在终端测试成功) FFMPEG_CMD = [ 'ffmpeg', '-hide_banner', '-thread_queue_size', '2048', '-f', 'video4linux2', '-video_size', '1024x768', '-framerate', '25', '-i', '/dev/video0', '-thread_queue_size', '8192', '-f', 'alsa', '-ac', '1', '-i', AUDIO_DEVICE, '-vcodec', 'libx264', '-acodec', 'aac', '-b:v', '4M', '-b:a', '128K', '-max_delay', '1000000', '-g', '50', '-preset:v', 'ultrafast', '-tune:v', 'zerolatency', '-vf', ( f"drawtext=fontfile={FONT_PATH}:" f"text='{CAM_NAME} | %{{localtime\\:%Y-%m-%d %H\\\\\\:%M\\\\\\:%S}}':" "x=20:y=20:fontsize=28:fontcolor=yellow:shadowcolor=black:shadowx=2:shadowy=2" ), '-f', 'flv', RTMP_URL ] RESTART_DELAY = 5 # 重启间隔(秒) def monitor_stream(): while True: # 杀死所有属于当前用户的 ffmpeg 进程,防止冲突 os.system("pkill -9 ffmpeg > /dev/null 2>&1") print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] 正在启动 FFmpeg 推流...") # 启动进程,将 stderr 重定向以便监控状态 process = subprocess.Popen( FFMPEG_CMD, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, bufsize=1 ) try: # 实时读取 FFmpeg 输出的状态行 while True: line = process.stdout.readline() if not line: break # 监控推流状态(例如抓取 fps 和 bitrate) if "frame=" in line: # 使用正则或字符串切片提取关键信息 stats = re.findall(r'(frame=.*?bitrate=.*?speed=.*?x)', line) if stats: print(f"\r推流中: {stats[0].strip()}", end="") else: print(f"\n[FFmpeg 日志] {line.strip()}") # 检查进程是否意外退出 if process.poll() is not None: break except Exception as e: print(f"\n监控异常: {e}") finally: # 确保彻底杀死进程 if process.poll() is None: process.terminate() try: process.wait(timeout=5) except subprocess.TimeoutExpired: process.kill() print(f"[{time.strftime('%H:%M:%S')}] FFmpeg 进程已结束,{RESTART_DELAY}秒后重启...") time.sleep(RESTART_DELAY) if __name__ == "__main__": try: monitor_stream() except KeyboardInterrupt: print("用户手动停止,程序退出。")