HLS直播技術方案及踩過的坑

農場老馬發表於2015-06-04


一、為什麼是IJKPlayer

在基礎技術方面,後端有比較成熟的系統,就不再說了,這裡說說客戶端方面。
有直播就會有彈幕,基本上是標配了。
字幕方面bilibili開源了一個Android的專案,不過IOS卻沒有,這個只能自己寫了,不過本身這個東西技術方案沒有什麼太高深的東西,建立一個HTTP連線,不停地讀資料就好了,如果關閉字幕,就把連線斷掉。在顯示方面可能要考慮一些細節問題,像速度、位置、字數限制、之類的。
播放器方面,Android和IOS理論上是原生支援HLS播放的,不過實際應用過程中適配問題比較多,所以業內一般都使用bilibili開源出來的IJKPlayer,像鬥魚TV之類的都是自己基於IJKPlayer改造的,技術方案比較成熟,穩定性方面比較可靠,使用起來也很簡單,專案的編譯指令碼做的比較簡單、靈活。

二、IJKPlayer的使用。

把專案Clone下來之後,首先要做的就是配置一下Codec,因為IJKPlayer使用ffmpeg做Codec,如果不裁剪一下,編出來的庫會大的驚人。看一下config/module.sh,把不需要的codec注掉就OK了,我只使用了aac、H264兩種。最後兩個平臺上面編出來都是大概有1M多,作為一個播放器來說,Size絕對很小了。
Android目前主流機器都支援ARMV7了,只編這一種也足夠了,對IOS來說,ARMV7、ARMV7s、ARM64這幾種都得支援,除錯時還需要使用i386,所以為了簡單起見,測試階段,我生成了支援ARMV7、ARMV7s、ARM64、i386這四種CPU架構的庫,等到釋出階段再去掉i386架構的程式碼,進一步縮小包大小。
下面以IOS為例說一下整個編譯過程。
1、修改config/module.sh,裁剪需要的codec等配置,把不用的去掉,減少最終生成的包大。
1、執行init-ios.sh,這裡主要是下載ffmpeg的程式碼。
2、執行ios/compile-ffmpeg.sh,這裡主要編譯ffmpeg的程式碼。可以修改裡面的配置來決定編譯哪些CPU架構,可選的有arm7、arm7s、arm64、i386、386_64等。
3、編譯完成之後,開啟IJKMediaPlayer,進行Build。IJKMediaPlayer是個.a專案。Build時,IJKMediaPlayer的build setting中,Architectures和Valid Architectures兩個設定項中的CPU架構列表都是armv7,armv7s,arm64這三種。如果Schema中的target選擇模擬器,則最終生成的.a庫檔案有i386,x86_64兩個CPU架構的指令,把.a整合到我的專案中,使用xcodebuild進行打包時,會報找不到armv7,armv7s,arm64等幾種架構指令的錯誤;如果Schema中的target選擇iOS device,則最終生成的.a庫檔案只有armv7、armv7s、arm64這幾種CPU架構的指令,整合到我的專案中使用XCode進行編譯時由於找不到i386架構的指令,也同樣會報錯。最後使用lipo create,所以兩個.a庫檔案進行Merge,問題解決,不過.a庫比較大,只好等釋出時再把i386,x86_64兩種CPU架構的指令裁剪掉了。
4、把編譯生成的libIJKMediaPlayer.a,以及對應的include檔案放到專案中就可以使用了。庫檔案和標頭檔案的位置在這裡:開啟finder,在選單中開啟“前往”,按住Alt,點選選單中出現的“資源庫”,Developer->Xcode->DerivedData,找到IJKMediaPlayer打頭的資料夾,點選進入,裡面的每個子資料夾分別對應Debug/Release、IOS裝置/模擬器四種情況下生成的.a庫和標頭檔案。
5、.a檔案生成時特別大,我這裡有20多M,但專案整體打包後包大小隻增加了1M多。這個數字差別如此之大,著實讓人吃驚。大家知道老碼農是好奇心最強的,把網際網路翻得底朝天,終於確認了原因如下:

三、.a的壓縮優化

1、編譯優化選項沒有設定,後來我在編譯libIJKMediaPlayer.a時,對Build Setting中的優化項進行了設定(具體設定了些什麼,看第六條),生成的libIJKMediaPlayer.a到了7M+。
2、打包App時,會把.a和App中的程式碼進行Link,在Link完成後會刪除很多.a中存在的在Link時使用的中間資訊,當Link完成之後這些資訊就被刪除了。

四、技術選型

關於直播實現方案的選擇,以及HLS優缺點的詳細分析,可以看下這篇文章:http://www.cnblogs.com/haibindev/archive/2013/01/30/2880764.html

五、生成.a時的CPU架構指令問題

IJKMediaPlayer編譯時的CPU架構指令生成問題,可以參考這裡:http://www.cocoachina.com/ios/20140915/9620.html
把兩種CPU架構指令的.a檔案進行Merge,可以參考這裡:http://blog.sina.com.cn/s/blog_916e0cff0102vb9c.html

六、編譯優化(Build Setting)

1、按照這兩篇文章裡提到的幾種優化方式進行優化:
2、strip style在非app的工程中使用non-global symbols,在app工程中使用all。
4、比較極端的情況下,也可以試試write link map file:http://blog.cnbang.net/tech/2296/

補充於2016.7.8
2015.6月份的iOS版在前幾天執行時,發現偶爾有黑屏現象。場景是程式啟動,播放第一個視訊二、三十分鐘後,退出再播放第二個視訊。
拉取最新程式碼,編了tag為k0.5.1的版本後,該問題沒有再重現過。

另外,目前播放器以framework的形式提供,接入時直接加入原始碼中就OK。如果使用Build Phase中新增二進位制庫的方式會出現framework no found的問題。

相關文章