在视频点播中,M3U8已经广为使用,为了节省用户观看视频前期的等待时间,我们一般将M3U8中前面2~3个切片使用较短的切片时间,这样用户可以更快的完成下载,提高用户体验。本文即介绍如何修改ffmpeg支持非定长的M3U8文件切片。
通过ffmpeg可以轻松实现对文件的M3U8切片,命令如下:
<pre name="code" class="cpp"> ./ffmpeg -i 1939211.ts -y -vcodec copy -acodec copy -map 0 -f segment -segment_list 1939211.m3u8 -segment_time 10 1939211-%03d.ts
使用-segment_time指定了每片的时长为10秒(实际会受视频中IDR帧的间隔影响)
怎样实现前2片时间为5秒呢?
修改ffmpeg源码方能实现,具体为:
/ffmpeg/libavformat/segment.c中
static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)函数
修改指定区域代码如下:
if (seg->use_clocktime) {
int64_t avgt = av_gettime();
time_t sec = avgt / 1000000;
localtime_r(&sec, &ti);
usecs = (int64_t)(ti.tm_hour * 3600 + ti.tm_min * 60 + ti.tm_sec) * 1000000 + (avgt % 1000000);
wrapped_val = usecs % seg->time;
if (seg->last_cut != usecs && wrapped_val < seg->last_val) {
seg->cut_pending = 1;
seg->last_cut = usecs;
}
seg->last_val = wrapped_val;
} else {
//modify start
//前面两个片使用5秒
int64_t t;
int ret = 0;
ret = av_parse_time(&t, "5", 1);
if (ret >= 0)
{
if((seg->segment_count == 0) || (seg->segment_count == 1))
{
end_pts = t * (seg->segment_count + 1);
}
else
{
end_pts = t*2 + seg->time * (seg->segment_count - 1);
}
}
else
{
av_log(s, AV_LOG_ERROR, "av_parse_time failed file:%s, line:%d!\n", __FILE__, __LINE__);
end_pts = seg->time * (seg->segment_count + 1);
}
//modify end
}
这里写死了前面2片长度为5秒,为了使用灵活建议新增专用的ffmpeg参数。