picam.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import os
  2. import subprocess
  3. import time
  4. import re
  5. from setting import RTMP_URL
  6. from setting import CAM_NAME
  7. FONT_PATH = "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc"
  8. cam_name=CAM_NAME
  9. push_url=RTMP_URL
  10. # --- 配置参数 ---
  11. # 替换为你的 ffmpeg 命令(建议先在终端测试成功)
  12. FFMPEG_CMD = [
  13. 'ffmpeg',
  14. '-hide_banner',
  15. '-thread_queue_size', '2048',
  16. '-f', 'video4linux2',
  17. '-video_size', '1024x768',
  18. '-framerate', '25',
  19. '-i', '/dev/video0',
  20. '-thread_queue_size', '8192',
  21. '-f', 'alsa',
  22. '-ac', '1',
  23. '-i', 'hw:1,0',
  24. '-vcodec', 'libx264',
  25. '-acodec', 'aac',
  26. '-b:v', '4M',
  27. '-b:a', '128K',
  28. '-max_delay', '1000000',
  29. '-g', '50',
  30. '-preset:v', 'ultrafast',
  31. '-tune:v', 'zerolatency',
  32. '-vf', (
  33. f"drawtext=fontfile={FONT_PATH}:"
  34. f"text='{cam_name} | %{{localtime\\:%Y-%m-%d %H\\\\\\:%M\\\\\\:%S}}':"
  35. "x=20:y=20:fontsize=28:fontcolor=yellow:shadowcolor=black:shadowx=2:shadowy=2"
  36. ),
  37. '-f', 'flv',
  38. push_url
  39. ]
  40. RESTART_DELAY = 5 # 重启间隔(秒)
  41. def monitor_stream():
  42. while True:
  43. # 杀死所有属于当前用户的 ffmpeg 进程,防止冲突
  44. os.system("pkill -9 ffmpeg > /dev/null 2>&1")
  45. print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] 正在启动 FFmpeg 推流...")
  46. # 启动进程,将 stderr 重定向以便监控状态
  47. process = subprocess.Popen(
  48. FFMPEG_CMD,
  49. stdout=subprocess.PIPE,
  50. stderr=subprocess.STDOUT,
  51. universal_newlines=True,
  52. bufsize=1
  53. )
  54. try:
  55. # 实时读取 FFmpeg 输出的状态行
  56. while True:
  57. line = process.stdout.readline()
  58. if not line:
  59. break
  60. # 监控推流状态(例如抓取 fps 和 bitrate)
  61. if "frame=" in line:
  62. # 使用正则或字符串切片提取关键信息
  63. stats = re.findall(r'(frame=.*?bitrate=.*?speed=.*?x)', line)
  64. if stats:
  65. print(f"\r推流中: {stats[0].strip()}", end="")
  66. # 检查进程是否意外退出
  67. if process.poll() is not None:
  68. break
  69. except Exception as e:
  70. print(f"\n监控异常: {e}")
  71. finally:
  72. # 确保彻底杀死进程
  73. if process.poll() is None:
  74. process.terminate()
  75. try:
  76. process.wait(timeout=5)
  77. except subprocess.TimeoutExpired:
  78. process.kill()
  79. print(f"[{time.strftime('%H:%M:%S')}] FFmpeg 进程已结束,{RESTART_DELAY}秒后重启...")
  80. time.sleep(RESTART_DELAY)
  81. if __name__ == "__main__":
  82. try:
  83. monitor_stream()
  84. except KeyboardInterrupt:
  85. print("用户手动停止,程序退出。")