FFmpeg+Python多摄像头录制时Cam3间歇性无帧输出问题排查
多摄像头FFmpeg录制间歇性空文件问题排查求助
问题背景
通过Python多线程调用FFmpeg同时录制3台摄像头,每段视频时长5秒,录制间隔约25秒。整体流程正常,但摄像头3的录制文件会间歇性生成0时长空文件(无视频帧)。已做排查:
- 排除硬件问题:更换摄像头后问题仍存在
- 调整线程调用顺序、更新FFmpeg至最新静态版均无效
- 录制时CPU、内存占用处于合理范围
核心代码
import os import datetime import subprocess from threading import Thread def take_vid1(path1, video_length, sampleN): dt = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S") save1 = os.path.join(path1, dt+'_1'+sampleN+'.mp4') command = [ffmpeg_path, '-hide_banner', '-y', '-f', 'dshow', '-thread_queue_size', '4096', '-rtbufsize', '500M', '-c:v', 'mjpeg', '-video_size', '1600x896', '-framerate', '30', '-i', 'video='+dev1, '-map', '0', '-t', video_length, save1] sp = subprocess.run(command, capture_output=True, text=True) print(dt + ' vid1 returncode: ' + str(sp.returncode)) def take_vid2(path2, video_length, sampleN): dt = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S") save2 = os.path.join(path2, dt+'_2'+sampleN+'.mp4') command = [ffmpeg_path, '-hide_banner', '-y', '-f', 'dshow', '-thread_queue_size', '4096', '-rtbufsize', '500M', '-c:v', 'mjpeg', '-video_size', '1600x896', '-framerate', '30', '-i', 'video='+dev2, '-map', '0', '-t', video_length, save2] sp = subprocess.run(command, capture_output=True, text=True) print(dt + ' vid2 returncode: ' + str(sp.returncode)) def take_vid3(path3, video_length, sampleN): dt = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S") save3 = os.path.join(path3, dt+'_3'+sampleN+'.mp4') command = [ffmpeg_path, '-hide_banner', '-y', '-f', 'dshow', '-thread_queue_size', '4096', '-rtbufsize', '500M', '-c:v', 'mjpeg', '-video_size', '1600x896', '-framerate', '30', '-i', 'video='+dev3, '-report', '-map', '0', '-t', video_length, save3] sp = subprocess.run(command, capture_output=True, text=True) print(dt + ' vid3 returncode: ' + str(sp.returncode)) # 线程初始化与启动 t1 = Thread(target=take_vid1, args=[cam1Path, video_length,sampleN]) t2 = Thread(target=take_vid2, args=[cam2Path, video_length,sampleN]) t3 = Thread(target=take_vid3, args=[cam3Path, video_length,sampleN]) threads = [t1,t2,t3] if __name__ == '__main__': for t in threads: t.start() for t in threads: t.join()
排查方向与解决建议
- 检查设备初始化延迟:摄像头3可能启动时未及时输出帧,FFmpeg在
-t指定的5秒内未捕获到帧,导致生成空文件。可尝试:- 添加
-stimeout 5000000参数(设置5秒超时,超时未收到帧则报错,避免生成空文件) - 给摄像头3的线程增加启动延迟,比如
t3.start()前执行time.sleep(0.3),避开多设备同时初始化的资源竞争
- 添加
- 调整FFmpeg输入参数:
- 增大
-thread_queue_size至8192,避免队列溢出导致丢帧 - 移除
-c:v mjpeg参数,让FFmpeg自动协商输入格式,部分摄像头在强制mjpeg模式下启动较慢 - 添加
-fflags +genpts,强制生成时间戳,避免无有效帧时文件结构异常
- 增大
- 捕获错误输出:修改摄像头3的代码,打印FFmpeg的stderr内容,定位具体错误:
print(dt + ' vid3 stderr: ' + sp.stderr) - 单线程测试:单独用线程录制摄像头3,测试是否仍会生成空文件,排除多线程资源竞争的影响
- 检查系统层面问题:尝试更换摄像头3的USB端口,更新摄像头驱动,排查Windows设备权限或USB供电不足的问题
- 分析失败日志:查看FFmpeg报告中是否存在
dshow: No video frames captured等关键错误,确认是设备未输出帧还是FFmpeg处理逻辑问题
内容的提问来源于stack exchange,提问作者RCam
相关产品推荐
相关产品推荐

