GST_DEBUG_DUMP_DOT_DIR=. GST_DEBUG=3 gst-launch-1...
बनाया गया: 20 जून 2025
बनाया गया: 20 जून 2025
GST_DEBUG_DUMP_DOT_DIR=. GST_DEBUG=3 gst-launch-1.0 urisourcebin uri=http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8 name=src ! decodebin3 name=dec dec. ! queue ! videoconvert ! videoscale ! autovideosink dec. ! queue ! audioconvert ! audioresample ! volume name=volume ! level ! autoaudiosink
设置暂停管道 ...
管道正在 PREROLLING ...
0:00:00.026710012 22626 0x55d1a8d25350 WARN structure gststructure.c:3100:priv_gst_structure_append_to_gstring: No value transform to serialize field 'session' of type 'GstSoupSession'
从组件“souphttpsrc0”获取上下文:gst.soup.session=context, session=(GstSoupSession)NULL;
重新分配延迟时间...
0:00:01.335211756 22626 0x7f033404e4c0 FIXME decodebin3 gstdecodebin3.c:1186:gst_decodebin_input_unblock_streams:<dec> Re-use existing input streams if/when possible
0:00:01.335293014 22626 0x7f033404e4c0 FIXME decodebin3 gstdecodebin3.c:1186:gst_decodebin_input_unblock_streams:<dec> Re-use existing input streams if/when possible
重新分配延迟时间...
重新分配延迟时间...
重新分配延迟时间...
设置播放管道 ..
现象:播放只有一幀图像,没有声音,播放进度为0
问题根源
urisourcebin
只负责把网络流取下来并解析成 动态 输出 pad,而不是把它们自动连到解码器。
在 gst-launch-1.0
里,只有当两个元素在 启动时就已经有 pad 时,用 !
才能一次性把它们“焊”在一起。
HLS 源在一开始是没有 pad 的 → urisourcebin ! decodebin3
实际上 没连上。
结果管线能取得头一个切片并完成 preroll,画面停在首帧,音轨也没有真正流进来,进度保持 0。
bash# 最简单的播放测试 gst-play-1.0 \ http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8
或
bashgst-launch-1.0 \ playbin3 uri=\ http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8
uridecodebin
uridecodebin
= urisourcebin
+ decodebin3
,并且会自己把动态 pad 连好:
bashGST_DEBUG=3 gst-launch-1.0 \ uridecodebin uri=http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8 name=dec \ dec. ! queue ! videoconvert ! videoscale ! autovideosink \ dec. ! queue ! audioconvert ! audioresample ! autoaudiosink
要点
dec.
前面的空格和点号告诉gst-launch
:等uridecodebin
产生 pad 后再去连。- 每条支路加
queue
,避免视频/音频互相阻塞。
urisourcebin
?那就得自己写代码在 C/GLib、Python、Rust… 里捕捉 pad-added
信号:
cg_signal_connect (src, "pad-added", G_CALLBACK (on_src_pad_added), decodebin);
然后在回调里把新 pad 手动 link 到 decodebin3
,或直接 link 到下游 element。
gst-launch-1.0
无法做这种“运行时布线”,因此不适合用 urisourcebin
+ decodebin3
的组合来播 HLS。
检查项 | 说明 |
---|---|
插件是否齐全 | gst-inspect-1.0 adaptivedemux2 hlsdemux avdec_h264 faad 若有缺失请安装对应插件集(gst-plugins-bad , gst-libav 等)。 |
时钟同步 | 如果只要视频首帧、音频缺失,有时是音频解码/输出插件缺失导致时钟挂起。 |
版本问题 | gst-launch-1.0 --version 建议 1.22+;低版本对 HLS 支持不稳定。 |
更细日志 | GST_DEBUG=*adaptive*:4,*hls*:4 可看出 segment/playlist 下载、切换与 demux 情况。 |
照以上方法换成 uridecodebin
或 playbin3
后,通常就能连播、声音视频都正常,播放进度也会向前走。祝调试顺利!
如果是自己写的gstreamer插件呢,请问 playbin3 如何使用私有插件播放
下面这几个步骤就能让 playbin3 顺利找到并使用你自己写的私有插件。按需要任选其一或组合使用即可。
.so
文件放到一个单独目录,例如 ~/gst-private
bash# 方法 A:环境变量 export GST_PLUGIN_PATH=$HOME/gst-private # 可以设多个目录,用 : 分隔 gst-inspect-1.0 myelement # 先确认插件已被注册 # 方法 B:一次性 gst-launch-1.0 --gst-plugin-path=$HOME/gst-private \ playbin3 uri=file:///tmp/test.mp4
GStreamer 会扫描 GST_PLUGIN_PATH
中的目录并把插件登记进运行时插件表 stackoverflow.com
调试小贴士:
GST_DEBUG=GST_PLUGIN_LOADING:6
能打印每个插件的加载过程。
直接把实例(或一个自定义 Bin)塞给 video-sink
/ audio-sink
属性:
bashGST_PLUGIN_PATH=~/gst-private \ gst-launch-1.0 playbin3 \ uri=file:///tmp/test.mp4 \ video-sink="myvideosink" \ audio-sink="myaudiosink"
playbin3
默认会用 autovideosink
/autoaudiosink
,手动指定即可覆盖 gstreamer.freedesktop.org stackoverflow.com
GST_PLUGIN_DEFINE
/ gst_element_register()
里给元素设置合适的 classification(如 Decoder/Video
)和 pad caps,这样 uridecodebin3
能识别它。GST_RANK_PRIMARY
(256)或更高;rank 越高,自动插件器越优先选它 gstreamer.freedesktop.org
cgst_element_register (plugin, "myh264dec", GST_RANK_PRIMARY + 1, GST_TYPE_MY_H264_DEC);
cGstPluginFeature *f = gst_element_factory_find ("myh264dec"); gst_plugin_feature_set_rank (f, GST_RANK_PRIMARY + 1); ``` [developer.ridgerun.com](https://developer.ridgerun.com/wiki/index.php/GStreamer_modify_the_elements_rank?utm_source=chatgpt.com)
创建一个包含你滤镜的 GstBin
,然后通过 video-filter
/ audio-filter
属性插进去:
cGstElement *flt = gst_parse_bin_from_description ("myfilter ! videoconvert", TRUE, NULL); g_object_set (playbin, "video-filter", flt, NULL);
把插件代码直接和应用链接,在初始化里调用 gst_plugin_register_static()
:
cgst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR, "my-static", "Private elements", plugin_init_cb, "1.0", "LGPL", "myapp", "myapp", "https://example.com");
静态注册后,gst_element_factory_make("myvideosink", NULL)
就能正常工作,完全不依赖文件系统扫描 gstreamer.freedesktop.org
如果你不想改环境变量,可以在 gst_init()
之后手动:
cGstRegistry *r = gst_registry_get (); gst_registry_scan_path (r, "/opt/myplugins"); // 扫描目录 gst_plugin_load_file ("/opt/myplugins/libgstmy.so", NULL); // 直接加载单个 .so
现象 | 排查要点 |
---|---|
gst-inspect-1.0 看不到元素 | 路径没进 GST_PLUGIN_PATH ;或者 .so 名必须形如 libgstXXX.so |
playbin3 还是没用到你的解码器 | rank 太低;或 pad caps/classification 不匹配 |
代码修改后仍加载旧插件 | 删除 ~/.cache/gstreamer-1.0/registry*.bin 后重试 |
按照上面流程,把路径加进来 + 保证元素 rank/分类正确,playbin3
就能像使用系统插件一样自动挑选并使用你的私有插件。祝编译顺利、调试顺心!
playbin3 如何设置音量和重采样呢
在 playbin3 里有两条常用途径来控制「音量」和「重采样(audioresample)」——
方案 | 适用场景 | 做法示例(gst-launch-1.0) | 要点 |
---|---|---|---|
直接用 playbin3 自带属性 | 只想调整体响度,别的保持自动 | gst-launch-1.0 playbin3 uri=file:///tmp/demo.mp4 volume=0.4 | • volume 属性是 gdouble,0 = 静音,1 = 100 %。<br>• 可在运行中通过 g_object_set(playbin, "volume", 0.8, NULL); 动态调节。<br>• 还有 mute (gboolean) 可直接开关静音。<br>• 采样率转换由自动协商完成,无需手动插 audioresample 。 |
在音频链插自定义滤镜 | 想显式加 volume 、audioresample 、capsfilter 等 | ```bash | |
gst-launch-1.0 playbin3 \ | |||
uri=file:///tmp/demo.mp4 \ | |||
audio-filter="volume name=vol ! audioresample ! audio/x-raw,rate=48000" | |||
``` | • audio-filter / video-filter 属性接受 bin 描述字符串。<br>• 这段 bin 会被插在解码器之后、audio-sink 之前。<br>• 可给元件取名 (name=vol ) 方便后续用 gst-launch-1.0 的 remote-control 或在代码里找回调节。<br>• 想指定声道数、格式等,同样在 audio-filter 里加 capsfilter 即可:… ! audio/x-raw,channels=2,format=S16LE | ||
完全替换 audio-sink | 想把自定义链放到最末端(含 sink) | ```bash | |
gst-launch-1.0 playbin3 \ | |||
uri=file:///tmp/demo.mp4 \ | |||
audio-sink="volume ! audioresample ! autoaudiosink" | |||
``` | • audio-sink 期望的是 元素实例 或 bin。<br>• 因为已经在最末端,必须自己包含一个真正的 sink(例如 autoaudiosink / pulsesink 等)。 |
c/* 创建并初始化 playbin3 */ GstElement *playbin = gst_element_factory_make ("playbin3", NULL); g_object_set (playbin, "uri", "file:///tmp/demo.mp4", "volume", 0.7, /* 方案 1 */ NULL); /* 方案 2:插 audio-filter */ GstElement *aflt = gst_parse_bin_from_description ( "volume name=vol ! audioresample ! audio/x-raw,rate=48000", TRUE, NULL); g_object_set (playbin, "audio-filter", aflt, NULL); /* 随时动态调节音量 */ GstElement *vol = gst_bin_get_by_name (GST_BIN (aflt), "vol"); g_object_set (vol, "volume", 0.3, NULL);
问题 | 答案 |
---|---|
audioresample 必须手动加吗? | 一般不用。只要上游和下游协商不一致,GStreamer 会自动在 pipeline 里插入 audioresample 。只有当你想 强制 输出固定采样率或需要精确控制时才显式加入。 |
能同时用 audio-filter 与 audio-sink 吗? | 可以,两者互不冲突。常见做法是把全局处理(EQ、限幅器等)放在 audio-filter ,然后在 audio-sink 里替换最终输出(比如自定义的 ALSA sink)。 |
Python 中怎么拿到 volume 元件? | ```python |
vol = playbin.get_property("audio-filter").get_by_name("vol") | |
vol.set_property("volume", 0.5) |
text| **playbin 与 playbin3 的差异?** | `playbin3` 使用 `urisourcebin`+`decodebin3`,对自适应流(HLS/DASH)更友好,并且支持 `audio-filter` / `video-filter` 这类新属性;在 1.22+ 建议直接用 `playbin3`。 | 只要记住 **“简单调音量 → 用 playbin3 自带属性;想自定义链 → 用 audio-filter/audio-sink”** 这条原则,就能灵活地在 `playbin3` 里加上任意音频处理元素。祝开发顺利!