GStreamer:构建媒体处理管道

FreeGuideOnline 最新 2026-07-03

bash

Debian/Ubuntu

sudo apt update sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-base
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad
gstreamer1.0-plugins-ugly libgstreamer1.0-dev


macOS 可使用 Homebrew:

```bash
brew install gstreamer gst-plugins-base gst-plugins-good \
  gst-plugins-bad gst-plugins-ugly

Windows 用户可从 GStreamer 官网 下载安装包。

核心概念

理解 GStreamer 的四个核心概念是构建管道的基石。

元素

元素是处理媒体数据的最小功能单元。每个元素执行一个特定操作,例如:

  • source:产生数据(从文件、网络、摄像头)
  • filter/transform:处理数据(编码、解码、缩放)
  • sink:消耗数据(播放到声卡、写入文件)

元素通过衬垫 (pad) 进行连接。

衬垫

衬垫是元素的输入或输出接口。源衬垫(src pad)产生数据,接收衬垫(sink pad)消费数据。只有具兼容能力的衬垫才能相互连接(协商 caps)。

箱柜

箱柜 (bin) 是元素的容器,可将多个元素组合成一个逻辑整体。它可以像单个元素一样操作状态,其中最常用的两个箱柜是:

  • 管道 (pipeline):顶层的箱柜,通常代表整个应用的处理流程。
  • 播放仓 (playbin):一个自动化的播放元素,内部封装了完整的解码与渲染管道。

总线与消息

管道拥有一个总线 (bus),用于异步通知应用事件(如错误、结束、状态变化)。通过监听总线消息,应用可以获取管道运行时的反馈。

命令行快速入门

gst-launch-1.0 是测试和构建管道的命令行工具。其基本语法为:

gst-launch-1.0 [元素1] ! [元素2] ! [元素3] ...

感叹号 ! 连接元素,数据从左向右流动。

播放本地音频文件

gst-launch-1.0 filesrc location=song.mp3 ! decodebin ! audioconvert ! autoaudiosink
  • filesrc 读取文件
  • decodebin 自动检测格式并解码
  • audioconvert 转换音频格式
  • autoaudiosink 自动选择音频输出设备

播放视频文件

gst-launch-1.0 playbin uri=file:///path/to/video.mp4

playbin 封装了完整播放流程,一行搞定。

创建测试音视频

生成一段 440Hz 正弦波测试音,持续5秒:

gst-launch-1.0 audiotestsrc freq=440 ! audioconvert ! autoaudiosink

显示测试视频图案:

gst-launch-1.0 videotestsrc ! autovideosink

捕获摄像头并显示

gst-launch-1.0 v4l2src ! videoconvert ! autovideosink

v4l2src 在 Linux 下可用,其他系统请用 avfvideosrcksvideosrc 等)

构建管道:C 语言示例

通过 API 动态创建管道可完成更复杂的控制。下面是一个最小可运行的 C 程序,实现播放 MP3 文件。

环境准备

编译时需链接 GStreamer:

gcc -o play play.c `pkg-config --cflags --libs gstreamer-1.0`

代码

#include <gst/gst.h>

int main(int argc, char *argv[]) {
    GstElement *pipeline, *source, *decode, *convert, *sink;
    GstBus *bus;
    GstMessage *msg;

    /* 初始化 GStreamer */
    gst_init(&argc, &argv);

    /* 创建元素 */
    pipeline  = gst_pipeline_new("my-pipeline");
    source    = gst_element_factory_make("filesrc", "file-source");
    decode    = gst_element_factory_make("decodebin", "decoder");
    convert   = gst_element_factory_make("audioconvert", "converter");
    sink      = gst_element_factory_make("autoaudiosink", "audio-output");

    if (!pipeline || !source || !decode || !convert || !sink) {
        g_printerr("One or more elements could not be created.\n");
        return -1;
    }

    /* 设置文件路径 */
    g_object_set(source, "location", "song.mp3", NULL);

    /* 将所有元素加入管道 */
    gst_bin_add_many(GST_BIN(pipeline), source, decode, convert, sink, NULL);

    /* 连接静态元素 */
    if (!gst_element_link(source, decode)) {
        g_printerr("Failed to link filesrc and decodebin.\n");
        return -1;
    }
    if (!gst_element_link_many(convert, sink, NULL)) {
        g_printerr("Failed to link audioconvert and audiosink.\n");
        return -1;
    }

    /* decodebin 的动态衬垫需要在运行时连接,这里简化使用消息监听 */
    g_signal_connect(decode, "pad-added", G_CALLBACK(on_pad_added), convert);

    /* 启动管道 */
    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    /* 等待管道结束或出错 */
    bus = gst_element_get_bus(pipeline);
    msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
        GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

    /* 清理 */
    if (msg != NULL)
        gst_message_unref(msg);
    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);

    return 0;
}

/* decodebin 的动态 pad-added 回调 */
static void on_pad_added(GstElement *decode, GstPad *pad, gpointer data) {
    GstElement *convert = (GstElement *)data;
    GstPad *sinkpad = gst_element_get_static_pad(convert, "sink");

    if (!gst_pad_is_linked(sinkpad)) {
        GstPadLinkReturn ret = gst_pad_link(pad, sinkpad);
        g_print("Dynamic pad linking: %s\n",
                ret == GST_PAD_LINK_OK ? "OK" : "Failed");
    }
    gst_object_unref(sinkpad);
}

该程序创建管道并静态连接 filesrcdecodebin。因 decodebin 输出衬垫在运行时才创建,因此通过 pad-added 信号动态连接到 audioconvert

常用管道模式

编码与文件录制

将摄像头视频编码为 H.264 保存到文件:

gst-launch-1.0 v4l2src ! videoconvert ! x264enc ! mp4mux ! filesink location=output.mp4

RTP 流媒体传输

发送端(H.264 视频流):

gst-launch-1.0 videotestsrc ! videoconvert ! x264enc ! rtph264pay ! udpsink host=127.0.0.1 port=5000

接收端:

gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp, media=video, payload=96" ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink

音量归一化与音频混合

gst-launch-1.0 audiotestsrc ! volume volume=0.5 ! autoaudiosink