【移動端html5】 android video播放進度精確控制

android上視頻播放存在的問題

在PC上播放html5視頻,設置video.currentTime=5,視頻將跳到5s的位置,並且顯示出第5s的畫面。在安卓下,卻存在下面兩個問題:

  • 在安卓上,爲了省電,在暫停的時候,改變視頻屬性不會刷新畫面,直到你再次播放的時候,這些改變纔會表現出來。所以暫停的時候改變currentTime不會更新畫面,手動改變進度條也不行。
  • 在安卓上,視頻並不是準確的按currentTime播放,可能你設置 currentTime = 5,但是播放出來的內容卻是第8s的。這個問題,用手改變進度條也會出現,可以將視頻拖到60s,在拖回10s,看看播放的內容是否是第10s的。

所以,對於一些需要精確控制視頻進度的情景,比如視頻演示,這兩個問題會造成很大的困擾,因爲android下,沒有辦法很精確的控制視頻進度。

可能並不是所有移動端都存在這兩個問題,沒驗證哪些存在

解決辦法

對於第二個問題,是沒有辦法改變的,這是html5 video的實現問題。但是第一個問題,卻可以通過模擬“暫停下設置視頻進度”解決。

模擬的方式是,先播放視頻,然後將視頻設置到目標時間,當視頻加載出第一幀的時候,暫停視頻,如下:

  1. 播放視頻,監聽playing事件

  2. 觸發playing事件,說明視頻已經開始播放,此時設置currentTime等於目標時間,監聽seeked事件

  3. 觸發seeked事件,在移動端下,seeked事件觸發後,表示已經尋址到了指定時間,但是畫面還沒更新,監聽timeupdate事件

  4. 觸發timeupdate事件,在移動端下,第一次觸發這個事件表示即將更新畫面,此時設置50ms的延遲,因爲一般視頻爲24fps,也就是40ms刷新一幀,50ms的延遲爲了確保第一幀加載出來

  5. 延遲結束,暫停視頻。此時視頻暫停再目標時間,畫面也已經加載出來。

之所以要搞得這麼複雜,是因爲在android下,事件觸發並不是很準確,經觸發了playingtimeupdate事件,但視頻可能都還沒開始播放,但是有這麼幾個規律:

  • 第一,觸發seeked之後的timeupdate的時候,視頻已經很接近播放了
  • 第二,觸發playing後,第2次觸發timeupdate的時候一定已經播放着了,但是觸發兩次timeupdate的間隔比較大,往往視頻已經很明顯的播放一小段。

並非放之四海皆準的規律

下面的代碼就是用這種方式實現的,能夠在android上暫停時設置currentTime,主要看setTime方法:

 /**
 * Created by Administrator on 2017/1/9.
 */
export default class Video{

    constructor(src){
        let uid = new Date().getTime();
        this.id = 'video'+uid;
        this.video = $(`<video id="${this.id}"></video>`).get(0);
        this.status = null; //播放狀態
    }

    play(){
        this.status = "playing";
        this.video.play();
        return this;
    }

    pause(){
        this.status = "paused";
        this.video.pause();
        return this;
    }



   /**
     * 設置視頻當前的事件
     * @param time 時間
     * @returns {Number}
     */
    setTime(time){
        if(this.status == "playing"){
            this.video.currentTime = time;
            console.log("當前視頻時間:"+this.video.currentTime);
            return time;
        }
        /*
         目的:在移動端下加載指定時長的視頻畫面
         移動端下存在的問題:在移動端下,如果不播放視頻,則視頻控件顯示黑屏,此時不可指定視頻當前時間
         解決辦法:在移動端下,設置到指定時長後,播放極小的一段時間,讓視頻控件顯示出當前的畫面,然後暫停,看起來就像直接指定時間一樣
         實現說明:
         1、監聽playing事件,並在其中監聽seeked和timeupdate事件,兩個事件都觸發後,視頻一般接近或已經開始播放了,
         然後再設置50ms的延遲,一般可保證視頻播放
         2、在setTime執行的過程中,有可能外部已經更改了視頻播放的狀態(通過調用this.play()或this.pause()),
         因此設置一個status字段,保存外部的操作
         */
        let that = this;
        that.video.play();
        $(that.video).one("playing",function(){
            that.video.currentTime = time;
            $(that.video).one("seeked",function(){
                $(that.video).one("timeupdate",function(){
                    clearTimeout(that.timeout);
                    that.timeout = setTimeout(()=>{
                        console.log("當前視頻時間:"+that.video.currentTime);
                        if(that.status == "playing"){
                            that.video.play();
                        }else{
                            that.video.pause();
                        }
                    },that.delay);
                });
            })
        })
        return time;
    }


}

一些鏈接

video標籤在不同平臺上的事件表現差異分析

Jumping to time offsets in HTML5 video

移動端HTML5視頻播放優化實踐

html5 video seekable屬性

【W3C】 HTML DOM Video 對象

【MDN】video標籤

視頻播放的那些事

html5–移動端視頻video的android兼容,去除播放控件、全屏等

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章