音视频问题汇总--播放器seekto功能优化
共 1931字,需浏览 4分钟
·
2022-02-09 17:35
最近工作中碰到一个问题,关于播放器播放一段视频的需求,因此查找了一些方案,在此记录一下。
背景介绍
客户在设备上把一段视频(好了,就是广告了)当作屏保进行播放,但是点击屏幕进入系统时时要退出屏保播放,进入我们的应用,然后再次进入屏保时继续进行视频播放,并且要从上次退出时播放的位置顺序播放向后循环播放。
这样一段需要,本身用Android自带的MediaPlayer或者MediaCodec进行即可播放,但是涉及到再次进入屏保应用时,还要seekto到上次播放的位置,这里就出现一个seekto不准的小问题,客户无法接受。接触音视频比较多的童鞋都知道,当要seekto到一个位置时,当前帧可能不是关键帧。所以要从该位置播放时就需要从该帧之后最近的一个关键帧开始,这时播放的位置可能不是客户想要的。假设上次播放退出时是00:00:57的位置,但是离这个位置最近是在00:00:59的位置,这时MediaPlayer播放的位置是从00:00:59开始的,客户说这个差距太大了,无法接受。那既然是恰饭人,只能想办法满足客户的需求了。那就从Seekto开始一次冒险之旅吧。
SeekTo介绍
Android播放器自己维护一个状态机,如下图:
如果不熟悉的,建议自行补救
官网描述:播放时,可以通过seekto调整播放的位置,API 26之前只需要一个参数int msec,但是API 26之后则需要传入两个参数(long msec, int mode)。两个参数分别为时间戳和跳转模式。
Tips:查看MediaPlayer的状态图可以看到seekTo可以在其他状态下调用,例如Prepared,Paused和PlaybackCompleted状态。 在这些状态下调用seekTo时,如果流中有视频并且请求的位置有效,则将显示一个视频帧。
关键帧
学习过视频压缩概念的都知道:在视频压缩概念中,视频序列的每帧都代表一幅未压缩的静止图像。而在传输或者存储时,会采取各种算法或者标准进行数据压缩,以便能够最大可能的减少数据的冗余容量。而在播放的时候就是解压缩或者解码过程。其中涉及到视频帧的类型有I帧、P帧、B帧,这些就是最常见的,最基本的概念。
简单地说,I帧是关键帧,一般属于帧内压缩、帧内编码,独立主义者,不依赖其他视频帧。而P帧是向前搜索的意思,它需要向前找离它最近的I帧作为参考后进行解码。B是双向搜索,就是需要向前、向后两个方向进行参考再进行解码。P帧和B帧都是基于I帧来压缩数据。
参考别的大牛画的图:
其他相关概念大家自行补充,不再累述。
解决方案
现在大家基本上对该问题有一点了解了,剩下就是解决掉他,盘他。
方案一:
最初,我们查找谷歌的官网,看是否有足够的api可以调用,最小化的代价解决该问题,就查到了seekto的不同模式切换的描述,选择SEEK_CLOSEST进行尝试,有效果,但是给客户看了一下,客户点了一下头,但是略有不甘,是否可以更好呢?
方案二:
只能再查资料,重新确定方案了,Google过程中有发现以下大佬做的优化,
我们也进行尝试,但是如果仅仅针对一个文件,到时还可以进行FFMPEG转换,增加I帧的方式进行提升,但是屏保广告,客户定期会更换的呀。总不能每次都进行转换吧?
客户点了半下头转摇头了。
方案三:
这时我们重新分析流程,查看客户使用场景,分析我们应用之间的调用关系,然后整理思路。。。。
噔 噔噔噔(windows XP开机了)
因为屏保进入和退出都是由我们自己控制的,无非退出时将屏保activity放置后台了,那我们可以将MediaPlayer尽心pause动作,再次进入时进行restart操作,就实现原地暂停、原地播放的效果了?如果后台activity被回收、或者异常退出,则用第一种方案seekto到比较近的地方进行播放。这样既可以实现快速进入快速查看,异常退出也可以比较近的位置查看效果。
之后我们紧急做了demo,并演示给客户看,客户点了三下头。貌似接受了。
到此这个问题就处理完成。
总结
作为职场恰饭人,客户就是上帝,这个句话属于被迫的,也是我们前进的动力,当我们无法改变时,只能快速排查,寻找最优的解决方案。
碰到问题时:
第一,先查官网,毕竟类似问题可能官网已经有解决方案了。
第二,无法满足时,及时分析使用场景,查看是否用其他的方案来绕过该难点问题,不断切割使之变成新的更小、更容易的问题,这样处理难度就会降低。
点赞、评论、私信、关注、转发,随时可以探讨,持续输出。