关于时间戳的那些事

1.先来看看简单点的

2.按照采样率计算

A、视频pts

视频比较好理解,就是每帧递增,假如fps是25帧的,时间基为fps的倒数1/25,那么pts递增即可。
如下:
第一帧:pts=0
第二帧:pts=1
第三帧:pts=3
第n帧:pts = n - 1;
。。。以此类推
计算公式为:第n帧的pts = n * ((1 / timbase)/ fps);
B、音频pts
音频相对来说更难理解一些,因为音频的一个packet不止一帧,所以一秒到底有多少个packet就不知道,就别说如何计算pts了。
假设音频一秒有num_pkt个packet,那么这个num_pkt到底是多少?
这的从音频基础开始说起,我们知道音频有个采样率,就是一秒钟采用多少次,很多音频都是44100的采样率,也有8k的,那么这个采样率和num_pkt有什么关系呢?
我们发现在AVFrame中有一个比较重要的字段叫做nb_samples,这个字段名为采样数,此字段可以结合音频数据格式计算这个frame->data有多大,其实这个字段联合采样率还可以计算音频一秒有多少个packet。
计算公式如下:
num_pkt = 采样率 / nb_samples;
这样我们就知道了音频每秒的包数目(可以见到理解为帧),有了此数据计算pts就和视频一模一样了,
计算公式如下:
第n个包的pts = n * ((1 / timbase)/ num_pkt);
很多音频时间基和采样率成倒数,那么根据公式我们的音频pts就可以很简单的以nb_samples递增了,如下:
第一个包:pts = 0 * nb_samples;
第二个包:pts = 1 * nb_samples;
第三个包:pts = 2 * nb_samples;
第n个包:pts = (n - 1) * nb_samples;
注:以上说的timebase为AVStream里的timebase。
通过avpriv_set_pts_info(st, 33, 1, 90000)函数,设置AVStream->time_base为1/90000。为什么是90000?因为mpeg的pts、dts都是以90kHz来采样的,所以采样间隔为1/90000秒。

3.音视频同步

(一个AAC原始帧包含一段时间内1024个采样及相关数据)根据aac文档

分析:

1 AAC

音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率(单位为s)

一帧 1024个 sample。采样率 Samplerate 44100KHz,每秒44100个sample,

所以 根据公式

     音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率

(NOTE:该时间可作解码时间的参考,解码时间应偏差确保在该时间的一定范围,异常的话,做一定的异常处理)

如,当前AAC一帧的播放时间是= 1024*1000000/44100= 22.32ms(单位为ms)

当前AAC一帧的播放时间是= 1024/44100 = 0.02232 s(单位为秒)=22.32ms(单位为ms)

反过来,如当想通过音频缓冲多少ms来计算实际应缓冲多少个音频帧时,可下计算:

比如对48K缓冲300ms需要多少个buffer,

buffer = 一秒内能产生多少个音频帧(48000/1024) 乘以 时间比例(300/1000) = (48000*300)/(1024*1000) = 14.0625个。

 

2 MP3

mp3 每帧均为1152个字节, 则:

frame_duration = 1152 * 1000000 / sample_rate

例如:sample_rate = 44100HZ时, 计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来。

 

===============================================================================================


### 时间戳的概念及其生成和使用 时间戳是一种用来表示某一时刻或件发生时的时间值,通常是一个数字或字符串,表示从一个特定的起始时间点(如 UNIX 时间戳的起始时间为 1970 年 1 月 1 日 UTC)到当前时刻所经过的时间量[^1]。 #### C# 中生成时间戳的方法 在 C# 中可以通过计算当前时间和 Unix 起始时间之间的差值来生成时间戳。以下是一个示例代码: ```csharp public virtual string GetTimestamp() { DateTime currentTime = DateTime.Now; DateTime epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); TimeSpan timeSpan = currentTime.ToUniversalTime() - epochTime; long timestamp = (long)timeSpan.TotalSeconds; return timestamp.ToString(); } ``` 此方法返回的是一个 10 位整数形式的时间戳,精确到秒级别[^2]。 #### Python 中生成时间戳并应用其生成文件名 在 Python 中可以利用 `datetime` 和 `time` 模块轻松生成时间戳,并将其应用于各种场景,例如生成带有唯一性的文件名。以下是具体实现方式: ```python import datetime import os def generate_timestamp_filename(prefix="file_", suffix=".txt"): now = datetime.datetime.now() timestamp = int(now.timestamp()) # 获取当前时间戳 filename = f"{prefix}{timestamp}{suffix}" return filename filename = generate_timestamp_filename() print(f"Generated Filename: {filename}") ``` 这段代码通过调用 `now.timestamp()` 方法获得当前时间戳,并以此为基础构建具有唯一名称的文件路径[^3]。 #### 随机数种子初始化中的时间戳应用 除了直接作为时间标记外,时间戳还常被用作随机数生成器的种子值。由于时间戳会随时间不断改变,因此非常适合用于设置初始状态下的伪随机序列。下面展示了一种基于 C 的简单例子: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> int main(){ srand((unsigned)time(NULL)); // 使用时间戳初始化随机数种子 printf("%d\n", rand()); return 0; } ``` 这里展示了如何利用标准库函数 `time` 来获取当前时间戳,并传递给 `srand` 函数完成随机化过程[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值