ijkplayer編譯so庫真沒那麼難

coder-pig發表於2018-01-23

引言

公司現在的電臺專案是我第二個接觸音訊播放專案,Android音視訊 播放很多還是使用的MediaPlayer(大中廠除外),但是如果你用過 MediaPlayer的話,很多開發者都會吐槽有多坑,連谷歌官方都推薦 使用ExoPlayer...遇到過最坑的就是播放線上音視訊的時候,網路不好 會一直載入,然後點多了還容易ANR...以前就一直想把音訊播放這個 換掉,通過自行搜尋和問別人,又下面幾個方案(小作坊不可能 另外去寫個編解碼播放庫):

  • ExoPlayer:Demo複雜得一匹...而且網上的資料也不是很多,pass;
  • Vitamio:自用免費,商用收費,直接就pass了;
  • 自己編譯ffmpeg:一聽就很複雜的,同樣Pass;
  • ijkplayer:大B站開源的基於FFmpeg的輕量級 Android/iOS視訊播放器,網上資料挺多的,而且官方 也有維護,雖然還有1600多個issues,和mediaplayer 差不多的介面,學習成本也不高,可以加進來試試水!

最後就決定使用ijkplayer來替換原先的MediaPlayer了!


1.如何使用ijkplayer

官方github.com/Bilibili/ij…

build.gradle新增下述依賴引用即可:

dependencies {
    # 對於大部分的裝置來說已經夠用了
    compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
    compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'

    # Other ABIs: 可選
    compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.4'
    compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.4'
    compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.4'
    compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.4'

    # ExoPlayer as IMediaPlayer: optional, experimental
    compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.4'
}
複製程式碼

這裡簡單說點東西來解除你可能存在的一些疑惑:

armv7aarmv5arm64x86x86_64 這些是對應的CPU架構, 一般來說準備一個armv7a就基本夠了,如果系統找不到CPU架構 對應的so庫會去找armeabi,多依賴一些架構只是稍微會快一點, 但是這樣也伴隨著apk體積的增大,這個需要你自行去權衡!!! 反正筆者就只有一個:armv7a,暫時沒發現什麼不服!

然後使用方法和MediaPlayer大同小異,這就不另外講述怎麼 使用了,網上一搜也很多。接下來要說下筆者遇到的一個問題:

ijkplayer預設不支援HTTPS

是的,不支援,如果你嘗試使用ijkplayer播放Https開頭的音訊,會報這樣的錯誤:

ijkplayer編譯so庫真沒那麼難

除了去編譯ijkplayer的原始碼,沒有其他選擇,編譯這玩意可把我 坑慘了,各種不懂,碰壁,不過最後所幸還是搗鼓成功了,順道 記錄下,方便後來者(順道吐槽下網上各種抄的文章,搜到的基本 都是一樣的...)

ijkplayer編譯so庫真沒那麼難


2.編譯支援Https的ijkplayer

不要問我Windows上怎麼編譯,反正我只會Ubuntu和MAC上編譯! 筆者在Ubuntu 14.04MAC OS 10.13 上都編譯成功了, 在使用Ubuntu編譯的時候有個坑要注意:

不要把專案克隆到外部硬碟,比如我電腦120G的SSD 還掛了一個1T的機械硬碟,一開始就clone到機械硬碟上了,然後編譯 一堆問題,什麼ln無法建立連結,chmod命令無效之類的,沒把我給毒死, 後面clone到SSD 上一點毛病也沒有,全程綠燈!


  • Step 1安裝Git與yasm
sudo apt-get install git
sudo apt-get install yasm
複製程式碼

  • Step 2:下載,配置SDK與NDK

sdk就不說了,你開發安卓肯定會有的,NDK一般是不預設下載的, 這裡也不建議你使用SDK Manager下載的NDK,之前試過有些許問題, 建議去官網下載:developer.android.google.cn/ndk/downloa… NDK的最小版本支援是10e,目前不支援NDK 15!

接著是配置環境變數:

Ubuntu

設定修改下:.bashrc檔案,把SDK和NDK配置上:

ijkplayer編譯so庫真沒那麼難

然後source .bashrc,鍵入ndk-build -v 看有沒有東西輸出 驗證配置是否生效。

ijkplayer編譯so庫真沒那麼難

MAC

開啟終端,cd到根目錄(cd ~),然後新建一個**.bash_profile**的檔案: 進行如下配置

ijkplayer編譯so庫真沒那麼難

然後輸入source .bash_profile,鍵入ndk-build -v 驗證:

ijkplayer編譯so庫真沒那麼難


  • Step 3:拉取ijkplayer原始碼
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android
git checkout -B latest k0.8.4
複製程式碼

  • Step 4:初始化android
./init-android.sh
複製程式碼

  • Step 5:編譯指令碼配置

就是自動化編譯時的一些配置選項,比如支援什麼協議啊,支援什麼音視訊型別等, 這個配置檔案是:config/module.sh,你喜歡可以開啟看看這個檔案: 比如這裡是配置處理什麼型別的資料的,enable啟用,disable禁用。

ijkplayer編譯so庫真沒那麼難

另外官方給我們提供了三個模板給我們使用:

ijkplayer編譯so庫真沒那麼難

module-default.sh:預設,如果你喜歡更多型別可以用這個; module-lite-hevc.sh:如果您更喜歡較小的二進位制大小的編解碼器/格式(包括hevc功能) module-lite.sh:如果您更喜歡較小的二進位制大小的編解碼器/格式(預設情況下)

反正體積最小,就用module-lite.sh這個就行了,使用也很簡單:

rm module.sh
ln -s module-lite.sh module.sh
source module.sh
複製程式碼

到此你還可以開啟module.sh自行進行修改,比如我只想它支援mp3, 其他格式都不支援,那麼可以把不想支援的格式的enable改成disable。


  • Step 6:初始化android支援Https
cd ..
./init-android-openssl.sh
複製程式碼

注:如果出現NDK或者SDK找不到,可以執行一下source ~/.bash_profile


  • Step 7:清除一波
cd android/contrib
./compile-openssl.sh clean
./compile-ffmpeg.sh clean
複製程式碼

  • Step 8:編譯openssl
./compile-openssl.sh all
複製程式碼

  • Step 9:編譯ffmpeg

這裡的話看你需要,如果想編譯所有版本的so庫,就跟all,如果是特定 CPU架構就跟cpu架構,比如:./compile-ffmpeg.sh armv7a 編譯特定需要的肯定是比全部耗時短~

./compile-ffmpeg.sh all
複製程式碼

  • Step 10:編譯ijkplayer

加all預設編譯所有架構的so庫,不加預設只編譯armv7a架構

./compile-ijk.sh all
複製程式碼

編譯需要漫長的等待,編譯成功後,會在目錄下生成一個ijkplayer的工程:

ijkplayer編譯so庫真沒那麼難

ijkplayer編譯so庫真沒那麼難

到此,編譯一個支援HTTPS的ijkplayer就完成了,接著是怎麼用這個東西啦:

再吐槽一句:網上很多教編譯的,到此就完了,完全不跟別人說怎麼用, 我一開始以為只要把so庫放到自己專案的libs下就可以了,結果各種編譯 報錯,我真服了,大佬們寫文章別虎頭蛇尾啊!!!

最簡單的使用方法,就是把這個專案當成一個library匯入到專案中, 就是build.gradle裡多一個compile project(':ijkplayer'), 然後你就可以用了,記得把你之前寫的:

compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
複製程式碼

這些依賴刪掉,不然還是會報不支援HTTPS的! 一般到這裡引用到專案裡就夠了,但是小豬不是個容易滿足的人! 所以有了下面的折騰!


3.刪減無關東西,生成aar依賴庫

覺得又很多無關的東西,說下小豬的期望吧:

  • 1.只是用來播放音樂(exo和example部分可以去掉);
  • 2.只需要armv7a架構的(刪除其他架構,並把armv7a的so庫放到ijkplayer-java);
  • 3.最後只保留一個ijkplayer-java,匯出成ijkplayer.aar檔案供自己的專案使用;

接著一步步來把實現小豬的期望吧:


  • Step 1:右鍵專案 Open Module Settings,點選減號把除了ijkplayer-example 和ijkplayer-java的依賴都刪除:

ijkplayer編譯so庫真沒那麼難

接著開啟ijkplayer-java/src/main/,新建一個libs資料夾, 同時開啟ijkplayer-armv7a/main/libs,把裡面的armeabi-v7a檔案 夾整個拷到ijkplayer-java的libs資料夾下。

ijkplayer編譯so庫真沒那麼難

然後可以把除了ijkplayer-example和ijkplayer-java的其他都刪掉了, 接著修改下ijkplayer-java的build.gradle檔案,刪掉最後一句,以及 修改下版本資訊。

ijkplayer編譯so庫真沒那麼難

接著編譯一波整個工程,執行下,點開simple,隨便點首歌看看能否播放, 如果可以正常播放,那麼就進入下一步了,匯出aar庫。


  • Step 2:編譯aar庫

這個倒是簡單,點選右側gradle,依次開啟,右鍵run就好

ijkplayer編譯so庫真沒那麼難

執行完畢,會在build/outputs/aar目錄下生成aar檔案。

ijkplayer編譯so庫真沒那麼難


  • Step 3:把aar檔案新增到專案中

這個也很簡單,直接丟到app的libs資料夾下,然後build.gradle 下新增依賴,(筆者直接把ijkplayer-java-release.aar改名成 ijkplayer.aar)

implementation(name: 'ijkplayer', ext: 'aar')
複製程式碼

接著,專案裡寫個簡單的播放音樂的程式碼試試水,按鈕點選播放一個音樂:

public class MusicPlayActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music_play);
        Button btn = findViewById(R.id.button);
        btn.setOnClickListener(v -> {
            IjkMediaPlayer player = new IjkMediaPlayer();
            player.setAudioStreamType(AudioManager.STREAM_MUSIC);
            player.setScreenOnWhilePlaying(true);
            player.setOnPreparedListener(IMediaPlayer::start);
            try {
                player.setDataSource("https:xxxx.mp3");
                player.prepareAsync();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}
複製程式碼

如果播放正常的話,說明我們的移植非常成功,如果你沒有用模組化, 到此就可以結束了,如果你像我一樣用了模組化,而且還把音訊播放 獨立成了一個模組,app -> 音訊播放模組 -> ijkplayer.aar, 恭喜你,編譯直接報錯,找不到aar,2333!解決方法的話,你要 接著看下面的啦~


4.模組化,模組使用aar找不到問題解決

需要修改三個build.gradle檔案,依次是音訊播放模組,app,以及application層級

音訊播放模組的build.gradle

ijkplayer編譯so庫真沒那麼難

app層級的build.gradle:

ijkplayer編譯so庫真沒那麼難

application層級的build.gradle

ijkplayer編譯so庫真沒那麼難

接著build一波專案,就可以啦~


小結

耗時幾天,總算是編譯成功,而且收穫頗多了,也懂了了一個道理: 人難免有畏難情緒,對於學習新的東西總會下意識的抗拒,覺得難, 但是大部分時候只是看上去難,當你去學了,並堅持一段時間,你 會發現,其實並沒有你想象中那麼難~

ijkplayer編譯so庫真沒那麼難

最後附上縮減後的ijk-player和aar包,有需要的自取: github.com/coder-pig/i…


相關文章