赞
踩
今天TV产品优化,发现一个难以修改的问题,使用gsyVideoPlayer的时候,切换的是系统内核播放视频,然后遥控器在控制快进快退的时候会有进度条回退的问题,这对用户就不友好了啊。
调查了之后发现,是因为关键帧的问题,快进的时候是按照视频的关键帧来进行快进的,如果视频背压缩的过于严重会导致视频的关键帧比较少,那么就会出现以下这种情况:
现在播放到8秒,你要快进到18秒,但是视频的关键帧在第15秒,那么进度条就会从18退到15,因为进度条是按照真实的视频进度来进行走动的。
知道了原因之后那么有两种方案:
方案一:从系统内核切换到Exo内核,因为我发现三种内核都测试过之后,Exo内核对于关键帧的处理更好,基本上不会出现快进回退的问题。
方案二:维持原有的系统内核,禁用gsyVideoPlayer原有的进度条展示,自己实现进度条,时间的展示。
采用了之后播放.mp4视频一点问题没有,非常流畅,实现了我想要的效果,但是现网的视频后缀是.m3u8格式的,使用Exo内核播放之后,报了如下错误:
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): Source error.
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): com.google.android.exoplayer2.source.UnrecognizedInputFormatException: None of the available extractors (MatroskaExtractor, FragmentedMp4Extractor, Mp4Extractor, Mp3Extractor, AdtsExtractor, Ac3Extractor, TsExtractor, FlvExtractor, OggExtractor, PsExtractor, WavExtractor, AmrExtractor) could read the stream.
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractorHolder.selectExtractor(ExtractorMediaPeriod.java:927)
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractingLoadable.load(ExtractorMediaPeriod.java:849)
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:320)
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
- 05-18 11:26:07.632: E/ExoPlayerImplInternal(10506): at java.lang.Thread.run(Thread.java:841)
- 05-18 11:26:07.632: E/EventLogger(10506): playerFailed [0.78]
- 05-18 11:26:07.632: E/EventLogger(10506): com.google.android.exoplayer2.ExoPlaybackException
- 05-18 11:26:07.632: E/EventLogger(10506): at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:349)
- 05-18 11:26:07.632: E/EventLogger(10506): at android.os.Handler.dispatchMessage(Handler.java:98)
- 05-18 11:26:07.632: E/EventLogger(10506): at android.os.Looper.loop(Looper.java:136)
- 05-18 11:26:07.632: E/EventLogger(10506): at android.os.HandlerThread.run(HandlerThread.java:61)
- 05-18 11:26:07.632: E/EventLogger(10506): Caused by: com.google.android.exoplayer2.source.UnrecognizedInputFormatException: None of the available extractors (MatroskaExtractor, FragmentedMp4Extractor, Mp4Extractor, Mp3Extractor, AdtsExtractor, Ac3Extractor, TsExtractor, FlvExtractor, OggExtractor, PsExtractor, WavExtractor, AmrExtractor) could read the stream.
- 05-18 11:26:07.632: E/EventLogger(10506): at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractorHolder.selectExtractor(ExtractorMediaPeriod.java:927)
- 05-18 11:26:07.632: E/EventLogger(10506): at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractingLoadable.load(ExtractorMediaPeriod.java:849)
- 05-18 11:26:07.632: E/EventLogger(10506): at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:320)
- 05-18 11:26:07.632: E/EventLogger(10506): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
- 05-18 11:26:07.632: E/EventLogger(10506): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
- 05-18 11:26:07.632: E/EventLogger(10506): at java.lang.Thread.run(Thread.java:841)
- 05-18 11:26:07.632: D/EventLogger(10506): loading [false]
这个报错看了半天,主要意思是说Exoplayer中没有可用的解析器,然后我去找了解决办法,说是需要设置如下代码:
- //EXOPlayer内核,支持格式更多
- PlayerFactory.setPlayManager(Exo2PlayerManager.class);
-
-
- //exo缓存模式,支持m3u8,只支持exo
- CacheFactory.setCacheManager(ExoPlayerCacheManager.class);
试了并不行,不知道是我的问题还是播放器的问题,最后也没找到解决办法,直接放弃。
首选我继承StandardGSYVideoPlayer创建了一个新的Player,然后重写其中的 setTextAndProgress方法,将super.setTextAndProgress(secProgress);方法注释掉即可,运行发现进度条不走,当前时间跟总时间一直在00:00.,然后只需要自己写一个计时器,让进度条每隔1s刷新一次将当前时间跟进度更新掉就好。写到这我就在想另外一个问题,它本身已经写了一个计时器了在更新进度了,我在写一个控制岂不是多余了嘛?本着不重复造轮子的态度,我进行了如下改动:
- /**
- * 处理快进快退问题
- * @param isForward
- */
- public void step(boolean isForward) {
- if (!getGSYVideoManager().isPlaying()) {
- PLog.i("fastForward is not playing");
- getStartButton().callOnClick();
- }
- int videoLength = (int) getGSYVideoManager().getDuration();
-
- if (videoLength == -1) {
- return;
- }
-
- int size = videoLength / LENGTH;// LENGTH快进快退的步长
-
- final int[] postion = new int[size + 2];
- postion[size + 1] = videoLength;
-
- for (int i = 0; i <= size; i++) {
- postion[i] = LENGTH * i;
- }
-
- mBottomContainer.setVisibility(VISIBLE);
-
- if (isForward) { // 快进
-
- if (mCurrentPosition == videoLength) {
- setProgress(videoLength, videoLength);
- return;
- }
-
- for (int i = 0; i < postion.length; i++) {
- if (postion[i] - mCurrentPosition > 0) {
- PLog.i("forwart postion=" + postion[i]);
- setProgress(postion[i], videoLength);
- getGSYVideoManager().seekTo(mCurrentPosition);
- break;
- }
- }
- } else { // 快退
-
- if (mCurrentPosition == 0) {
- setProgress(0, videoLength);
- return;
- }
-
- for (int i = 0; i < postion.length; i++) {
- if (postion[i] - mCurrentPosition >= 0) {
- setProgress(postion[i - 1], videoLength);
- getGSYVideoManager().seekTo(mCurrentPosition);
- break;
- }
- }
- }
- }
-
- /**
- * 快进快退 自己控制 进度条 避免快进 回退问题
- *
- * @param position
- * @param videoLength
- */
- public void setProgress(int position, int videoLength) {
- mCurrentPosition = position;
- int progress = (int) (mCurrentPosition / (videoLength / 100));
- mProgressBar.setProgress(progress);
- mTotalTimeTextView.setText(CommonUtil.stringForTime(videoLength));
- mCurrentTimeTextView.setText(CommonUtil.stringForTime(position));
-
- mHadler.postDelayed(new Runnable() {
- @Override
- public void run() {
- mBottomContainer.setVisibility(GONE);
- }
- }, 500);
- }
-
- @Override
- protected void setTextAndProgress(int secProgress) { // 避免关键帧 回退的问题
- if (!mProgressBar.isShown()) {
- super.setTextAndProgress(secProgress);
- }
- }
我做了一个假象,在进度条展示的时候,我会按照自己分割的关键帧去快进快退,这样控制强行让进度条永远按照你想要的方向走,但是当500ms进度条消失之后,我让进度条按照gsyVideoPlayer原有的计时器进行更新,这样我不仅省了一个计时器并且实现了了想要的效果,进度条在显示的时候永远不会回退,消失之后可能会有稍微回退,但是用户看不到了,问题应该不大。
最后还是希望不要将视频压缩的太过严重,关键帧太少,视频清晰度降低,对用户的体验更不好,在用户能看到的地方一定要将体验做好,可以在看不到的地方做优化,本次优化主要针对于遥控器控制的快进快退,手机开发的小伙伴可以借鉴下思路。
1. https://blog.csdn.net/yhroppo/article/details/104494850
2. github地址 :https://github.com/CarGuo/GSYVideoPlayer
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。