Python中基于GStreamer自定义AppSrc实现RTSP流的配置问题
问题排查与解决:GStreamer AppSrc推送模式配合编码器报错
核心问题分析
你遇到的gst_pad_set_caps: assertion 'caps != NULL && gst_caps_is_fixed (caps)' failed错误,本质是编码器接收的caps未完全固定——虽然AppSrc设置了固定caps,但管线中可能存在caps协商环节未处理好,导致编码器端拿到的caps不满足固定要求。
关键修复步骤
1. 确保AppSrc的caps完全固定(包含所有必要参数)
很多人只设置了基础的格式、宽高参数,但编码器还需要帧率、像素 stride等关键参数,必须全量明确:
import gi gi.require_version('Gst', '1.0') from gi.repository import Gst, GLib import numpy as np Gst.init(None) # 生成100x100红色测试帧 frame = np.zeros((100, 100, 3), dtype=np.uint8) frame[:,:,0] = 255 # 初始化AppSrc并设置全量固定caps appsrc = Gst.ElementFactory.make("appsrc", "appsrc") caps = Gst.Caps.from_string( "video/x-raw,format=RGB,width=100,height=100,framerate=30/1,pixel-aspect-ratio=1/1,stride=300" ) appsrc.set_property("caps", caps) appsrc.set_property("format", Gst.Format.TIME) appsrc.set_property("is-live", True)
stride:RGB格式下为width*3(每个像素占3字节),必须明确指定,避免编码器自动计算出错framerate:用30/1这类分数形式固定,不能留空
2. 强制管线caps协商,避免动态变更
在AppSrc之后添加capsfilter元素,强制下游只能接收固定caps,阻断编码器的无效协商尝试:
capsfilter = Gst.ElementFactory.make("capsfilter", "capsfilter") capsfilter.set_property("caps", caps) # 以JPEG编码写入AVI为例构建完整管线 pipeline = Gst.Pipeline.new("test-pipeline") encoder = Gst.ElementFactory.make("jpegenc", "encoder") muxer = Gst.ElementFactory.make("avimux", "muxer") filesink = Gst.ElementFactory.make("filesink", "filesink") filesink.set_property("location", "output.avi") # 将所有元素添加到管线 for elem in [appsrc, capsfilter, encoder, muxer, filesink]: pipeline.add(elem) # 按顺序链接元素 Gst.Element.link_many(appsrc, capsfilter, encoder, muxer, filesink)
3. 正确处理AppSrc的回调与时间戳
推送模式下,必须给每个缓冲区设置准确的时间戳和时长,否则编码器会因时序异常阻塞:
def push_buffer(appsrc, data): # 将numpy数组转为GstBuffer buffer = Gst.Buffer.new_wrapped(frame.tobytes()) # 按帧率计算时间戳(单位:纳秒) timestamp = data['frame_count'] * (1e9 // 30) buffer.set_pts(timestamp) buffer.set_dts(timestamp) buffer.set_duration(1e9 // 30) # 推送缓冲区 ret = appsrc.emit("push-buffer", buffer) data['frame_count'] += 1 # 推送100帧后发送EOS信号停止 if data['frame_count'] >= 100: appsrc.emit("end-of-stream") return Gst.FlowReturn.EOS return ret # 绑定回调并初始化帧计数 data = {'frame_count': 0} appsrc.connect("need-data", push_buffer, data) # 启动管线并运行主循环 pipeline.set_state(Gst.State.PLAYING) loop = GLib.MainLoop() try: loop.run() except KeyboardInterrupt: pass # 清理资源 pipeline.set_state(Gst.State.NULL)
4. 针对RTSP流的额外配置
如果是推送H264 RTSP流,需补充以下配置:
- 使用
x264enc时,设置speed-preset等参数,同时给capsfilter添加H264的固定caps:
caps_h264 = Gst.Caps.from_string( "video/x-h264,profile=baseline,width=100,height=100,framerate=30/1" )
- RTSP服务器端(如
gst-rtsp-server)需明确指定接收的caps,避免动态协商
常见误区排查
- 不要依赖GStreamer自动填充caps参数,所有涉及视频格式的元素都必须用固定caps约束
- 推送模式下
is-live必须设为True,否则编码器会无限等待EOS信号导致阻塞 - numpy数组的 dtype 必须是
uint8,与GStreamer的video/x-raw格式匹配
内容的提问来源于stack exchange,提问作者KleinSchwab
相关产品推荐
相关产品推荐

