ffmpeg视频文件PTS与时间戳,帧号的换算
ffmpeg中的pts,dts,duration时间记录都是基于timebase换算,很多刚接触ffmpeg的同学都不容易搞清楚它的时间计算方法。
我们先看下ffmpeg时间是怎么算的:
一帧图像(音频)的时间戳(时间戳一般以第一帧为0开始,但也有很多首帧不是从0开始,这里用first_frame_pts表示)
时间戳 = pts * (AVRational.num/AVRational.den) ,这里的pts是相对pts = 绝对PTS - 首帧PTS
看下ffmpeg的说明:
“当有理数用浮点数做转换时是有损的,ffmpeg要求高精度的计算的时间戳,所以用分数来做换算”。
我们在看下换算用到的结构体,一看到他是用分数就容易理解了
typedef struct AVRational{
int num; ///<分子
int den; ///< 分母
} AVRational;
其实当num=1,den=1000的时候pts的时间单位就相当于毫秒 1/1000秒
其实当num=1,den=1000000的时候pts的时间单位就相当于微秒 1/1000000秒
时间换算
比如我们要通过ffmpeg实现直播推流,推流一个文件,文件中的时间基数一般是{ num=1,den=1000000} ,推流用的正常是timebase {num=1,den=1000}。那就可以做如下计算:
推流的pts = 文件pts * 文件timebase / 推流timebase
如果手动计算要判断分母是否为0,不然会造成程序宕掉。当然ffmpeg内部也提供了转换的函数
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;
下面是我根据我们业务系统定义的JSON文件,对文件内容进行了PTS到时间戳的转换,采用JAVA实现如下:
// metadata,视频流信息
int fps = video_results.getJSONObject("metadata").getIntValue("fps"); //帧率
int time_base_num = video_results.getJSONObject("metadata").getIntValue("time_base_num"); //时间戳基数:分子
int time_base_den = video_results.getJSONObject("metadata").getIntValue("time_base_den"); //时间戳基数:分母
int first_frame_pts = video_results.getJSONObject("metadata").getIntValue("first_frame_pts"); //起始帧号
int begin_pts = track_results.getJSONObject(j).getJSONArray("faces").getJSONObject(0).getIntValue("pts"); //开始PTS
int end_pts = track_results.getJSONObject(j).getJSONArray("faces").getJSONObject(1).getIntValue("pts"); //结束PTS
System.out.printf("track %d pts:%d,%d\n", j,begin_pts,end_pts);
//转换成时间戳输出,格式:s
System.out.printf("track %d time(sec):%f,%f\n", j,begin_timestamp,end_timestamp);
//输出格式:秒+帧
int begin_frame = (begin_pts-first_frame_pts)*fps*time_base_num/time_base_den;
int end_frame = (end_pts-first_frame_pts)*fps*time_base_num/time_base_den;
int begin_second = begin_frame/fps; //秒
int begin_pts_t = begin_frame - begin_second*fps;
int end_second = end_frame/fps; //秒
int end_pts_t = end_frame - end_second*fps;
System.out.printf("track %d time(sec.frame):%d.%d,%d.%d\n", j,begin_second,begin_pts_t,end_second,end_pts_t);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现