Android之MediaPlayer加载视频慢
时间:2022-11-16 15:00:00
问题:Android系统播放器MediaPlayer播放网络视频,慢慢加载...缓冲慢...
结论:视频元数据位置错误
简单的解释是,大多数视频格式都是MP4,MP4格式视频是由一个接一个的Box组成Box可理解为数据块。Box里面可以嵌套Box:
ftyp,moov,mdat就是Box这里需要关注的是名字。moov和mdat两个Box。
moov是视频的元数据,存储视频的整体信息、时间、码率、宽度等
mdat是我们播放的具体媒体数据
(如果哥们想自己体验一下, mac可以用MediaParaser, window用Mp4Info)
下面这句话很关键
获取播放器moov box开始播放视频!
获取播放器moov box开始播放视频!
获取播放器moov box开始播放视频!
这句话是这篇文章的核心。可以忽略,至少记住这一点
所以关于播放器加载视频慢的原因,上图是理想状态下的视频box的位置。
但是当一些视频被压制时,它们会被压制moov box放在视频尾部,也就是mdat之后。这导致播放器必须下载整个视频才能获得moov box,然后才能播放。
相当于你和姐姐约会。刚见面的老板说网上有问题让你解决。你解决后,继续约会。看看姐姐会不会当场和你分手。
方案一
直接原因是找到了。聪明的兄弟会问另一个问题
既然moov box为什么有些视频把它放在最后?
我做了实验,发现ffmpeg在转换视频格式时,默认会moov box放在视频的尾部。我猜是。ffmpeg只有在转换完整的视频后,我们才能确切地知道新视频的长度、代码率和其他信息,所以我们可以把它放在新视频的结尾。
ffmpeg它还提供了移动moov box命令到视频头部
ffmpeg -i input.mp4 -c copy -f mp4 -movflags faststart output.mp4
这不是解决方案之一吗?
试试新视频,加载时间真的变成了2~3秒了
真相大白!!!!!!相大白!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
方案二
就在我准备和姐姐交流感情的时候,产品阿姨告诉我,我们有几万个视频,项目马上就要上线了。谁给你时间一个一个转换?你说,你说!
我是个打工人.. 别骂我嘛..
在实际开发中,会有各种各样的情况无法修改视频源。这时,我们只能自己想办法。
视频播放的前提是获得moov box,而视频源moov box在尾巴,我们能吗?
先请求视频尾部获取moov box,然后从头要求视频?
当然可以。流媒体的请求不是一次性的,而是分片的。 先发起一个http请求,读取响应body如果发现开头moov开头继续往下读mdat。如果没有发现,第二个请求可以直接读取文件末尾的数据,这样也可以通过两个请求获得moov。该方案要求服务端支持Request-Range请求,即可通过Range直接读取文件的尾部,但一般oss支持所有服务。
这个方案可以!但是我想重写一遍吗?MediaPlayer请求??姐姐怎么办?
转念一想,这个问题应该很普遍,聪明的哥们一定已经填坑了。所以我用它ijkPlayer和exoPlayer分别测试,果然这两个播放器已经处理好了这种情况,直接更换就好。ijkPlayer的官方so库不支持https所以最后采用了请求exoPlayer