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"); //起始帧号

     //输出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 ", j,begin_pts,end_pts);

      //转换成时间戳输出,格式:s    
     double begin_timestamp = (double)((begin_pts-first_frame_pts)*time_base_num)/(double)time_base_den;
     double end_timestamp = (double)((end_pts-first_frame_pts)*time_base_num)/(double)time_base_den; 
     System.out.printf("track %d time(sec):%f,%f ", 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 ", j,begin_second,begin_pts_t,end_second,end_pts_t);
   
原文地址:https://www.cnblogs.com/yangxiayi1987/p/13223063.html