播放器功能 | MediaPlayer | ExoPlayer | IjkPlayer | RTC | TXPlayer |
---|---|---|---|---|---|
UI/Player/業務解耦 | 支持 | 支持 | 支持 | ||
切換視頻播放模式 | 支持 | 支持 | 支持 | ||
視頻無縫切換 | 支持 | 支持 | 支持 | ||
調節播放進度 | 支持 | 支持 | 支持 | ||
網絡環境監聽 | 支持 | 支持 | 支持 | ||
滑動改變亮度/聲音 | 支持 | 支持 | 支持 | ||
設置視頻播放比例 | 支持 | 支持 | 支持 | ||
自由切換視頻內核 | 支持 | 支持 | 支持 | ||
記錄播放位置 | 支持 | 支持 | 支持 | ||
清晰度模式切換 | 支持 | 支持 | 支持 | ||
重力感應自動進入 | 支持 | 支持 | 支持 | ||
鎖定屏幕功能 | 支持 | 支持 | 支持 | ||
倍速播放 | 不支持 | 支持 | 支持 | ||
視頻小窗口播放 | 支持 | 支持 | 支持 | ||
列表小窗口播放 | 支持 | 支持 | 支持 | ||
邊播邊緩存 | 支持 | 支持 | 支持 | ||
同時播放多個視頻 | 支持 | 支持 | 支持 | ||
仿快手預加載 | 支持 | 支持 | 支持 | ||
基於內核無UI | 支持 | 支持 | 支持 | ||
添加彈幕 | 支持 | 支持 | 支持 | ||
全屏顯示電量 | 支持 | 支持 | 支持 |
類型 | 功能說明 |
---|---|
項目結構 | 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 |
A基礎功能java
B高級功能android
C拓展功能【這塊根據實際狀況選擇是否須要使用,通常視頻付費App會有這個工鞥】git
視頻常見的佈局視圖github
後期可能涉及的佈局視圖web
視頻播放器的痛點算法
播放器內核難以切換api
播放器內核和UI層耦合緩存
UI難以自定義或者修改麻煩性能優化
視頻播放器結構不清晰服務器
須要達到的目的和效果
通用視頻框架特色
必定要解耦合
適合多種業務場景
視頻分層
播放器內核
VideoPlayer播放器
UI控制器視圖
以下所示
//視頻UI層,必需要有 implementation 'cn.yc:VideoPlayer:3.0.1' //視頻緩存,若是不須要則能夠不依賴 implementation 'cn.yc:VideoCache:3.0.0' //視頻內核層,必須有 implementation 'cn.yc:VideoKernel:3.0.1'
若是寬高比變形,則會有黑邊
<org.yczbj.ycvideoplayerlib.player.VideoPlayer android:id="@+id/video_player" android:layout_width="match_parent" android:layout_height="240dp"/>
以下所示
//建立基礎視頻播放器,通常播放器的功能 BasisVideoController controller = new BasisVideoController(this); //設置控制器 mVideoPlayer.setVideoController(controller); //設置視頻播放連接地址 mVideoPlayer.setUrl(url); //開始播放 mVideoPlayer.start();
若是是全屏播放,則須要在清單文件中設置當前activity的屬性值
這兩個變量控制全屏後和退出全屏的屏幕方向
<activity android:name=".VideoActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:screenOrientation="portrait"/>
如何一進入頁面就開始播放視頻,稍微延時一下便可
代碼以下所示,注意避免直接start(),由於有可能視頻尚未初始化完成……
mVideoPlayer.postDelayed(new Runnable() { @Override public void run() { mVideoPlayer.start(); } },300);
首先建立一個自定義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();
提問:針對不一樣內核播放器,好比谷歌的ExoPlayer,B站的IjkPlayer,還有原生的MediaPlayer,有些api不同,那使用的時候如何統一api呢?
定義一個接口,這個接口有什麼呢?這個接口定義通用視頻播放器方法,好比常見的有:視頻初始化,設置url,加載,以及播放狀態,簡單來講能夠分爲三個部分。
首先定義一個工廠抽象類,而後不一樣的內核播放器分別建立其具體的工廠實現具體類
如何使用,分爲三步,具體操做以下所示
這種建立對象最大優勢
發展中遇到的問題
UI難以自定義或者修改麻煩
視頻播放器結構須要清晰
適合多種業務場景
方便播放業務發生變化
關於視頻播放器
關於視頻視圖View
播放器player和controller交互
播放器player和view交互
如何添加自定義播放器視圖
若是是在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(); } } ```
網絡上比較好的項目:https://github.com/danikula/A...
可是存在一些問題,好比以下所示
而後看一下怎麼使用,超級簡單。傳入視頻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(); }
大概的原理
原理詳細一點來講
如何實現預加載
統一管理視頻播放器封裝庫日誌,方便後期排查問題
針對視頻封裝庫,統一處理拋出的異常,爲了方便開發者快速知道異常的來由,則能夠查詢約定的code碼。