1. 问题
通过ffmpeg转换不同清晰度后,前端通过video.js加载m3u8文件后,客户端切换标清与原画发现总时长不一致,如图
2. 分析
前端如何得到总时长呢?
m3u8参数
一级索引和二级索引中,给出的地址可能是相对地址/绝对地址。相对地址根据一级索引的地址更改。
通常一级索引会给出不同带宽的下载链接,可以根据网速适配不同的下载链接,从而避免卡顿。
流格式可能是.ts .aac或者RFC支持的其他格式。
m3u8参数
- EXTINF:播放时间长度,单位s
- BANDWIDTH:带宽
- EXT-X-ENDLIST:有这个参数,说明是点播,是完整的一段音频或者视频;没有这个参数,说明是直播,需要不断从二级索引中去获取下一片段的链接
- EXT-X-MEDIA-SEQUENCE(可选): 播放列表的第一个音频的序号,如64.m3u8中,有3个音频,序号分别是12591742,12591743,12591744。如果不设置,默认为第一个音频链接序号为0。可以没有这个参数
- EXT-X-KEY:可能是加密的,具体见RFC
- EXT-X-TARGETDURATION:每片最大时长,单位s, #EXTINF应该小于这个值
- 更多参数参考中文链接:http://www.dnsdizhi.com/m/?post=242
由以上得知,前端通过每片ts的时长累加得到最终时长;
贴下当前转换的参数:
原画转换参数
-i 97CB2FFDF74149FE83974352D78B8B09.avi -codec:a aac -async 2 -ar 44100 -codec:v libx264 -g 30 -vsync 2 -hls_time 10 -hls_list_size 0 -threads 2 -max_muxing_queue_size 9999 -y /sysvol/cache/97CB2FFDF74149FE83974352D78B8B09-1629884714-tmp-od.m3u8
标清转换参数
-i 97CB2FFDF74149FE83974352D78B8B09.avi -codec:a aac -async 2 -ar 44100 -codec:v libx264 -g 30 -profile:v 0 -i_qfactor 0.71 -partitions +parti4x4+partp8x8+partb8x8 -qmax 51 -qmin 10 -qdiff 4 -b:v 256k -maxrate 256k -bufsize 256k -bt 512k -me_range 16 -trellis 1 --pix_fmt yuv420p -movflags faststart -hls_time 10 -hls_list_size 0 -threads 2 -max_muxing_queue_size 9999 -y /sysvol/cache/97CB2FFDF7sd.m3u8
使用原画及标清转换后得到的分片都为14片,但是EXT-X-TARGETDURATION不同,所以两组转换后不一样,导致前端显示总时长不一致
原画下,EXT-X-TARGETDURATION为12
标清下, EXT-X-TARGETDURATION为6
其中hls_time是控制每片时长,那先从该参数入手,查阅到如下解答:
使用FFmpeg命令进行hls切片,得到的ts文件时长不准确
可是调整后还是没有达到理想效果
3. 问题解决
经查阅相关资料及测试发现问题所在
发现参数中 -r 设置了每秒帧率,经测试当帧率为15时是正常的,当前设置为30,当测试该值变化时,最终的时长也会受影响;
最终去掉 -r 参数,使用默认值,总时长保持一直,原画和标清的转换后大小及清晰度也正常;
4. 当前问题
可能自己对ffmpeg没有深入研究,所以以上解决方式有问题还希望大佬多多提提建议及沟通讨论。