“視頻太長太枯燥,要是可以快進(jìn)播放就好了!”、“這個視頻已經(jīng)看過了,想要快速回顧一下,但是再看1個小時有點(diǎn)久”、“老師發(fā)音太快,能不能放慢語速,快跟不上節(jié)奏了”
? ? ? ? 課程視頻越來越長,學(xué)習(xí)時間越來越少。面對這些場景,很多視頻播放的App都增加了倍速功能,可以開啟0.5x、1.5x甚至2.0x等倍速,用于增強(qiáng)播放功能。 iOS系統(tǒng)播放內(nèi)核的強(qiáng)大,很輕松的應(yīng)付了產(chǎn)品經(jīng)理提出的這個需求,但是面對市場上數(shù)不清的Android系統(tǒng)版本和設(shè)備,這讓Android客戶端增加倍速功能,無疑又新添了一道門坎。
? ? ? ? 為了增加倍速功能,并保持系統(tǒng)版本兼容,一開始選擇的是集成vlc播放器的方案。vlc 2.x版本后,增加了倍速播放功能,但vlc本身結(jié)構(gòu)比較龐大,集成難度較高,增加了后續(xù)維護(hù)的難度,在使用一段時間后,開始考慮給Android端更換另外一種倍速方案。
? ? ? ? 這次是集成Google ExoPlayer的播放器,ExoPlayer本身在Android 6.0系統(tǒng)及以上,支持系統(tǒng)級別的倍速播放功能,能更好的利用設(shè)備硬件功能。ExoPlayer本身出自Google之手,是官方推薦的播放器,對Android系統(tǒng)兼容較好,并且設(shè)計結(jié)構(gòu)簡單易懂,容易擴(kuò)展。
? ? ? ?但是遺憾在6.0以下就不支持倍速設(shè)置。得益于ExoPlayer可擴(kuò)展性很強(qiáng),支持對視頻、音頻等渲染器做擴(kuò)展,通過改變默認(rèn)音頻渲染器的音頻輸出,可以加快音頻流的速度,在ExoPlayer中,保持音視頻同步,一般是視頻跟著音頻的速率走,所以我們調(diào)整音頻的速率,就同時也改變了視頻。音頻流的速率調(diào)整可以通過一個三方庫Sonic(https://github.com/waywardgeek/sonic/blob/master/Sonic.java)來改變。
? ? ? ? 當(dāng)播放器進(jìn)行構(gòu)建音頻渲染器的時候,可以根據(jù)Android系統(tǒng)版本選擇不同的音頻渲染器。當(dāng)Android系統(tǒng)是6.0及以上時,我們使用默認(rèn)的MediaCodecAudioRenderer,6.0以下時,就使用自定義的音頻渲染器SonicMediaCodecAudioTrackRenderer。
? ? ? ? SonicMediaCodecAudioTrackRenderer的核心,就是拿到音頻流的buffer,使用Sonic對這段buffer數(shù)據(jù)流進(jìn)行速率調(diào)整處理,然后把調(diào)整后的buffer流送給音頻渲染器,這樣就更改了音頻速率。
? ? ? ? SonicMediaCodecAudioTrackRenderer本身也繼承至MediaCodecAudioRenderer類,在onOutputFormatChanged方法里,我們初始化Sonic和一些緩存buffer數(shù)組,并配置速率。
? ? ? ? processOutputBuffer方法會在音頻渲染器工作的時候被調(diào)用,在這里使用Sonic來改變原始的音頻流buffer數(shù)據(jù),并把轉(zhuǎn)換后的流buffer傳遞給播放器播放。
? ? ? ? 在Android 6.0的系統(tǒng)上,我們只要給默認(rèn)的MediaCodecAudioRenderer渲染器配置PlaybackParams參數(shù)就可以實(shí)現(xiàn)倍速播放了。
? ? ? ? 至此,完成了ExoPlayer對倍速功能的支持,并兼容到了多個Android系統(tǒng)版本。在集成到Android項目中,無論從代碼耦合結(jié)構(gòu),還是播放器擴(kuò)展性、易讀性,ExoPlayer無疑比vlc更具優(yōu)勢。