OpenCV处理RTSP流推RTMP时subprocess写入报Broken pipe错误如何解决
问题原因与解决方案
核心错误原因
你当前使用的-c copy是流复制模式,仅适合直接转发已编码的视频流,不能处理OpenCV输出的原始未编码帧。FFmpeg无法识别你通过stdin传入的原始BGR像素数据,直接异常退出,导致写入管道时报Broken pipe错误。
需要修改的配置
- 调整FFmpeg启动参数,明确指定输入原始帧的格式、分辨率、帧率等信息,替换流复制模式为实时编码模式
- 调整帧处理逻辑顺序,先判断帧读取是否成功,再执行后续处理操作
修改后的完整代码
import sys import subprocess import cv2 rtmp_url = "rtmp://127.0.0.1:1935/live/test" cap = cv2.VideoCapture("rtsp://10.0.1.7/media.sdp") # 采集视频信息用于ffmpeg配置 fps = int(cap.get(cv2.CAP_PROP_FPS)) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 修正后的ffmpeg命令:明确输入格式为原始bgr24帧,编码为h264输出flv command = [ 'ffmpeg', '-y', # 自动覆盖输出 '-f', 'rawvideo', '-vcodec','rawvideo', '-pix_fmt', 'bgr24', # OpenCV默认像素格式 '-s', f'{width}x{height}', # 分辨率 '-r', str(fps), # 帧率 '-i', '-', # 从stdin读取输入 '-c:v', 'libx264', # 用h264编码 '-pix_fmt', 'yuv420p', # 兼容RTMP的像素格式 '-preset', 'veryfast', # 编码速度优先,降低延迟 '-f', 'flv', rtmp_url ] p = subprocess.Popen(command, stdin=subprocess.PIPE, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) font = cv2.FONT_HERSHEY_SIMPLEX while cap.isOpened(): ret, frame = cap.read() # 先判断帧读取是否成功 if not ret: print("frame read failed") break # 叠加水印 cv2.putText(frame, 'TEXT ON VIDEO', (50, 50), font, 1, (0, 255, 255), 2, cv2.LINE_4) # 本地预览 cv2.imshow('video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # 写入ffmpeg子进程 try: p.stdin.write(frame.tobytes()) except Exception as e: print(e) break cap.release() cv2.destroyAllWindows() p.stdin.close() p.wait()
额外说明
如果需要排查FFmpeg端的报错,可以把启动参数里的stderr=subprocess.DEVNULL改成stderr=subprocess.PIPE,再读取FFmpeg的错误日志定位问题。
内容的提问来源于stack exchange,提问作者Vamsi
相关产品推荐
相关产品推荐

