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

从GStreamer获取的PTS与保存的TS文件中PTS不匹配问题排查

GStreamer PTS不匹配问题排查与解决

问题背景

我用Rust实现了一个GStreamer管道,拉取摄像头RTSP流并做AI目标检测,简化后的管道如下:

rtspsrc latency=100 location=rtsp://<rtspurl> protocols=0x4 name=basesrc basesrc. ! rtph264depay ! tee name=t 
t. ! queue ! vaapidecodebin name=video_decoder ! tee name=decode_t 
   decode_t. ! queue ! videorate ! video/x-raw,framerate=15/1 ! vaapipostproc format=nv12 ! video/x-raw,width=2880,height=1620 ! vaapih265enc ! h265parse config-interval=-1 ! hlssink2 playlist-length=5 max-files=0 target-duration=10 send-keyframe-requests=true program-date-time=true playlist-location=manifest.m3u8 location=video/%t.ts 
   decode_t. ! queue ! videorate ! video/x-raw,framerate=3/1 ! vaapipostproc format=nv12 ! video/x-raw,width=640,height=384 ! videoconvert ! objectdetector ! fakesink async=false 

其中objectdetector是我开发的自定义插件,在transform_frame_ip()中通过gst_video::VideoFrameRef<&mut gst::BufferRef>获取PTS:

let pts = frame.buffer().pts().expect("Buffer must have a PTS value.");

但用ffprobe查看hlssink生成的TS分段文件时,得到的PTS和插件中获取的完全不同,ffprobe命令:

ffprobe -select_streams v -show_frames -of csv -show_entries frame=coded_picture_number,key_frame,pict_type,pts,pts_time -i <> 

需要匹配两者的PTS以对应实际播放时间,方便在浏览器播放manifest时绘制目标检测框,请问问题出在哪?

核心原因与解决方法

1. PTS时间基准不统一

GStreamer中每个Pad/Element的PTS基于自身的时间基准(Clock Time Base),而ffprobe显示的TS文件PTS基于TS容器的标准时间基准(通常为90kHz,即1/90000秒),两者刻度不同,直接数值对比无意义。

解决方式:

  • 在自定义插件中,将PTS转换为秒级绝对时间,或转换为与HLSSink输出一致的时间基准,再与ffprobe输出的pts_time字段对比。

2. 转换PTS为统一时间单位

在objectdetector插件中,获取当前Pad的时间基准,将PTS转换为秒级时间:

// 获取当前Buffer所属Pad的时间基准
let time_base = frame.buffer().pad().unwrap().current_time_base();
// 将PTS转换为秒级浮点数
let pts_seconds = pts.to_nseconds() as f64 / time_base.denom() as f64;

此时得到的pts_seconds可以直接和ffprobe输出的pts_time字段匹配,用于对应播放时间。

3. 对齐HLSSink的墙钟时间

由于你设置了program-date-time=true,HLSSink会将流时间戳转换为实际墙钟时间写入播放列表和TS文件。你可以在插件中同样将PTS转换为墙钟时间,和HLSSink输出对齐:

// 获取管道时钟
let clock = element.clock().unwrap();
// 将流PTS转换为系统绝对时间
let absolute_time = clock.convert_stream_time_to_system_time(time_base, pts);
// 转换为RFC3339格式,和HLSSink的program-date-time输出格式一致
let time_str = absolute_time.to_rfc3339();

这个时间字符串可以直接对应浏览器播放时的实际时间点,用于绘制检测框。

4. 同步分支时钟避免偏移

你的检测分支使用了fakesink async=false,会导致该分支脱离管道同步时钟,可能造成时间戳和编码分支偏移。建议:

  • 移除async=false,让检测分支与主编码分支共享管道时钟,确保时间基准一致。
  • 若必须保留async=false,需手动同步两个分支的时间基准,比如通过总线消息传递时间基准参数。

内容的提问来源于stack exchange,提问作者Gatothgaj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 02:43:22