You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派中使用FFmpeg同时录制双摄像头的Python脚本故障及画面拼接报错问题

解决树莓派上FFmpeg双摄像头录制的两个问题

让我们一步步拆解并解决你遇到的这两个问题:

问题1:同时启动两个FFmpeg子进程无法正常运行

同时启动两个FFmpeg进程失败,大概率是树莓派的硬件资源限制(USB带宽、CPU性能)或者子进程执行方式导致的,给你几个可行的优化方案:

1. 优化USB带宽与摄像头参数

树莓派的USB总线带宽有限,两个USB摄像头同时高分辨率/高帧率录制很容易占满带宽。你可以:

  • 给每个FFmpeg命令添加分辨率和帧率限制,降低资源消耗:
    ffmpeg -nostdin -i /dev/video0 -s 640x480 -framerate 15 -c:v copy -an -sn -dn -segment_time 30 -f segment path1/%03d.avi
    
  • 如果树莓派有分开的USB接口组(比如USB2和USB3),把两个摄像头插在不同组的接口上,避免带宽冲突。

2. 改进子进程调用方式

你当前用shell=True执行命令,不仅不安全,还可能因为shell解析问题导致意外阻塞。建议改用列表形式传递命令参数,同时处理FFmpeg的输出缓冲区:

import os
import datetime
import subprocess

ROOT_PATH = os.getenv("ROOT_PATH", "/home/pi")
ENCODING = os.getenv("ENCODING", "copy")
new_dir = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")

RECORDINGS_PATH1 = os.getenv("RECORDINGS_PATH", "RecordingsCam1")
RECORDINGS_PATH2 = os.getenv("RECORDINGS_PATH", "RecordingsCam2")
recording_path1 = os.path.join(ROOT_PATH, RECORDINGS_PATH1, new_dir)
recording_path2 = os.path.join(ROOT_PATH, RECORDINGS_PATH2, new_dir)

# 用makedirs并设置exist_ok=True,避免目录已存在报错
os.makedirs(recording_path1, exist_ok=True)
os.makedirs(recording_path2, exist_ok=True)

segments_path1 = os.path.join(recording_path1, "%03d.avi")
segments_path2 = os.path.join(recording_path2, "%03d.avi")

# 用列表形式定义命令,避免shell=True的安全隐患与解析问题
cmd1 = [
    "ffmpeg", "-nostdin", "-i", "/dev/video0",
    "-c:v", ENCODING, "-an", "-sn", "-dn",
    "-segment_time", "30", "-f", "segment", segments_path1,
    "-loglevel", "error"  # 减少日志输出,避免缓冲区阻塞
]

cmd2 = [
    "ffmpeg", "-nostdin", "-i", "/dev/video2",
    "-c:v", ENCODING, "-an", "-sn", "-dn",
    "-segment_time", "30", "-f", "segment", segments_path2,
    "-loglevel", "error"
]

# 重定向输出到DEVNULL,避免缓冲区满导致进程阻塞
proc1 = subprocess.Popen(cmd1, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
proc2 = subprocess.Popen(cmd2, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

# 如果需要等待录制结束,可以添加 proc1.wait() 和 proc2.wait()

3. 降低FFmpeg资源占用

给FFmpeg添加线程限制,避免两个进程抢占过多CPU资源:

# 在cmd1和cmd2末尾添加线程限制参数
cmd1.extend(["-threads", "1"])
cmd2.extend(["-threads", "1"])

问题2:画面并排时出现Filtering and streamcopy cannot be used together报错

这个错误的逻辑很清晰:当使用滤镜(比如hstack/vstack拼接画面)时,不能用-c:v copy参数。因为copy是直接复制原始视频流,不做任何编码处理;而滤镜需要修改视频帧,必须重新编码视频。

解决方案:替换为实际的视频编码器

把-c:v copy改成树莓派支持的编码器,优先用硬件加速编码器(效率更高),比如h264_v4l2m2m,也可以用软件编码器libx264。

这里给你一个双画面并排录制的Python示例:

import os
import datetime
import subprocess

ROOT_PATH = os.getenv("ROOT_PATH", "/home/pi")
new_dir = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
RECORDINGS_PATH = os.getenv("RECORDINGS_PATH", "RecordingsCombined")
recording_path = os.path.join(ROOT_PATH, RECORDINGS_PATH, new_dir)
os.makedirs(recording_path, exist_ok=True)
segments_path = os.path.join(recording_path, "%03d.avi")

# 使用hstack滤镜水平拼接两个摄像头画面,用树莓派硬件加速编码
cmd = [
    "ffmpeg", "-nostdin",
    "-i", "/dev/video0", "-i", "/dev/video2",
    "-filter_complex", "[0:v][1:v]hstack=inputs=2[v]",  # hstack水平拼接,vstack为垂直拼接
    "-map", "[v]",
    "-c:v", "h264_v4l2m2m",  # 树莓派硬件H.264编码器,大幅降低CPU占用
    "-preset", "ultrafast",
    "-crf", "23",  # 控制视频质量,值越小质量越高(18-28是合理范围)
    "-an", "-sn", "-dn",
    "-segment_time", "30", "-f", "segment", segments_path,
    "-loglevel", "error"
]

proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

关键说明:

  • 如果硬件编码h264_v4l2m2m出现兼容性问题,可以改用软件编码器libx264,但要保留-preset ultrafast参数提升编码速度。
  • 滤镜参数hstack=inputs=2支持调整拼接比例,比如hstack=inputs=2:shortest=1可以让输出时长和较短的视频流一致。

内容的提问来源于stack exchange,提问作者user11614098

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:47:43