ExoPlayer 與 MediaPlayer
與Android內(nèi)置的MediaPlayer相比官份,ExoPlayer具有許多優(yōu)點:
1.支持通過HTTP(DASH)和SmoothStreaming進行動態(tài)自適應(yīng)流,這兩種都不受MediaPlayer的支持九默。還支持許多其他格式。同時它還支持HTTP直播(HLS),MP4,MP3,WebM,M4A,MPEG-TS 和 AAC的格式文件
2.能夠自定義和擴展播放器,以適應(yīng)各種不同需求萎馅。 ExoPlayer專門設(shè)計了這一點坑填,大部分組件都可以自己替換
便于隨著App的升級而升級抛人。因為ExoPlayer是一個包含在你的應(yīng)用中的庫,對于你使用哪個版本有完全的控制權(quán)脐瑰,并且你可以簡單的跟隨應(yīng)用的升級而升級妖枚;
3.更少的適配性問題。
缺點:
ExoPlayer的音頻和視頻組件依賴Android的 MediaCodec接口苍在,該接口發(fā)布于Android4.1(API 等級16)绝页。因此它不能工作于之前的Android版本。
簡述:
ExoPlayer庫的核心是ExoPlayer接口寂恬,ExoPlayer公開了傳統(tǒng)的高級媒體播放器功能续誉,例如緩沖媒體,播放掠剑,暫停和seek等功能屈芜。在具體實現(xiàn)方面,該開源庫對播放的媒體類型朴译、存儲方式井佑、位置、渲染方式等進行了最少的實現(xiàn)眠寿,旨在讓開發(fā)者自定義各種特性躬翁。ExoPlayer實現(xiàn)不是直接實現(xiàn)加載和呈現(xiàn)媒體,而是將這項工作委托給各種組件盯拱。 所有ExoPlayer共同的組件有:
MediaSource:定義多媒體數(shù)據(jù)源盒发,這個類的功能就是從Uri中讀取多媒體文件的二進制數(shù)據(jù)例嘱。 MediaSource在播放開始時通過ExoPlayer.prepare注入
TrackSelector:軌道提取器,從MediaSource中提取各個軌道的二進制數(shù)據(jù)宁舰,交給Renderer渲染拼卵。創(chuàng)建播放器時初注入
Renderer:對多媒體中的各個軌道(音軌、視頻軌蛮艰、字幕軌等)數(shù)據(jù)進行渲染腋腮,渲染就是“播放”,把二進制文件渲染成聲音壤蚜、畫面即寡。 創(chuàng)建播放器時注入
LoadControl:對MediaSource進行控制,比如什么時候開始緩沖袜刷、緩沖多少等等聪富。創(chuàng)建播放器時注入
該庫為提供了這些組件的默認實現(xiàn),能夠滿足大部分需求著蟹,如果有特殊需求墩蔓,可以通過自定義組件來實現(xiàn)。 比如萧豆,可以自定義LoadControl來更改播放器的緩沖策略钢拧,或自定義Renderer來渲染Android本身不支持的編解碼器。
整個庫中都存在注入組件的概念炕横,許多子組件都能單獨替換成自定義組件,而不會影響整個流程葡粒。 例如份殿,默認的MediaSource實現(xiàn)需要通過其構(gòu)造函數(shù)注入一個或多個DataSource工廠, 通過提供自定義Factory嗽交,可以從非標(biāo)準源或不同的網(wǎng)絡(luò)堆棧加載數(shù)據(jù)卿嘲。
入門
實現(xiàn)一個最簡單的播放器,需要如下流程:
- 添加ExoPlayer庫作為依賴
- 創(chuàng)建一個SimpleExoPlayer實例
- 將播放器連接到UI夫壁,用于視頻輸出和用戶輸入(也就是放在某個Activity中)
- 準備播放器拾枣,傳入MediaSource作為多媒體源
- 播放完成后釋放
這些步驟在下面更詳細地概述。完整的示例可以參考demo(github地址:https://github.com/google/ExoPlayer)中的PlayerActivity盒让。
添加ExoPlayer作為依賴
第一步是確保項目根目錄中的build.gradle文件中包含jcenter倉庫:
repositories {
jcenter()
}
然后在應(yīng)用app模塊的build.gradle文件中添加ExoPlayer庫的依賴:
compile 'com.google.android.exoplayer:exoplayer:r2.X.X'
創(chuàng)建播放器
使用ExoPlayerFactory創(chuàng)建一個ExoPlayer實例梅肤, 該Factory提供了一系列方法來創(chuàng)建各種定制ExoPlayer實例。 大部分情況下邑茄,使用ExoPlayerFactory.newSimpleInstance方法之一即可姨蝴, 這些方法返回SimpleExoPlayer,它實現(xiàn)了ExoPlayer以添加額外的高級別播放器功能肺缕。 下面是創(chuàng)建SimpleExoPlayer的示例:
// step1\. 創(chuàng)建一個默認的TrackSelector
Handler mainHandler = new Handler();
// 創(chuàng)建帶寬
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
// 創(chuàng)建軌道選擇工廠
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
// 創(chuàng)建軌道選擇器實例
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
//step2\. 創(chuàng)建播放器
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
使用SimpleExoPlayer的setVideoSurfaceView左医、setVideoTextureView授帕、setVideoSurfaceHolder和setVideoSurface方法設(shè)置播放器的目標(biāo)SurfaceView、TextureView浮梢、SurfaceHolder或Surface跛十。
準備播放器
在ExoPlayer中,每一個多媒體文件均由MediaSource表示秕硝,要播放一個多媒體芥映,您必須先創(chuàng)建一個相應(yīng)的MediaSource實例,然后將此實例傳遞給ExoPlayer.prepare缝裤。 ExoPlayer庫為DASH(DashMediaSource)屏轰,SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常規(guī)媒體文件(ExtractorMediaSource)提供了默認MediaSource實現(xiàn)憋飞,這些實現(xiàn)將在本指南的后面更詳細地描述霎苗。 下面的代碼演示如何播放一個mp4文件:
// 測量播放帶寬,如果不需要可以傳null
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
// 創(chuàng)建加載數(shù)據(jù)的工廠
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, "yourApplicationName"), bandwidthMeter);
// 創(chuàng)建解析數(shù)據(jù)的工廠
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// 傳入Uri榛做、加載數(shù)據(jù)的工廠唁盏、解析數(shù)據(jù)的工廠,就能創(chuàng)建出MediaSource
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
dataSourceFactory, extractorsFactory, null, null);
// Prepare
player.prepare(videoSource);
播放器準備好后检眯,可以通過各種方法來控制播放厘擂。 例如,setPlayWhenReady啟動和暫停播放锰瘸,seekTo方法控制進度刽严。
退出時通過ExoPlayer.release釋放播放器,釋放硬件資源避凝。
MediaSource
在ExoPlayer中舞萄,每個多媒體均由MediaSource表示, ExoPlayer庫為DASH(DashMediaSource)管削、SmoothStreaming(SsMediaSource)倒脓、HLS(HlsMediaSource)和常規(guī)媒體文件(ExtractorMediaSource)提供了默認實現(xiàn)。 github上的demo中含思,可以在PlayerActivity中找到實例化所有四個示例崎弃。
除了上述的MediaSource之外,ExoPlayer庫還提供了MergingMediaSource含潘、LoopingMediaSource和ConcatenatingMediaSource饲做。 這些MediaSource通過組合實現(xiàn)更復(fù)雜的播放功能。 一些常見的用例如下所述调鬓。 注意艇炎,示例描述的是視頻播放,但它們同樣適用于僅音頻播放腾窝,實際上也適用于任何支持的媒體類型的播放缀踪。
事件監(jiān)聽
播放期間居砖,可以監(jiān)聽由ExoPlayer生成的事件,指示播放器的整體狀態(tài)驴娃。 這些事件可用作更新用戶界面(如播放控件)的觸發(fā)器奏候。 許多ExoPlayer組件還報告自己的組件特定的底層事件,可以用來監(jiān)聽性能唇敞。
上層事件
ExoPlayer通過addListener/removeListener方法添加/刪除ExoPlayer.EventListener的實例蔗草, 監(jiān)聽者能夠監(jiān)聽到播放狀態(tài)的變化,以及播放失敗的事件疆柔。
使用SimpleExoPlayer時咒精,可以在播放器上設(shè)置其他偵聽器。 比如旷档,setVideoListener允許應(yīng)用程序接收與視頻渲染有關(guān)的事件模叙,這些事件可能對于調(diào)整UI(例如,一個特定寬高比的視頻被渲染到surface上了)有用鞋屈。 可以在SimpleExoPlayer上設(shè)置其他偵聽器來接收調(diào)試信息范咨,例如調(diào)用setVideoDebugListener和setAudioDebugListener。
底層事件
除了上層監(jiān)聽外,ExoPlayer庫提供的許多單獨的組件允許自己的事件監(jiān)聽器。 通常需要將Handler對象傳遞給這些組件迹鹅,這些Handler決定偵聽器方法將在哪個線程調(diào)用,所以在大多數(shù)情況下替蛉,應(yīng)該使用主線程的Handler。
向組件發(fā)送消息
一些組件允許在播放過程中更改配置拄氯。 一般來說灭返,可以通過sendMessages或blockingSendMessages方法將消息通過ExoPlayer傳遞到組件來進行更改。 這種方法確保了線程安全坤邪,更改配置的操作與ExoPlayer上的其它事件一樣,需要按順序執(zhí)行罚缕。
自定義
ExoPlayer與MediaPlayer的主要優(yōu)點之一是可以自定義和擴展播放器艇纺,以更好地適應(yīng)開發(fā)人員使用。 ExoPlayer庫專門設(shè)計了這一點邮弹,定義了一些接口和抽象基類黔衡,使應(yīng)用程序開發(fā)人員可以輕松地替換庫提供的默認實現(xiàn)。 以下是構(gòu)建自定義組件的一些case:
Renderer:可以自定義Renderer來處理默認實現(xiàn)不支持的多媒體格式
TrackSelector:自定義TrackSelector可以更改從MediaSource中提取軌道的方式
LoadControl:自定義LoadControl可以更改播放器的緩沖策略
Extractor:如果需要支持默認庫不支持的容器格式腌乡,可以自定義Extractor類盟劫,然后可以將其與ExtractorMediaSource一起使用,以播放容器格式的多媒體
MediaSource:如果希望獲取媒體樣本以自定義方式提供給渲染器与纽,或者希望實現(xiàn)自定義MediaSource合成行為侣签,則實現(xiàn)自定義MediaSource類可能是適當(dāng)?shù)?/p>
DataSource:ExoPlayer庫已經(jīng)包含了許多不同情況的DataSource實現(xiàn)塘装。您可能希望實現(xiàn)自己的DataSource類,以其他方式加載數(shù)據(jù)影所,比如通過自定義協(xié)議蹦肴,使用自定義HTTP堆棧或從自定義持久緩存加載數(shù)據(jù)猴娩。
自定義指南
如果自定義組件需要將事件報告回應(yīng)用程序阴幌,我們建議您使用與現(xiàn)有ExoPlayer組件相同的模型,其中將事件偵聽器與Handler一起傳遞到組件的構(gòu)造函數(shù)卷中。
我們建議自定義組件使用與現(xiàn)有ExoPlayer組件相同的模型矛双,以便在播放過程中可以方便地重新配置,請參考上面“向組件發(fā)送消息”章節(jié)蟆豫。 為此议忽,您應(yīng)該實現(xiàn)一個ExoPlayerComponent并在其handleMessage方法中接收配置更改消息。 您的應(yīng)用程序應(yīng)通過調(diào)用ExoPlayer的sendMessages和blockingSendMessages方法來傳遞配置更改无埃。