關于Android VideoView seekTo不準確的解決方案

本文章為原創(chuàng),轉載時請注明出處


實現 Android 的視頻播放,通常有以下幾種方式

1.使用自帶的播放器,指定 ActionACTION_VIEW,DataUri,Type 為其 MIME 類型。
2.使用 VideoView 來播放,在布局文件中使用 VideoView 結合
MediaController 來實現對其控制。
3.使用 MediaPlayer 類和 SurfaceView 來實現,這種方式很靈活。

使用 VideoView 播放視頻的步驟:

1.在界面布局文件中定義 VideoView 組件,或在程序中創(chuàng)建
VideoView 組件
2.調用 VideoView 的如下兩個方法來加載指定的視頻

setVidePath(String path) // 加載path文件代表的視
setVideoURI(Uri uri) // 加載uri所對應的視頻

3.調用 start()、stop()、pause()方法來控制視頻的播放
4.通過與 MediaController 類結合使用,開發(fā)者可以不用自己控制播放與暫停

調用 seekTo 方法跳轉不準的問題

典型場景:

當用戶從后臺恢復播放界面時,需要跳轉到之前退出的時間點繼續(xù)播放原來的視頻。其實現邏輯大致上是:

  1. 在暫停時保存當前 VideoViewcurrantPosition 進度
  2. 恢復播放時,調用 seekTo 方法,傳入 currantPosition 作為跳轉參數

按照官方提供的 API 來看,這是最合理的使用方式。但在某些情況下,我們會遇到視頻恢復播放時進度位置不準的問題,甚至有些會重頭開始播放。
下面就針對使用 VideoView 播放視頻時 seekTo 跳轉不準的問題進行分析。

問題定位

1. 消除方法異步執(zhí)行的影響

首先明確一點: *** VideoViewseekTo 方法是異步執(zhí)行的***,因此會有 seek 未完成但播放已經開始的現象。需要消除 seekTo 對恢復播放的影響,應該在 seek 操作完成的 seekComplete 回調方法中執(zhí)行 ViedeoViewstart 方法。

Tip: seekComplete 屬于 MediaPlayer 類的 OnPreparedListener 監(jiān)聽器的一個回調方法。雖然 VideoView 是基于 MediaPlayer 實現的,但沒提供 setOnSeekCompleteListener 設置監(jiān)聽器的方法,所以我們要拿到 VideoView 內部持有 MediaPlayer 對象。

// 設置 VideoView 的 OnPrepared 監(jiān)聽,拿到 MediaPlayer 對象。
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
            //設置 MediaPlayer 的 OnSeekComplete 監(jiān)聽
                mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
                    @Override
                    public void onSeekComplete(MediaPlayer mp) {
                    // seekTo 方法完成時的回調
                        if(isPause){
                            videoView.start();
                            isPause = false;
                        }
                    }
                });
            }
        });
2. 消除視頻源的問題

其實 seekTo 跳轉的位置其實并不是參數所帶的 position,而是離 position 最近的視頻關鍵幀。

關于視頻關鍵幀建議大家可以去了解一下相關知識,大致上就是視頻播放時需要從一個關鍵幀的位置開始。

所以當視頻在跳轉到相應的 position 位置缺少關鍵幀的情況下,調用 seekTo 方法是無法在當前位置開始播放。這時會尋找離指定 position 最近的關鍵幀位置開始播放。

關于視頻源造成的問題,可以采取以下解決措施:

  • 替換成滿足需求的視頻源文件(尋找合格的視頻文件)
  • 對視頻源文件進行處理,增加其關鍵幀數量,比如可以1s設置一個關鍵幀(基于目前已有的視頻文件進行處理)。

如果選擇第二種方式,要增加視頻的關鍵幀數量,可以推薦大家使用FFmpeg進行增加關鍵幀的處理工作。 http://ffmpeg.org/

FFmpeg 工具相關命令行語句:
ffmpeg.exe -i "D:\in.mp4" -c:v libx264 -preset superfast -x264opts keyint=25 -acodec copy -f mp4 "D:\out.mp4"

命令語句大致意思是:在 D 盤路徑下把 in.mp4 視頻文件每隔 25 幀設置一個關鍵幀,音軌保持原視頻參數,其余使用 FFmpeg 提供的default 值,最后保存為 out.mp4 文件到 D 盤。


總結

在深究問題的原因時不可淺嘗而止,也不要一味的懷疑是不是代碼造成了問題。很多情況下都選擇盲目地替換不同的視頻組件出實現,而忽略了視頻源文件本身的問題。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容