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

基于C++的GStreamer RTSP服务器延迟问题求助

解决GStreamer RTSP推流10秒延迟问题

1. 修正Appsrc时间戳逻辑

你当前同时开启了do-timestamp=true和手动设置PTS,这会导致时间戳逻辑冲突;且初始PTS从0累加会让播放器因时间戳滞后缓存大量帧。

  • 将appsrc的do-timestamp改为false,确保时间戳完全由手动控制
  • 绑定PTS到系统时钟实际时间,避免累积延迟,同时修复时钟引用泄漏:
    void VideoStreamer::need_data(GstElement* appsrc, guint /* unused */, gpointer user_data) {
        VideoStreamer* self = static_cast<VideoStreamer*>(user_data);
        GstFlowReturn ret;
    
        std::lock_guard<std::mutex> lock(self->queue_mutex);
        if (!self->frame_queue.empty()) {
            cv::Mat frame = self->frame_queue.front();
            self->frame_queue.pop();
    
            GstBuffer* buffer;
            int size = frame.total() * frame.elemSize();
            buffer = gst_buffer_new_allocate(nullptr, size, nullptr);
    
            GstMapInfo map;
            gst_buffer_map(buffer, &map, GST_MAP_WRITE);
            memcpy(map.data, frame.data, size);
            gst_buffer_unmap(buffer, &map);
    
            GstClock* clock = gst_element_get_clock(appsrc);
            GstClockTime now = gst_clock_get_time(clock);
            
            // 初始化或更新PTS,确保不落后于当前时间
            if (self->last_pts == 0) {
                self->last_pts = now;
            } else {
                self->last_pts = MAX(now, self->last_pts + gst_util_uint64_scale_int(1, GST_SECOND, 30));
            }
    
            GST_BUFFER_PTS(buffer) = self->last_pts;
            GST_BUFFER_DURATION(buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 30);
    
            g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
            gst_buffer_unref(buffer);
            gst_object_unref(clock); // 释放时钟引用,修复内存泄漏
        } else {
            g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
        }
    }
    

2. 限制帧队列大小,避免后端堆积

如果OpenCV处理速度远快于推流速度,frame_queue会持续累积帧,直接导致延迟。限制队列最大长度(比如3-5帧),丢弃旧帧只保留最新的:

// 在向队列添加帧的代码中修改
std::lock_guard<std::mutex> lock(queue_mutex);
const int MAX_QUEUE_SIZE = 5;
if (frame_queue.size() >= MAX_QUEUE_SIZE) {
    frame_queue.pop(); // 丢弃最早的帧
}
frame_queue.push(new_frame);

3. 优化管线缓存与编码器参数

默认的queue和编码器会缓存大量数据,是延迟的核心来源。修改管线配置:

gst_rtsp_media_factory_set_launch(factory,
        "( appsrc name=mysource is-live=true format=GST_FORMAT_TIME do-timestamp=false ! "
        "video/x-raw,format=BGR,width=1920,height=1080,framerate=30/1 ! "
        "videoconvert ! queue max-size-buffers=2 max-size-bytes=0 max-size-time=0 ! "
        "video/x-raw,format=NV12 ! "
        "vaapih264enc low-latency=true rate-control=vbr bitrate=4096 keyframe-period=15 ! "
        "rtph264pay name=pay0 pt=96 config-interval=1 )");

关键调整:

  • queue设置max-size-buffers=2,仅缓存2帧
  • vaapih264enc添加low-latency=true,启用编码器低延迟模式
  • rtph264pay添加config-interval=1,每1秒发送一次SPS/PPS,帮助客户端快速初始化
  • 确认appsrc的do-timestamp=false

4. 客户端播放优化

确保客户端启用低延迟模式:

  • 使用GStreamer客户端测试:gst-launch-1.0 rtspsrc location=rtsp://your-url latency=0 ! rtph264depay ! h264parse ! vaapih264dec ! videoconvert ! autovideosink sync=false
  • VLC播放器可将「网络缓存(ms)」设置为100-200ms(路径:工具->偏好设置->输入/编解码器)

内容的提问来源于stack exchange,提问作者Gökhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 03:28:11