Python从MQTT接收JPG帧转RTSP流报错问题排查
问题分析与解决方案
错误原因
你遇到的CAP_IMAGES: can't find starting number错误,本质是OpenCV默认的VideoWriter不支持直接向RTSP服务器推流。它会把你传入的RTSP URL误判为图片序列的文件名模板(比如img_%03d.jpg这种带编号的格式),自然找不到起始编号而报错。
解决步骤
1. 确认环境依赖
- 安装带FFmpeg支持的OpenCV:如果用pip安装,优先选择
opencv-python-headless,或确保编译OpenCV时包含FFmpeg模块。 - 确认RTSP服务器(如rtsp-simple-server)已正常启动并监听
8554端口。
2. 修改VideoWriter配置
必须指定FFmpeg作为后端,并添加RTSP推流的必要参数,同时统一帧尺寸(你的代码中初始帧尺寸与VideoWriter设置的(640,480)不匹配,会导致写入失败)。
3. 修改后的完整代码
import base64 import cv2 as cv import numpy as np import paho.mqtt.client as mqtt MQTT_BROKER = "0.0.0.0" MQTT_PORT = 15883 MQTT_RECEIVE = "test/cam" # 初始化帧尺寸与实际接收帧保持一致 frame = np.zeros((240, 320, 3), np.uint8) frame_width, frame_height = frame.shape[1], frame.shape[0] size = (frame_width, frame_height) # RTSP推流地址 rtsp_url = 'rtsp://127.0.0.1:8554/test' # 配置VideoWriter:指定FFmpeg后端,设置RTSP传输协议和编码 fourcc = cv.VideoWriter_fourcc(*"H264") out = cv.VideoWriter( rtsp_url, cv.CAP_FFMPEG, fourcc, 20.0, size, True ) # 设置RTSP为TCP传输,避免UDP丢包 out.set(cv.CAP_PROP_RTSP_TRANSPORT, cv.RTSP_TRANSPORT_TCP) def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) client.subscribe(MQTT_RECEIVE) def on_message(client, userdata, msg): global frame, frame_width, frame_height, size img = base64.b64decode(msg.payload) npimg = np.frombuffer(img, dtype=np.uint8) frame = cv.imdecode(npimg, 1) # 更新帧尺寸(适配摄像头分辨率变化) frame_height, frame_width = frame.shape[:2] size = (frame_width, frame_height) # 尺寸变化时重新初始化VideoWriter if out.get(cv.CAP_PROP_FRAME_WIDTH) != frame_width or out.get(cv.CAP_PROP_FRAME_HEIGHT) != frame_height: out.release() out = cv.VideoWriter( rtsp_url, cv.CAP_FFMPEG, fourcc, 20.0, size, True ) out.set(cv.CAP_PROP_RTSP_TRANSPORT, cv.RTSP_TRANSPORT_TCP) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect(MQTT_BROKER, MQTT_PORT) client.loop_start() while True: if frame is not None: cv.imshow("Stream", frame) # 确保写入帧尺寸与VideoWriter一致 resized_frame = cv.resize(frame, size) out.write(resized_frame) if cv.waitKey(1) & 0xFF == ord('q'): break cv.destroyAllWindows() client.loop_stop() out.release()
关键修改点
- 给
VideoWriter添加cv.CAP_FFMPEG参数,强制使用FFmpeg后端处理RTSP协议。 - 统一帧尺寸,避免因尺寸不匹配导致的写入失败。
- 设置RTSP为TCP传输,降低丢包概率。
替代方案(OpenCV推流仍异常时)
如果上述方法无效,可直接用FFmpeg命令行推流:将解码后的帧写入管道,通过FFmpeg推送到RTSP服务器,示例代码片段:
import subprocess # 初始化FFmpeg推流进程 ffmpeg_cmd = [ 'ffmpeg', '-y', '-f', 'rawvideo', '-vcodec', 'rawvideo', '-pix_fmt', 'bgr24', '-s', f'{frame_width}x{frame_height}', '-r', '20', '-i', '-', '-c:v', 'libx264', '-preset', 'ultrafast', '-f', 'rtsp', rtsp_url ] process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE) # 在循环中写入帧 process.stdin.write(frame.tobytes())
内容的提问来源于stack exchange,提问作者Nicholas Drogo
相关产品推荐
相关产品推荐

