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

Windows下如何用Gst-RTSP-Server结合OpenCV C++实现RTSP推流?

嘿,我看你已经有GStreamer RTSP推流和OpenCV UDP推流的基础了,那咱们直接解决用OpenCV的cv::Mat帧推RTSP的问题,给你两个实用方案,重点推荐第一个,因为和你之前用的gst-rtsp-server逻辑衔接更顺畅:

方案一:基于gst-rtsp-server自定义媒体工厂(推荐)

这个方案是把gst-rtsp-server的示例逻辑和OpenCV结合,用appsrc作为数据源,手动把OpenCV的帧推送到GStreamer管道里,稳定性和灵活性都更好。

完整代码示例

#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
#include <opencv2/opencv.hpp>

using namespace cv;

static GstElement *appsrc = nullptr;
static VideoCapture cap;

// 当GStreamer需要数据时触发的回调,负责从OpenCV获取帧并推送
static void need_data(GstElement *src, guint size, gpointer user_data) {
    Mat frame;
    cap >> frame;
    if (frame.empty()) {
        // 视频结束,发送EOS信号终止流
        gst_element_send_event(src, gst_event_new_eos());
        return;
    }

    // 把OpenCV的BGR格式转成GStreamer常用的I420格式
    Mat frame_converted;
    cvtColor(frame, frame_converted, COLOR_BGR2YUV_I420);

    // 创建GStreamer缓冲区并复制帧数据
    GstBuffer *buffer = gst_buffer_new_allocate(nullptr, frame_converted.total() * frame_converted.elemSize(), nullptr);
    GstMapInfo map;
    gst_buffer_map(buffer, &map, GST_MAP_WRITE);
    memcpy(map.data, frame_converted.data, map.size);
    gst_buffer_unmap(buffer, &map);

    // 设置时间戳,保证播放器同步(30fps的话每帧时长约33ms)
    GstClockTime timestamp = gst_util_get_timestamp();
    GST_BUFFER_PTS(buffer) = timestamp;
    GST_BUFFER_DURATION(buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 30);

    // 把缓冲区推送到appsrc
    GstFlowReturn ret = gst_app_src_push_buffer(GST_APP_SRC(src), buffer);
    if (ret != GST_FLOW_OK) {
        g_printerr("推送帧失败: %s\n", gst_flow_get_name(ret));
    }

    // 控制帧率,和视频原帧率匹配
    cv::waitKey(30);
    // 同时显示原帧(可选)
    imshow("OpenCV Source Frame", frame);
}

int main(int argc, char *argv[]) {
    // 初始化GStreamer和OpenCV
    gst_init(&argc, &argv);
    cv::namedWindow("OpenCV Source Frame", WINDOW_AUTOSIZE);

    // 打开视频文件(换成0可以调用摄像头)
    cap.open("Wildlife.mp4");
    if (!cap.isOpened()) {
        g_printerr("无法打开视频源!\n");
        return -1;
    }

    // 创建RTSP服务器实例
    GstRTSPServer *server = gst_rtsp_server_new();
    gst_rtsp_server_set_service(server, "8554"); // 设置RTSP端口,默认8554

    // 创建媒体映射,用于绑定路径和媒体工厂
    GstRTSPMediaMapping *mapping = gst_rtsp_server_get_media_mapping(server);
    GstRTSPMediaFactory *factory = gst_rtsp_media_factory_new();

    // 定义GStreamer管道:appsrc -> 格式转换 -> H.264编码 -> RTP打包
    // 这里用x264enc的zerolatency调优参数,适合实时推流
    gst_rtsp_media_factory_set_launch(factory,
        "( appsrc name=source is-live=true format=GST_FORMAT_TIME "
        "! videoconvert ! video/x-raw,format=I420,width=640,height=360,framerate=30/1 "
        "! x264enc tune=zerolatency bitrate=500 speed-preset=superfast "
        "! rtph264pay name=pay0 pt=96 )");

    // 设置共享模式,允许多个客户端同时连接
    gst_rtsp_media_factory_set_shared(factory, TRUE);

    // 当媒体配置完成时,获取appsrc并绑定need-data回调
    g_signal_connect(factory, "media-configure", G_CALLBACK([](GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data) {
        GstElement *element = gst_rtsp_media_get_element(media);
        appsrc = gst_bin_get_by_name(GST_BIN(element), "source");
        g_signal_connect(appsrc, "need-data", G_CALLBACK(need_data), nullptr);
        g_object_unref(element);
    }), nullptr);

    // 把媒体工厂绑定到RTSP路径/test
    gst_rtsp_media_mapping_add_factory(mapping, "/test", factory);
    g_object_unref(mapping);

    // 启动服务器
    gst_rtsp_server_attach(server, nullptr);
    g_print("RTSP服务器已启动,播放地址:rtsp://localhost:8554/test\n");

    // 启动GStreamer主循环
    GMainLoop *loop = g_main_loop_new(nullptr, FALSE);
    g_main_loop_run(loop);

    // 清理资源
    g_main_loop_unref(loop);
    g_object_unref(server);
    cap.release();
    cv::destroyAllWindows();
    return 0;
}

编译命令

确保你的系统安装了gstreamer-1.0、gstreamer-rtsp-server-1.0和OpenCV开发包,然后用以下命令编译:

g++ -o opencv_rtsp_pusher opencv_rtsp_pusher.cpp `pkg-config --cflags --libs gstreamer-1.0 gstreamer-rtsp-server-1.0 opencv4`

关键说明

  • 用appsrc作为GStreamer的数据源,它允许我们手动推送帧数据,完美适配OpenCV的cv::Mat
  • 转换帧格式时,把OpenCV默认的BGR转成I420,这是GStreamer处理视频的通用格式
  • x264enc的tune=zerolatency参数是实时推流的关键,能大幅降低延迟
  • 时间戳的设置很重要,否则播放器可能出现卡顿或音视频不同步
方案二:用OpenCV VideoWriter直接推RTSP(简易版)

如果你想快速实现,也可以用OpenCV的VideoWriter结合GStreamer的RTSP sink,但这个方案依赖GStreamer的rtspclientsink,需要你先启动一个RTSP服务器(比如用gst-launch-1.0临时启动)。

步骤1:启动临时RTSP服务器

先在终端运行这个命令,启动一个接收UDP流并转为RTSP的服务器:

gst-launch-1.0 udpsrc port=5004 ! application/x-rtp,payload=96 ! rtph264depay ! h264parse ! rtspclientsink location=rtsp://localhost:8554/test

步骤2:OpenCV推流代码

修改你原来的UDP推流代码,把GStreamer管道改成推送到上面的UDP端口:

#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char* argv[]) {
    VideoCapture cap("Wildlife.mp4");
    if (!cap.isOpened()) {
        printf("无法打开视频!\n");
        return -1;
    }

    // 用H.264编码推送到UDP,再由临时RTSP服务器转成RTSP流
    VideoWriter out = VideoWriter(
        "appsrc ! queue ! videoconvert ! video/x-raw, format=I420, width=640, height=360, framerate=30/1 "
        "! x264enc tune=zerolatency ! rtph264pay ! udpsink host=127.0.0.1 port=5004",
        CAP_GSTREAMER, 0, 30, Size(640, 360)
    );

    if (!out.isOpened()) {
        printf("VideoWriter初始化失败!\n");
        return -1;
    }

    Mat frame;
    while (cap.read(frame)) {
        if (frame.empty()) break;
        out.write(frame);
        imshow("Frame", frame);
        waitKey(30);
    }

    cap.release();
    out.release();
    destroyAllWindows();
    return 0;
}

说明

这个方案更简单,但需要额外启动一个中间RTSP服务器,稳定性不如方案一,适合快速测试。

注意事项
  • 确保安装了GStreamer的H.264编码插件(Ubuntu下是gstreamer1.0-plugins-ugly,Windows下需要在安装GStreamer时勾选对应组件)
  • 调整分辨率、帧率参数时,要和视频源(文件/摄像头)的实际参数匹配,否则会出现格式不兼容
  • 如果用摄像头,把cap.open("Wildlife.mp4")改成cap.open(0)即可

内容的提问来源于stack exchange,提问作者A.k.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 22:22:46