FFmpeg中的时间戳(DTS和PTS)

本文介绍了FFmpeg中两种时间戳的概念:DTS和PTS。详细解释了它们在视频压缩包和信号帧中的作用,并通过IPB帧的具体例子阐述了这两种时间戳如何确保视频正确解码及播放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FFmpeg里有两种时间戳:DTS(Decoding Time Stamp)和PTS(Presentation Time Stamp)。 顾名思义,前者是解码的时间,后者是显示的时间。要仔细理解这两个概念,需要先了解FFmpeg中的packet和frame的概念。

FFmpeg中用AVPacket结构体来描述解码前或编码后的压缩包,用AVFrame结构体来描述解码后或编码前的信号帧。 对于视频来说,AVFrame就是视频的一帧图像。这帧图像什么时候显示给用户,就取决于它的PTS。DTS是AVPacket里的一个成员,表示这个压缩包应该什么时候被解码。 如果视频里各帧的编码是按输入顺序(也就是显示顺序)依次进行的,那么解码和显示时间应该是一致的。可事实上,在大多数编解码标准(如H.264或HEVC)中,编码顺序和输入顺序并不一致。 于是才会需要PTS和DTS这两种不同的时间戳。



比如说,视频编码中有 I P B帧

I是完整的帧  P是向前帧(依赖I帧) B是双向帧(也就是依赖I 和P 和B帧)。

那么,对于帧序列

I B B P

编码顺序是 I P B B 

但是保存为一个视频文件时 顺序是 I B B P的顺序。

但是读取文件时就不是内容在前就先解码,所以需要一个DTS标记,由上可以看到B帧在P之前的,所以B先播放,所以有需要一个PTS标记。


### 使用 FFmpeg 修改媒体文件的时间戳FFmpeg 中,时间戳是一个非常重要的概念,它用于描述音频视频帧的播放顺序以及同步关系。通过调整时间戳,可以实现诸如延迟校正、重新同步等功能。 要修改媒体文件的时间戳,通常会涉及以下几个参数: 1. **PTS (Presentation Time Stamp)**:表示该帧应该被显示的时间。 2. **DTS (Decoding Time Stamp)**:表示该帧应该被解码的时间。 3. **Time Base**:定义了 PTS DTS 的单位,通常是分数形式(例如 `1/90000` 表示每秒有 90,000 个时间刻度)。 以下是具体的操作方法: #### 方法一:使用 `-itsoffset` 参数 `-itsoffset` 是一种简单的方法来偏移输入流的时间轴。它可以用来增加或减少整个文件的时间戳。 ```bash ffmpeg -itsoffset <offset_seconds> -i input.mp4 -c copy output.mp4 ``` 其中 `<offset_seconds>` 是希望应用的时间偏移量(正值表示延后,负值表示提前)。此命令不会重新编码数据,而是直接复制原始流并调整其时间戳[^1]。 #### 方法二:手动设置 PTS/DTS 如果需要更精细地控制每一帧的时间戳,则可以通过滤镜复杂表达式或者脚本逐包操作完成。下面展示了一个利用 setpts 滤波器的例子: ```bash ffmpeg -i input.mp4 -vf "setpts=PTS+<seconds>/TB" -c:a copy output.mp4 ``` 这里,“`<seconds>`”代表你想加到当前呈现时刻上的秒数;而 TB 自动取自对应轨道的时间基准[^5]。 对于更加复杂的场景比如单独修正某一路或多路流的不同步问题,则可能需要用到 per-stream filters 或者编写自定义程序调用 libavformat 库接口来进行精确操控[^6]。 #### 示例代码片段 当您想要开发应用程序以动态更改这些属性时,可参考如下 C++ 实现思路: ```cpp // 初始化... while ((ret = av_read_frame(ifmt_ctx, pkt)) >= 0) { if(pkt->stream_index == video_stream_idx){ // 调整视频包的时间戳 int64_t new_pts = adjust_timestamp(pkt->pts); pkt->pts = new_pts; // 如果存在则同样处理DTS if(pkt->dts != AV_NOPTS_VALUE){ pkt->dts = adjust_timestamp(pkt->dts); } } // 写入输出文件... } ``` 注意,在实际项目里还需要考虑边界条件如未初始化的时间戳等问题[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值