01.視頻播放器框架介紹

視頻播放器介紹文檔

目錄介紹

  • 01.該視頻播放器介紹
  • 02.視頻播放器功能
  • 03.視頻播放器架構說明
  • 04.視頻播放器如何使用
  • 05.播放器詳細Api文檔
  • 06.播放器封裝思路
  • 07.播放器示例展現圖
  • 08.添加自定義視圖
  • 09.視頻播放器優化處理
  • 10.播放器問題記錄說明
  • 11.性能優化和庫大小
  • 12.視頻緩存原理介紹
  • 13.查看視頻播放器日誌
  • 14.該庫異常code說明
  • 15.該庫系列wiki文檔
  • 16.版本更新文檔記錄

00.視頻播放器通用框架

  • 基礎封裝視頻播放器player,能夠在ExoPlayer、MediaPlayer,聲網RTC視頻播放器內核,原生MediaPlayer能夠自由切換
  • 對於視圖狀態切換和後期維護拓展,避免功能和業務出現耦合。好比須要支持播放器UI高度定製,而不是該lib庫中UI代碼
  • 針對視頻播放,音頻播放,播放回放,以及視頻直播的功能。使用簡單,代碼拓展性強,封裝性好,主要是和業務完全解耦,暴露接口監聽給開發者處理業務具體邏輯
  • 該播放器總體架構:播放器內核(自由切換) + 視頻播放器 + 邊播邊緩存 + 高度定製播放器UI視圖層

01.該視頻播放器介紹

1.1 該庫說明

播放器功能 MediaPlayer ExoPlayer IjkPlayer RTC TXPlayer
UI/Player/業務解耦 支持 支持 支持
切換視頻播放模式 支持 支持 支持
視頻無縫切換 支持 支持 支持
調節播放進度 支持 支持 支持
網絡環境監聽 支持 支持 支持
滑動改變亮度/聲音 支持 支持 支持
設置視頻播放比例 支持 支持 支持
自由切換視頻內核 支持 支持 支持
記錄播放位置 支持 支持 支持
清晰度模式切換 支持 支持 支持
重力感應自動進入 支持 支持 支持
鎖定屏幕功能 支持 支持 支持
倍速播放 不支持 支持 支持
視頻小窗口播放 支持 支持 支持
列表小窗口播放 支持 支持 支持
邊播邊緩存 支持 支持 支持
同時播放多個視頻 支持 支持 支持
仿快手預加載 支持 支持 支持
基於內核無UI 支持 支持 支持
添加彈幕 支持 支持 支持
全屏顯示電量 支持 支持 支持

1.2 該庫功能說明

類型 功能說明
項目結構 VideoCache緩存lib,VideoKernel視頻內核lib,VideoPlayer視頻UIlib
內核 MediaPlayer、ExoPlayer、IjkPlayer,後期接入Rtc和TXPlayer
協議/格式 http/https、concat、rtsp、hls、rtmp、file、m3u八、mkv、webm、mp三、mp4等
畫面 調整顯示比例:默認、16:九、4:三、填充;播放時旋轉畫面角度(0,90,180,270);鏡像旋轉
佈局 內核和UI分離,和市面GitHub上大多數播放器不同,方便定製,經過addView添加
播放 正常播放,小窗播放,列表播放,仿抖音播放
自定義 能夠自定義添加視頻UI層,能夠說UI和Player高度分離,支持自定義渲染層SurfaceView

02.視頻播放器功能

  • A基礎功能java

    • A.1.1 可以自定義視頻加載loading類型,設置視頻標題,設置視頻底部圖片,設置播放時長等基礎功能
    • A.1.2 能夠切換播放器的視頻播放狀態,播放錯誤,播放未開始,播放開始,播放準備中,正在播放,暫停播放,正在緩衝等等狀態
    • A.1.3 能夠自由設置播放器的播放模式,好比,正常播放,全屏播放,和小屏幕播放。其中全屏播放支持旋轉屏幕。
    • A.1.4 能夠支持多種視頻播放類型,好比,原生封裝視頻播放器,還有基於ijkPlayer封裝的播放器。
    • A.1.5 能夠設置是否隱藏播放音量,播放進度,播放亮度等,能夠經過拖動seekBar改變視頻進度。還支持設置n秒後不操做則隱藏頭部和頂部佈局功能
    • A.1.6 能夠設置豎屏模式下全屏模式和橫屏模式下的全屏模式,方便多種使用場景
    • A.1.7 top和bottom面版消失和顯示:點擊視頻畫面會顯示、隱藏操做面板;顯示後不操做會5秒後自動消失【也能夠設置n秒消失時間】
  • B高級功能android

    • B.1.1 支持一遍播放一遍緩衝的功能,其中緩衝包括兩部分,第一種是播放過程當中緩衝,第二種是暫停過程當中緩衝
    • B.1.2 基於ijkPlayer,ExoPlayer,Rtc,原生MediaPlayer等的封裝播放器,支持多種格式視頻播放
    • B.1.3 能夠設置是否記錄播放位置,設置播放速度,設置屏幕比例
    • B.1.4 支持滑動改變音量【屏幕右邊】,改變屏幕亮度【屏幕左邊】,屏幕底測左右滑動調節進度
    • B.1.5 支持list頁面中視頻播放,滾動後暫停播放,播放能夠自由設置是否記錄狀態。而且還支持刪除視頻播放位置狀態。
    • B.1.6 切換橫豎屏:切換全屏時,隱藏狀態欄,顯示自定義top(顯示電量);豎屏時恢復原有狀態
    • B.1.7 支持切換視頻清晰度模式
    • B.1.8 添加鎖屏功能,豎屏不提供鎖屏按鈕,橫屏全屏時顯示,而且鎖屏時,屏蔽手勢處理
  • C拓展功能【這塊根據實際狀況選擇是否須要使用,通常視頻付費App會有這個工鞥】git

    • C1產品需求:相似優酷,愛奇藝視頻播放器部分邏輯。好比若是用戶沒有登陸也沒有看視頻權限,則提示試看視頻[自定義佈局];若是用戶沒有登陸可是有看視頻權限,則正常觀看;若是用戶登陸,可是沒有充值會員,部分須要權限視頻則進入試看模式,試看結束後彈出充值會員界面;若是用戶餘額不足,好比餘額只有99元,可是視頻觀看要199元,則又有其餘提示。
    • C2自身需求:好比封裝好了視頻播放庫,那麼點擊視頻上登陸按鈕則跳到登陸頁面;點擊充值會員頁面也跳到充值頁面。這個經過定義接口,可讓使用者經過方法調用,靈活處理點擊事件。
    • C.1.1 能夠設置試看模式,設置試看時長。試看結束後就提示登陸或者充值……
    • C.1.2 對於設置視頻的寬高,建議設置成4:3或者16:9或者經常使用比例,若是不是經常使用比例,則可能會有黑邊。其中黑邊的背景能夠設置
    • C.1.3 能夠設置播放有權限的視頻時的各類文字描述,而沒有把它寫在封裝庫中,使用者本身設定
    • C.1.4 鎖定屏幕功能,這個參考大部分播放器,只有在全屏模式下才會有

03.視頻播放器架構說明

  • 視頻常見的佈局視圖github

    • 視頻底圖(用於顯示初始化視頻時的封面圖),視頻狀態視圖【加載loading,播放異常,加載視頻失敗,播放完成等】
    • 改變亮度和聲音【改變聲音視圖,改變亮度視圖】,改變視頻快進和快退,左右滑動快進和快退視圖(手勢滑動的快進快退提示框)
    • 頂部控制區視圖(包含返回健,title等),底部控制區視圖(包含進度條,播放暫停,時間,切換全屏等)
    • 鎖屏佈局視圖(全屏時展現,其餘隱藏),底部播放進度條視圖(不少播放器都有這個),清晰度列表視圖(切換清晰度彈窗)
  • 後期可能涉及的佈局視圖web

    • 手勢指導頁面(有些播放器有新手指導功能),離線下載的界面(該界面中包含下載列表, 列表的item編輯(全選, 刪除))
    • 用戶從wifi切換到4g網絡,提示網絡切換彈窗界面(當網絡由wifi變爲4g的時候會顯示)
    • 圖片廣告視圖(帶有倒計時消失),開始視頻廣告視圖,非會員試看視圖
    • 彈幕視圖(這個很重要),水印顯示視圖,倍速播放界面(用於控制倍速),底部視頻列表縮略圖視圖
    • 投屏視頻視圖界面,視頻直播間刷禮物界面,老師開課界面,展現更多視圖(下載,分享,切換音頻等)
  • 視頻播放器的痛點算法

    • 播放器內核難以切換api

      • 不一樣的視頻播放器內核,因爲api不同,因此難以切換操做。要是想兼容內核切換,就必須本身制定一個視頻接口+實現類的播放器
    • 播放器內核和UI層耦合緩存

      • 也就是說視頻player和ui操做柔和到了一塊兒,尤爲是二者之間的交互。好比播放中須要更新UI進度條,播放異常須要顯示異常UI,都比較難處理播放器狀態變化更新UI操做
    • UI難以自定義或者修改麻煩性能優化

      • 好比常見的視頻播放器,會把視頻各類視圖寫到xml中,這種方式在後期代碼會很大,並且改動一個小的佈局,則會影響大。這樣到後期每每只敢加代碼,而不敢刪除代碼……
      • 有時候難以適應新的場景,好比添加一個播放廣告,老師開課,或者視頻引導業務需求,則須要到播放器中寫一堆業務代碼。迭代到後期,違背了開閉原則,視頻播放器須要作到和業務分離
    • 視頻播放器結構不清晰服務器

      • 這個是指該視頻播放器可否看了文檔後快速上手,知道封裝的大概流程。方便後期他人修改和維護,所以須要將視頻播放器功能分離。好比切換內核+視頻播放器(player+controller+view)
  • 須要達到的目的和效果

    • 基礎封裝視頻播放器player,能夠在ExoPlayer、MediaPlayer,聲網RTC視頻播放器內核,原生MediaPlayer能夠自由切換
    • 對於視圖狀態切換和後期維護拓展,避免功能和業務出現耦合。好比須要支持播放器UI高度定製,而不是該lib庫中UI代碼
    • 針對視頻播放,視頻投屏,音頻播放,播放回放,以及視頻直播的功能
  • 通用視頻框架特色

    • 必定要解耦合

      • 播放器內核與播放器解耦: 支持更多的播放場景、以及新的播放業務快速接入,而且不影響其餘播放業務,好比後期添加阿里雲播放器內核,或者騰訊播放器內核
      • 播放器player與視頻UI解耦:支持添加自定義視頻視圖,好比支持添加自定義廣告,新手引導,或者視頻播放異常等視圖,這個須要較強的拓展性
    • 適合多種業務場景

      • 好比適合播放單個視頻,多個視頻,以及列表視頻,或者相似抖音那種一個頁面一個視頻,還有小窗口播放視頻。也就是適合大多數業務場景
  • 視頻分層

    • 播放器內核

      • 能夠切換ExoPlayer、MediaPlayer,IjkPlayer,聲網視頻播放器,這裏使用工廠模式Factory + AbstractVideoPlayer + 各個實現AbstractVideoPlayer抽象類的播放器類
      • 定義抽象的播放器,主要包含視頻初始化,設置,狀態設置,以及播放監聽。因爲每一個內核播放器api可能不同,因此這裏須要實現AbstractVideoPlayer抽象類的播放器類,方便後期統一調用
      • 爲了方便建立不一樣內核player,因此須要建立一個PlayerFactory,定義一個createPlayer建立播放器的抽象方法,而後各個內核都實現它,各自建立本身的播放器
    • VideoPlayer播放器

      • 能夠自由切換視頻內核,Player+Controller。player負責播放的邏輯,Controller負責視圖相關的邏輯,二者之間用接口進行通訊
      • 針對Controller,須要定義一個接口,主要負責視圖UI處理邏輯,支持添加各類自定義視圖View【統一實現自定義接口Control】,每一個view儘可能保證功能單一性,最後經過addView形式添加進來
      • 針對Player,須要定義一個接口,主要負責視頻播放處理邏輯,好比視頻播放,暫停,設置播放進度,設置視頻連接,切換播放模式等操做。須要注意把Controller設置到Player裏面,二者之間經過接口交互
    • UI控制器視圖

      • 定義一個BaseVideoController類,這個主要是集成各類事件的處理邏輯,好比播放器狀態改變,控制視圖隱藏和顯示,播放進度改變,鎖定狀態改變,設備方向監聽等等操做
      • 定義一個view的接口InterControlView,在這裏類裏定義綁定視圖,視圖隱藏和顯示,播放狀態,播放模式,播放進度,鎖屏等操做。這個每一個實現類則均可以拿到這些屬性呢
      • 在BaseVideoController中使用LinkedHashMap保存每一個自定義view視圖,添加則put進來後而後經過addView將視圖添加到該控制器中,這樣很是方便添加自定義視圖
      • 播放器切換狀態須要改變Controller視圖,好比視頻異常則須要顯示異常視圖view,則它們之間的交互是經過ControlWrapper(同時實現Controller接口和Player接口)實現

04.視頻播放器如何使用

4.1 關於gradle引用說明

  • 以下所示

    //視頻UI層,必需要有
    implementation 'cn.yc:VideoPlayer:3.0.1'
    //視頻緩存,若是不須要則能夠不依賴
    implementation 'cn.yc:VideoCache:3.0.0'
    //視頻內核層,必須有
    implementation 'cn.yc:VideoKernel:3.0.1'

4.2 在xml中添加布局

  • 注意,在實際開發中,因爲Android手機碎片化比較嚴重,分辨率太多了,建議靈活設置佈局的寬高比爲4:3或者16:9或者你認爲合適的,能夠用代碼設置。
  • 若是寬高比變形,則會有黑邊

    <org.yczbj.ycvideoplayerlib.player.VideoPlayer
        android:id="@+id/video_player"
        android:layout_width="match_parent"
        android:layout_height="240dp"/>

4.3 最簡單的視頻播放器參數設定

  • 以下所示

    //建立基礎視頻播放器,通常播放器的功能
    BasisVideoController controller = new BasisVideoController(this);
    //設置控制器
    mVideoPlayer.setVideoController(controller);
    //設置視頻播放連接地址
    mVideoPlayer.setUrl(url);
    //開始播放
    mVideoPlayer.start();

4.4 注意問題

  • 若是是全屏播放,則須要在清單文件中設置當前activity的屬性值

    • android:configChanges 保證了在全屏的時候橫豎屏切換不會執行Activity的相關生命週期,打斷視頻的播放
    • android:screenOrientation 固定了屏幕的初始方向
    • 這兩個變量控制全屏後和退出全屏的屏幕方向

      <activity android:name=".VideoActivity"
              android:configChanges="orientation|keyboardHidden|screenSize"
              android:screenOrientation="portrait"/>
  • 如何一進入頁面就開始播放視頻,稍微延時一下便可

    • 代碼以下所示,注意避免直接start(),由於有可能視頻尚未初始化完成……

      mVideoPlayer.postDelayed(new Runnable() {
          @Override
          public void run() {
              mVideoPlayer.start();
          }
      },300);

05.播放器詳細Api文檔

  • 01.最簡單的播放
  • 02.如何切換視頻內核
  • 03.切換視頻模式
  • 04.切換視頻清晰度
  • 05.視頻播放監聽
  • 06.列表中播放處理
  • 07.懸浮窗口播放
  • 08.其餘重要功能Api
  • 09.播放多個視頻
  • 10.VideoPlayer相關Api
  • 11.Controller相關Api
  • 12.仿快手播放視頻
  • 具體看這篇文檔:[視頻播放器Api說明]()

06.播放器封裝思路

6.1視頻層級示例圖

image

6.2 視頻播放器流程圖

  • 待完善

6.3 視頻播放器lib庫

image

6.4 視頻內核lib庫介紹

image
image

6.5視頻播放器UI庫介紹

image

07.播放器示例展現圖

image
image
image
image
image
image
image
image
image
image

08.添加自定義視圖

  • 好比,如今有個業務需求,須要在視頻播放器剛開始添加一個廣告視圖,等待廣告倒計時120秒後,直接進入播放視頻邏輯。相信這個業務場景很常見,你們都碰到過,使用該播放器就特別簡單,代碼以下所示:
  • 首先建立一個自定義view,須要實現InterControlView接口,重寫該接口中全部抽象方法,這裏省略了不少代碼,具體看demo。

    public class AdControlView extends FrameLayout implements InterControlView, View.OnClickListener {
    
        private ControlWrapper mControlWrapper;
        public AdControlView(@NonNull Context context) {
            super(context);
            init(context);
        }
    
        private void init(Context context){
            LayoutInflater.from(getContext()).inflate(R.layout.layout_ad_control_view, this, true);
        }
       
        /**
         * 播放狀態
         * -1               播放錯誤
         * 0                播放未開始
         * 1                播放準備中
         * 2                播放準備就緒
         * 3                正在播放
         * 4                暫停播放
         * 5                正在緩衝(播放器正在播放時,緩衝區數據不足,進行緩衝,緩衝區數據足夠後恢復播放)
         * 6                暫停緩衝(播放器正在播放時,緩衝區數據不足,進行緩衝,此時暫停播放器,繼續緩衝,緩衝區數據足夠後恢復暫停
         * 7                播放完成
         * 8                開始播放停止
*/
    @Override
    public void onPlayStateChanged(int playState) {
        switch (playState) {
            case ConstantKeys.CurrentState.STATE_PLAYING:
                mControlWrapper.startProgress();
                mPlayButton.setSelected(true);
                break;
            case ConstantKeys.CurrentState.STATE_PAUSED:
                mPlayButton.setSelected(false);
                break;
        }
    }

    /**
     * 播放模式
     * 普通模式,小窗口模式,正常模式三種其中一種
     * MODE_NORMAL              普通模式
     * MODE_FULL_SCREEN         全屏模式
     * MODE_TINY_WINDOW         小屏模式
     * @param playerState                   播放模式
     */
    @Override
    public void onPlayerStateChanged(int playerState) {
        switch (playerState) {
            case ConstantKeys.PlayMode.MODE_NORMAL:
                mBack.setVisibility(GONE);
                mFullScreen.setSelected(false);
                break;
            case ConstantKeys.PlayMode.MODE_FULL_SCREEN:
                mBack.setVisibility(VISIBLE);
                mFullScreen.setSelected(true);
                break;
        }
        //暫未實現全面屏適配邏輯,須要你本身補全
    }
}
```
  • 而後該怎麼使用這個自定義view呢?很簡單,在以前基礎上,經過控制器對象add進來便可,代碼以下所示

    controller = new BasisVideoController(this);
    AdControlView adControlView = new AdControlView(this);
    adControlView.setListener(new AdControlView.AdControlListener() {
        @Override
        public void onAdClick() {
            BaseToast.showRoundRectToast( "廣告點擊跳轉");
        }
    
        @Override
        public void onSkipAd() {
            playVideo();
        }
    });
    controller.addControlComponent(adControlView);
    //設置控制器
    mVideoPlayer.setController(controller);
    mVideoPlayer.setUrl(proxyUrl);
    mVideoPlayer.start();

09.視頻播放器優化處理

9.1 如何兼容不一樣內核播放器

  • 提問:針對不一樣內核播放器,好比谷歌的ExoPlayer,B站的IjkPlayer,還有原生的MediaPlayer,有些api不同,那使用的時候如何統一api呢?

    • 好比說,ijk和exo的視頻播放listener監聽api就徹底不一樣,這個時候須要作兼容處理
    • 定義接口,而後各個不一樣內核播放器實現接口,重寫抽象方法。調用的時候,獲取接口對象調用api,這樣就能夠統一Api
  • 定義一個接口,這個接口有什麼呢?這個接口定義通用視頻播放器方法,好比常見的有:視頻初始化,設置url,加載,以及播放狀態,簡單來講能夠分爲三個部分。

    • 第一部分:視頻初始化實例對象方法,主要包括:initPlayer初始化視頻,setDataSource設置視頻播放器地址,setSurface設置視頻播放器渲染view,prepareAsync開始準備播放操做
    • 第二部分:視頻播放器狀態方法,主要包括:播放,暫停,恢復,重製,設置進度,釋放資源,獲取進度,設置速度,設置音量
    • 第三部分:player綁定view後,須要監聽播放狀態,好比播放異常,播放完成,播放準備,播放size變化,還有播放準備
  • 首先定義一個工廠抽象類,而後不一樣的內核播放器分別建立其具體的工廠實現具體類

    • PlayerFactory:抽象工廠,擔任這個角色的是工廠方法模式的核心,任何在模式中建立對象的工廠類必須實現這個接口
    • ExoPlayerFactory:具體工廠,具體工廠角色含有與業務密切相關的邏輯,而且受到使用者的調用以建立具體產品對象。
  • 如何使用,分爲三步,具體操做以下所示

    • 1.先調用具體工廠對象中的方法createPlayer方法;2.根據傳入產品類型參數得到具體的產品對象;3.返回產品對象並使用。
    • 簡而言之,建立對象的時候只須要傳遞類型type,而不須要對應的工廠,便可建立具體的產品對象
  • 這種建立對象最大優勢

    • 工廠方法用來建立所須要的產品,同時隱藏了哪一種具體產品類將被實例化這一細節,用戶只須要關心所需產品對應的工廠,無須關心建立細節,甚至無須知道具體產品類的類名。
    • 加入新的產品時,好比後期新加一個阿里播放器內核,這個時候就只須要添加一個具體工廠和具體產品就能夠。系統的可擴展性也就變得很是好,徹底符合「開閉原則」

9.2 播放器UI抽取封裝優化

  • 發展中遇到的問題

    • 播放器可支持多種場景下的播放,多個產品會用到同一個播放器,這樣就會帶來一個問題,一個播放業務播放器狀態發生變化,其餘播放業務必須同步更新播放狀態,各個播放業務之間互相交叉,隨着播放業務的增多,開發和維護成本會急劇增長, 致使後續開發不可持續。
  • UI難以自定義或者修改麻煩

    • 好比常見的視頻播放器,會把視頻各類視圖寫到xml中,這種方式在後期代碼會很大,並且改動一個小的佈局,則會影響大。這樣到後期每每只敢加代碼,而不敢刪除代碼……
    • 有時候難以適應新的場景,好比添加一個播放廣告,老師開課,或者視頻引導業務需求,則須要到播放器中寫一堆業務代碼。迭代到後期,違背了開閉原則,視頻播放器須要作到和業務分離
  • 視頻播放器結構須要清晰

    • 也就是說視頻player和ui操做柔和到了一塊兒,尤爲是二者之間的交互。好比播放中須要更新UI進度條,播放異常須要顯示異常UI,都比較難處理播放器狀態變化更新UI操做
    • 這個是指該視頻播放器可否看了文檔後快速上手,知道封裝的大概流程。方便後期他人修改和維護,所以須要將視頻播放器功能分離。好比切換內核+視頻播放器(player+controller+view)
    • 必定要解耦合,播放器player與視頻UI解耦:支持添加自定義視頻視圖,好比支持添加自定義廣告,新手引導,或者視頻播放異常等視圖,這個須要較強的拓展性
  • 適合多種業務場景

    • 好比適合播放單個視頻,多個視頻,以及列表視頻,或者相似抖音那種一個頁面一個視頻,還有小窗口播放視頻。也就是適合大多數業務場景
  • 方便播放業務發生變化

    • 播放狀態變化是致使不一樣播放業務場景之間交叉同步,解除播放業務對播放器的直接操控,採用接口監聽進行解耦。好比:player+controller+interface
  • 關於視頻播放器

    • 定義一個視頻播放器InterVideoPlayer接口,操做視頻播放,暫停,緩衝,進度設置,設置播放模式等多種操做。
    • 而後寫一個播放器接口的具體實現類,在這個裏面拿到內核播放器player,而後作相關的實現操做。
  • 關於視頻視圖View

    • 定義一個視圖InterVideoController接口,主要負責視圖顯示/隱藏,播放進度,鎖屏,狀態欄等操做。
    • 而後寫一個播放器視圖接口的具體實現類,在這裏裏面inflate視圖操做,而後接口方法實現,爲了方便後期開發者自定義view,所以須要addView操做,將添加進來的視圖用map集合裝起來。
  • 播放器player和controller交互

    • 在player中建立BaseVideoController對象,這個時候須要把controller添加到播放器中,這個時候有兩個要點特別重要,須要把播放器狀態監聽,和播放模式監聽傳遞給控制器
    • setPlayState設置視頻播放器播放邏輯狀態,主要是播放緩衝,加載,播放中,暫停,錯誤,完成,異常,播放進度等多個狀態,方便控制器作UI更新操做
    • setPlayerState設置視頻播放切換模式狀態,主要是普通模式,小窗口模式,正常模式三種其中一種,方便控制器作UI更新
  • 播放器player和view交互

    • 這塊很是關鍵,舉個例子,視頻播放失敗須要顯示控制層的異常視圖View;播放視頻初始化須要顯示loading,而後更新UI播放進度條等。都是播放器和視圖層交互
    • 能夠定義一個類,同時實現InterVideoPlayer接口和InterVideoController接口,這個時候會從新這兩個接口全部的方法。此類的目的是爲了在InterControlView接口實現類中既能調用VideoPlayer的api又能調用BaseVideoController的api
  • 如何添加自定義播放器視圖

    • 添加了自定義播放器視圖,好比添加視頻廣告,能夠選擇跳過,選擇播放暫停。那這個視圖view,確定是須要操做player或者獲取player的狀態的。這個時候就須要暴露監聽視頻播放的狀態接口監聽
    • 首先定義一個InterControlView接口,也就是說全部自定義視頻視圖view須要實現這個接口,該接口中的核心方法有:綁定視圖到播放器,視圖顯示隱藏變化監聽,播放狀態監聽,播放模式監聽,進度監聽,鎖屏監聽等
    • 在BaseVideoController中的狀態監聽中,經過InterControlView接口對象就能夠把播放器的狀態傳遞到子類中

9.4 代碼方面優化措施

  • 若是是在Activity中的話,建議設置下面這段代碼

    @Override
    protected void onResume() {
        super.onResume();
        if (mVideoPlayer != null) {
            //從後臺切換到前臺,當視頻暫停時或者緩衝暫停時,調用該方法從新開啓視頻播放
            mVideoPlayer.resume();
        }
    }
@Override
protected void onPause() {
    super.onPause();
    if (mVideoPlayer != null) {
        //從前臺切到後臺,當視頻正在播放或者正在緩衝時,調用該方法暫停視頻
        mVideoPlayer.pause();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mVideoPlayer != null) {
        //銷燬頁面,釋放,內部的播放器被釋放掉,同時若是在全屏、小窗口模式下都會退出
        mVideoPlayer.release();
    }
}

@Override
public void onBackPressed() {
    //處理返回鍵邏輯;若是是全屏,則退出全屏;若是是小窗口,則退出小窗口
    if (mVideoPlayer == null || !mVideoPlayer.onBackPressed()) {
        super.onBackPressed();
    }
}
```

10.播放器問題記錄說明

11.性能優化和庫大小

12.視頻緩存原理介紹

  • 網絡上比較好的項目:https://github.com/danikula/A...

    • 網絡用的HttpURLConnection,文件緩存處理,文件最大限度策略,回調監聽處理,斷點續傳,代理服務等。
  • 可是存在一些問題,好比以下所示

    • 文件的緩存超過限制後沒有按照lru算法刪除,
    • 處理返回給播放器的http響應頭消息,響應頭消息的獲取處理改成head請求(需服務器支持)
    • 替換網絡庫爲okHttp(由於大部分的項目都是以okHttp爲網絡請求庫的),可是這個改動性比較大
  • 而後看一下怎麼使用,超級簡單。傳入視頻url連接,返回一個代理連接,而後就能夠呢

    HttpProxyCacheServer cacheServer = ProxyVideoCacheManager.getProxy(this);
    String proxyUrl = cacheServer.getProxyUrl(URL_AD);
    mVideoPlayer.setUrl(proxyUrl);
    
    
    public static HttpProxyCacheServer getProxy(Context context) {
        return sharedProxy == null ? (sharedProxy = newProxy(context)) : sharedProxy;
    }
    
    private static HttpProxyCacheServer newProxy(Context context) {
        return new HttpProxyCacheServer.Builder(context)
                .maxCacheSize(512 * 1024 * 1024)       // 512MB for cache
                //緩存路徑,不設置默認在sd_card/Android/data/[app_package_name]/cache中
                //.cacheDirectory()
                .build();
    }
  • 大概的原理

    • 原始的方式是直接塞播放地址給播放器,它就能夠直接播放。如今咱們要在中間加一層本地代理,播放器播放的時候(獲取數據)是經過咱們的本地代理的地址來播放的,這樣咱們就能夠很好的在中間層(本地代理層)作一些處理,好比:文件緩存,預緩存(秒開處理),監控等。
  • 原理詳細一點來講

    • 1.採用了本地代理服務的方式,經過原始url給播放器返回一個本地代理的一個url ,代理URL相似:http://127.0.0.1:port/視頻url;(port端口爲系統隨機分配的有效端口,真實url是爲了真正的下載),而後播放器播放的時候請求到了你本地的代理上了。
    • 2.本地代理採用ServerSocket監聽127.0.0.1的有效端口,這個時候手機就是一個服務器了,客戶端就是socket,也就是播放器。
    • 3.讀取客戶端就是socket來讀取數據(http協議請求)解析http協議。
    • 4.根據url檢查視頻文件是否存在,讀取文件數據給播放器,也就是往socket裏寫入數據(socket通訊)。同時若是沒有下載完成會進行斷點下載,固然弱網的話數據須要生產消費同步處理。
  • 如何實現預加載

    • 其實預加載的思路很簡單,在進行一個播放視頻後,再返回接下來須要預加載的視頻url,啓用線程去請求下載數據
    • 開啓一個線程去請求並預加載一部分的數據,可能須要預加載的數據大於>1,利用隊列先進入的先進行加載,所以能夠採用LinkedHashMap保存正在預加載的task。
    • 在開始預加載的時候,判斷該播放地址是否已經預加載,若是不是那麼建立一個線程task,而且把它放到map集合中。而後執行預加載邏輯,也就是執行HttpURLConnection請求
    • 提供取消對應url加載的任務,由於有可能該url不須要再進行預加載了,好比參考抖音,當用戶瞬間下滑幾個視頻,那麼不少視頻就須要跳過了不須要再進行預加載
  • 具體直接看項目代碼:VideoCache緩衝模塊

13.查看視頻播放器日誌

  • 統一管理視頻播放器封裝庫日誌,方便後期排查問題

    • 好比,視頻內核,日誌過濾則是:aaa
    • 好比,視頻player,日誌過濾則是:bbb
    • 好比,緩存模塊,日誌過濾則是:VideoCache

14.該庫異常code說明

  • 針對視頻封裝庫,統一處理拋出的異常,爲了方便開發者快速知道異常的來由,則能夠查詢約定的code碼。

    • 這個在sdk中特別常見,所以該庫必定程度是借鑑騰訊播放器……

視頻框架:https://github.com/yangchong2...

相關文章
相關標籤/搜索