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

Python中GStreamer的splitmuxsrc元素链接失败问题排查

问题描述

我在Python3.6中尝试实现以下GStreamer命令行管道:

splitmuxsrc location=clip000*.mp4 ! video/x-h264,alignment=au ! h264parse ! avdec_h264 ! videoconvert ! xvimagesink

该命令行可正常运行,但转换为Python代码后出现如下错误:

Error: gst-stream-error-quark: Internal data stream error. (1), gstsplitmuxsrc.c(598): gst_splitmux_pad_loop (): /GstPipeline:pipeline0/GstSplitMuxSrc:muxsrc:
streaming stopped, reason not-linked (-1)

直接链接splitmuxsrc与h264parse无效,且splitmuxsrc没有静态src pad,尝试获取其video类型的request pad也无法成功。

附原Python代码:

import gi

gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject

# Initialize GStreamer
Gst.init(None)

# Create GStreamer pipeline
pipeline = Gst.Pipeline()

# Create elements
muxsrc = Gst.ElementFactory.make("splitmuxsrc", "muxsrc")
h264parse = Gst.ElementFactory.make("h264parse", "h264parse")
avdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264")
videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert")
xvimagesink = Gst.ElementFactory.make("xvimagesink", "xvimagesink")

# Add elements to the pipeline
pipeline.add(muxsrc)
pipeline.add(h264parse)
pipeline.add(avdec_h264)
pipeline.add(videoconvert)
pipeline.add(xvimagesink)

# Link elements
muxsrc.link(h264parse)
h264parse.link(avdec_h264)
avdec_h264.link(videoconvert)
videoconvert.link(xvimagesink)

# Set properties if needed
muxsrc.set_property("location", "clip000*.mp4")

# Set up the main loop
loop = GObject.MainLoop()


# Bus callback function
def bus_callback(bus, message, loop):
    t = message.type
    if t == Gst.MessageType.EOS:
        print("End of Stream")
        loop.quit()
    elif t == Gst.MessageType.ERROR:
        err, debug = message.parse_error()
        print("Error: {}, {}".format(err, debug))
        loop.quit()
    return True


# Create and set up the bus
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message", bus_callback, loop)

# Start the pipeline
pipeline.set_state(Gst.State.PLAYING)

# Run the main loop
try:
    loop.run()
except KeyboardInterrupt:
    pass

# Stop the pipeline
pipeline.set_state(Gst.State.NULL)
解决方案

问题核心是splitmuxsrc的动态pad处理逻辑和属性设置顺序错误,修改后的代码如下:

import gi

gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject

# Initialize GStreamer
Gst.init(None)

# Create GStreamer pipeline
pipeline = Gst.Pipeline()

# Create elements
muxsrc = Gst.ElementFactory.make("splitmuxsrc", "muxsrc")
h264parse = Gst.ElementFactory.make("h264parse", "h264parse")
avdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264")
videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert")
xvimagesink = Gst.ElementFactory.make("xvimagesink", "xvimagesink")

# Add elements to the pipeline
pipeline.add(muxsrc)
pipeline.add(h264parse)
pipeline.add(avdec_h264)
pipeline.add(videoconvert)
pipeline.add(xvimagesink)

# 先链接splitmuxsrc之外的后续元素链
h264parse.link(avdec_h264)
avdec_h264.link(videoconvert)
videoconvert.link(xvimagesink)

# 先设置splitmuxsrc的文件路径属性,确保元素提前识别文件列表
muxsrc.set_property("location", "clip000*.mp4")

# 处理splitmuxsrc的动态pad创建事件
def pad_added_handler(src, new_pad, sink_element):
    # 获取目标元素的静态sink pad
    sink_pad = sink_element.get_static_pad("sink")
    if sink_pad.is_linked():
        print("Pad已链接,跳过")
        return
    # 校验新pad的媒体格式是否匹配H264
    caps = new_pad.get_current_caps()
    if caps.to_string().startswith("video/x-h264"):
        # 执行pad链接
        if new_pad.link(sink_pad) != Gst.PadLinkReturn.OK:
            print("Pad链接失败!")

# 给splitmuxsrc绑定pad-added信号回调
muxsrc.connect("pad-added", pad_added_handler, h264parse)

# Set up the main loop
loop = GObject.MainLoop()

# Bus callback function
def bus_callback(bus, message, loop):
    t = message.type
    if t == Gst.MessageType.EOS:
        print("流已结束")
        loop.quit()
    elif t == Gst.MessageType.ERROR:
        err, debug = message.parse_error()
        print("错误: {}, {}".format(err, debug))
        loop.quit()
    return True

# Create and set up the bus
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message", bus_callback, loop)

# Start the pipeline
pipeline.set_state(Gst.State.PLAYING)

# Run the main loop
try:
    loop.run()
except KeyboardInterrupt:
    pass

# Stop the pipeline
pipeline.set_state(Gst.State.NULL)

修改关键要点

  1. 调整属性设置顺序:先给splitmuxsrc设置location属性再启动管道,确保元素能提前解析文件列表,为后续动态pad创建做准备。
  2. 处理动态Pad:splitmuxsrc不会预先生成静态src pad,而是在启动后根据文件内容动态创建。通过监听pad-added信号,在新pad出现时校验格式并链接到h264parse。
  3. 预链接后续元素链:提前把h264parse到xvimagesink的元素链接完成,避免动态pad链接时出现依赖缺失问题。

内容的提问来源于stack exchange,提问作者just-my-name

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:07:55