一.本章节介绍
本章节将系统讲解FFMPEG的核心时间概念,涵盖时间基、时间戳及时间转换等关键内容。掌握这些知识点对理解推流技术至关重要,因为音视频合成的本质正是通过这些时间参数的精确转换实现的。
二.F FMPEG 时间基、 时间戳的讲解:
2 .1. 时间基( time_base) :
时间基也称之为时间基准,它代表的是每个刻度是多少秒。比方说:视频帧率是25 F PS ****,****那它的时间刻度是{1,25}。相当于1s内划分出25个等分,也就是每隔1/25秒后显示一帧视频数据。具体的如下图所示:

在FFMPEG中时间基准都是用A VR ational结构体来表示:
cpp
typedef struct AVRational{
int num; ///< Numerator
int den; ///< Denominator
} AVRational;
num:表示分子(numerator的缩写)
den:表示分母(denominator的缩写)
在视频处理中,时间基通常以帧率为单位。例如对于25帧的视频,FFmpeg使用AVRational video_timebase = {1, 25}来表示。
在音频处理中,时间基则以采样率为单位。比如48000Hz的音频采样率,FFmpeg会表示为AVRational audio_timebase = {1, 48000}。
对于封装格式来说:flv 封装格式的 time_base 为{1,1000},ts 封装格式的 time_base 为{1,90000}

从ffplay输出的信息中可以看到多个关于时间基的说明:
-
tbr:表示基准帧率,通常情况下tbr与fps数值一致
-
tbn:表示视频流的时间基,例如:
- TS格式数据的时间基为90000
- FLV格式视频流的时间基为1000
-
tbc:表示视频编解码器的时间基,该值通常是帧率的两倍。例如:
- 当帧率为25fps时,tbc值为50
2 .2. 时间戳(PTS、DTS):

时间戳表示在时间轴上所占的刻度数量,其单位并非具体秒数,而是时间刻度。只有将时间基与时间戳结合使用时,才能准确表达具体时间。
例如: 假设有一把刻度尺:
- pts = 25个刻度
- time_base = {1,25}(每个刻度为1/25厘米) 则尺子总长度 = pts × time_base = 25 × 1/25 = 1厘米
视频PTS计算: PTS(Presentation Time Stamp)用于确定解码后视频帧的显示时机。计算公式为:
- n:第n帧视频
- timebase:{1, framerate}
- fps:帧率 pts = n × ((1/timebase)/fps) pts = pts++
示例: n=1, pts=1
n=2, pts=2
n=3, pts=3
音频PTS计算:
- n:第n帧音频
- nb_samples:采样个数(AAC默认1024)
- timebase:{1, samplerate}
- samplerate:采样率(如48000) num_pkt = samplerate/nb_samples
pts = n × ((1/timebase)/num_pkt)
pts = pts+1024
示例(samplerate=48000, nb_sample=1024): n=1, pts=1024
n=2, pts=2048
n=3, pts=3072
注:时间基和时间戳必须配合实用才能具体表达时间否则没用,例如时间戳就好像数字(1,2,3,4,5)但并没有具体的单位,时间基就比如是单位(例如美元,日元 ,人民币),所以这两个必须两个配合实用才行
2.3. D ****TS:****表示的是压缩解码的时间戳,在没有B帧的情况下PTS 等于 DTS。假设编码的里面引入了B帧,则还要计算B帧的时间。
没有B帧:dts = pts
存在B帧:dts = pts + b_time
三.时间转换原理
在FFMPEG中,不同复合流的时间基可能不一致。例如,FLV格式的时间基time_base为{1,1000},而某个视频流的时间基可能是{1,25}。当需要合成MPEGTS文件时,就需要将{1,25}时间基下的时间信息转换为{1,1000}时间基下的表示方式。
在F FMPEG 中用以下的A PI 进行时间基转换:
cpp
/**
* Convert valid timing fields (timestamps / durations) in a packet from one
* timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
* ignored.
*
* @param pkt packet on which the conversion will be performed
* @param tb_src source timebase, in which the timing fields in pkt are
* expressed
* @param tb_dst destination timebase, to which the timing fields will be
* converted
*/
void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);
参数说明:
-
第一个参数:AVPacket结构体指针
-
第二个参数:源时间基
-
第三个参数:目标时间基
功能说明:
该API用于将AVPacket的时间基从tb_src转换为tb_dst。以下是H264和AAC时间基转换的示例:
视频H264时间基转MPEGTS时间基:
**转换公式:DST_VIDEO_PTS = VIDEO_PTS * VIDEO_TIME_BASE / DST_TIME_BASE**
H264时间基{1,25} → FLV时间基{1,1000}:
**- 输入pts=1 → 输出pts=40
- 输入pts=2 → 输出pts=80 (经av_packet_rescale_ts转换)
- 输入pts=3 → 输出pts=120
- 输入pts=4 → 输出pts=160**
音频AAC时间基转FLV时间基:
**转换公式:DST_AUDIO_PTS = AUDIO_PTS * AUDIO_TIME_BASE / DST_TIME_BASE**
AAC时间基{1,48000} → FLV时间基{1,1000}:
**- 输入pts=1024 → 输出pts≈21.3
- 输入pts=2048 → 输出pts≈42.6 (经av_packet_rescale_ts转换)
- 输入pts=3072 → 输出pts≈64
- 输入pts=4096 → 输出pts≈85.3**
结论:
-
视频时间基转换实质是执行公式:DST_VIDEO_PTS = VIDEO_PTS * VIDEO_TIME_BASE / DST_TIME_BASE
-
音频时间基转换实质是执行公式:DST_AUDIO_PTS = AUDIO_PTS * AUDIO_TIME_BASE / DST_TIME_BASE
图解:
