问题: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的请求??那我的妹妹怎么办?!文章来源:https://www.toymoban.com/news/detail-412239.html
转念一想,这个问题应该很普遍,聪明的哥哥们一定已经填过坑了。于是我用ijkPlayer和exoPlayer分别测了一下,果然这两个播放器都已经对这种情况做了处理,直接替换就好。ijkPlayer的官方so库不支持https请求,于是最终采用了exoPlayer文章来源地址https://www.toymoban.com/news/detail-412239.html
到了这里,关于Android之MediaPlayer加载视频慢的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!