隨着音視頻領域的火熱,在不少領域(教育,遊戲,娛樂,體育,跑步,餐飲,音樂等)嘗試作音視頻直播/點播功能,那麼做爲開發一個小白,如何快速學習音視頻基礎知識,瞭解音視頻編解碼的傳輸協議,編解碼方式,以及如何技術選型,如何解決遇到的坑,本文拋磚引玉,歡迎大咖交流。html
視頻是什麼
java
靜止的畫面叫圖像(picture)。連續的圖像變化每秒超過24幀(frame)畫面以上時,根椐視覺暫留原理, 人眼沒法辨別每付單獨的靜態畫面,看上去是平滑連續的視覺效果。這樣的連續畫面叫視頻。 當連續圖像變化每秒低於24幀畫面時,人眼有不連續的感受叫動畫(cartoon)
流媒體
android
指採用流式傳輸的方式在Internet / Intranet播放的媒體格式.流媒體的數據流隨時傳送隨 時播放,只是在開始時有些延遲 邊下載邊播入的流式傳輸方式不只使啓動延時大幅度地縮短,並且對系統緩存容量的需求也大大下降,極大地減小用戶用在等待的時間
分辨率
ios
分辨率是一個表示平面圖像精細程度的概念,一般它是以橫向和縱向點的數量來衡量的,表示成水平點數垂直點數的形式, 在計算機顯示領域咱們也表示成「每英寸像素」(ppi).在一個固定的平面內,分辨率越高,意味着可以使用的點數越多,圖像越細緻
碼流
git
數據傳輸時單位時間傳送的數據位數,能夠理解其爲取樣率,單位時間內取樣率越大,精度就越高,處理出來的文件就越接近原始文件,可是文件體積與取樣率是成正比的 如何用最低的碼率達到最少的失真,通常咱們用的單位是kbps即千位每秒
幀率
github
幀/秒(frames per second)的縮寫,也稱爲幀速率,測量用於保存、顯示動態視頻的信息數量。每一幀都是靜止的圖象,快速連續地顯示幀便造成了運動的假象。 每秒鐘幀數 (fps) 愈多,所顯示的動做就會愈流暢,可理解爲1秒鐘時間裏刷新的圖片的幀數,也能夠理解爲圖形處理器每秒鐘可以刷新幾回,也就是指每秒鐘可以播放(或者錄製)多少格畫面。
封裝格式(專業上講叫容器,通俗的叫文件格式),視頻編解碼,音頻編解碼 ####1.1常見的封裝格式 * MPEG : 編碼採用的容器,具備流的特性。裏面又分爲 PS,TS 等,PS 主要用於 DVD 存儲,TS 主要用於 HDTV. * MPEG Audio Layer 3 :大名鼎鼎的 MP3,已經成爲網絡音頻的主流格式,能在 128kbps 的碼率接近 CD 音質 * MPEG-4(Mp4) : 編碼採用的容器,基於 QuickTime MOV 開發,具備許多先進特性;其實是對Apple公司開發的MOV格式(也稱Quicktime格式)的一種改進. * MKV: 它能把 Windows Media Video,RealVideo,MPEG-4 等視頻音頻融爲一個文件,並且支持多音軌,支持章節字幕等;開源的容器格式 * 3GP : 3GPP視頻採用的格式, 主要用於流媒體傳送;3GP實際上是MP4格式的一種簡化版本,是手機視頻格式的絕對主流. * MOV : QuickTime 的容器,恐怕也是現今最強大的容器,甚至支持虛擬現實技術,Java等,它的變種 MP4,3GP都沒有這麼厲害;普遍應用於Mac OS操做系統,在Windows操做系統上也可兼容,可是遠比不上AVI格式流行 * AVI : 最多見的音頻視頻容器,音頻視頻交錯(Audio Video Interleaved)容許視頻和音頻交錯在一塊兒同步播放. * WAV : 一種音頻容器,你們常說的 WAV 就是沒有壓縮的 PCM 編碼,其實 WAV 裏面還能夠包括 MP3 等其餘 ACM 壓縮編碼 等等
RTP :(Real-time Transport Protocol)是用於Internet上針對多媒體數據流的一種傳輸層協議.RTP協議和RTP控制協議RTCP一塊兒使用,並且它是創建在UDP協議上的 RTCP:Real-time Transport Control Protocol或RTP Control Protocol或簡寫RTCP)實時傳輸控制協議,是實時傳輸協議(RTP)的一個姐妹協議 RTP協議和RTP控制協議RTCP一塊兒使用,並且它是創建在UDP協議上的 RTSP:(Real Time Streaming Protocol)是用來控制聲音或影像的多媒體串流協議,RTSP提供了一個可擴展框架,使實時數據,如音頻與視頻的受控、點播成爲可能。 數據源包括現場數據與存儲在剪輯中的數據。該協議目的在於控制多個數據發送鏈接,爲選擇發送通道,如UDP、多播UDP與TCP提供途徑,併爲選擇基於RTP上發送機制提供方法 傳輸時所用的網絡通信協定並不在其定義的範圍內,服務器端能夠自行選擇使用TCP或UDP來傳送串流內容,比較能容忍網絡延遲 RTP不像http和ftp可完整的下載整個影視文件,它是以固定的數據率在網絡上發送數據,客戶端也是按照這種速度觀看影視文件,當影視畫面播放事後,就不能夠再重複播放,除非從新向服務器端要求數據。 RTSP與RTP最大的區別在於:RTSP是一種雙向實時數據傳輸協議,它容許客戶端向服務器端發送請求,如回放、快進、倒退等操做。固然,RTSP可基於RTP來傳送數據,還能夠選擇TCP、UDP、組播UDP等通道來發送數據,具備很好的擴展性。它時一種相似與http協議的網絡應用層協議
RTMPweb
RTMP(Real Time Messaging Protocol)實時消息傳送協議是Adobe Systems公司爲Flash播放器和服務器之間音頻、視頻和數據傳輸 開發的開放協議
HLS算法
HTTP Live Streaming(HLS)是蘋果公司(Apple Inc.)實現的基於HTTP的流媒體傳輸協議,可實現流媒體的直播和點播,主要應用在iOS系統, 爲iOS設備(如iPhone、iPad)提供音視頻直播和點播方案。HLS點播,基本上就是常見的分段HTTP點播,不一樣在於,它的分段很是小。 相對於常見的流媒體直播協議,例如RTMP協議、RTSP協議、MMS協議等,HLS直播最大的不一樣在於,直播客戶端獲取到的,並非一個完整的數據流。 HLS協議在服務器端將直播數據流存儲爲連續的、很短時長的媒體文件(MPEG-TS格式),而客戶端則不斷的下載並播放這些小文件, 由於服務器端老是會將最新的直播數據生成新的小文件,這樣客戶端只要不停的按順序播放從服務器獲取到的文件,就實現了直播。 因而可知,基本上能夠認爲,HLS是以點播的技術方式來實現直播。因爲數據經過HTTP協議傳輸,因此徹底不用考慮防火牆或者代理的問題, 並且分段文件的時長很短,客戶端能夠很快的選擇和切換碼率,以適應不一樣帶寬條件下的播放。不過HLS的這種技術特色,決定了它的延遲通常老是會高於普通的流媒體直播協議。
播放流程: 獲取流-->解碼-->播放
錄製播放路程: 錄製音頻視頻-->剪輯-->編碼-->上傳服務器 別人播放.
直播過程 : 錄製音視頻-->編碼-->流媒體傳輸-->服務器--->流媒體傳輸到其餘app-->解碼-->播放緩存
幾個重要的環節bash
問題
android自己有提供MediaPlayer,那麼mediaplayer支持哪些格式的流媒體協議吶?又支持哪些解碼器吶?兼容性如何,性功能如何?
Supported Media Formats
Media Playback
MPEG-2:制定於1994年,設計目標爲高級工業標準的圖像質量以及更高的傳輸率。這種格式主要應用在DVD/SVCD的製做(壓縮)方面, 同時在一些HDTV(高清晰電視廣播)和一些高要求視頻編輯、處理上面也有至關的應用。使用MPEG-2的壓縮算法,能夠把一部120分鐘長的電影壓縮到4到8GB的大小。 這種視頻格式的文件擴展名包括.mpg、.mpe、.mpeg、.m2v及DVD光盤上的.vob文件等。 MPEG-4:制定於1998年,MPEG-4是爲了播放流式媒體的高質量視頻而專門設計的,它可利用很窄的帶寬,經過幀重建技術, 壓縮和傳輸數據,以求使用最少的數據得到最佳的圖像質量。目前MPEG-4最有吸引力的地方在於它可以保存接近於DVD畫質的 小體積視頻文件。另外,這種文件格式還包含了之前MPEG壓縮標準所不具有的比特率的可伸縮性、動畫精靈、交互性甚至版權 保護等一些特殊功能。這種視頻格式的文件擴展名包括.asf、.mov和DivX AVI等。
從上圖咱們也看到,android平臺自身支持的音視頻解碼是有限的 通常的mp3 mp4....3gp 等等 其餘的只能本身解碼了。。。
那麼如何解碼吶?
通過一番調研對比,選擇樂ijkplayer.
正如上文所說,android本事對音視頻流媒體傳輸協議,以及音視頻編解碼支持有限.因此對於直播類應用,要本身解碼
vitamio
webRTC
ffmpeg
vlc
ijkplayer
先說下 vitamio這個是功能很強大,可是企業收費版的,我的用戶能夠玩玩.
目前WebRtc只適合小範圍(8人之內)音視頻會議,不適合作直播能夠用WebRTC來作視頻直播嗎?
接下來介紹下 ffmpeg vlc ijkplayer以及選擇方案
ffmpeg是一個很是強大的音視頻編解碼開源庫,目前市場上流行的播放器,大部分都是基於此開發的,包括暴風,騰訊,等等以及上面提到的vitamio,vlc,ijkplayer
關於ffmpeg源碼分析,有興趣的請看雷霄驊(leixiaohua1020)的專欄
vlc 支持android開發 ,ijkplayer也支持. 經過反編譯網易雲音樂,以及YY等音視頻app.發現網易雲音樂,鬥魚用的ijkplayer,YY用的VLC.
那麼vlc&ijkplayer相比較各有什麼優缺點吶,該如何選擇吶?[待深刻使用,或者用過的能夠交流下]
其實這個沒有深刻分析,ijkplayer是bilibili開源的音視頻編解碼庫,對android,ios進行和很好的抽取封裝,易於編譯使用.vlc嘗試過,稍微複雜些.
若是不須要對源碼進行修改,在app的build.gradle中加入以下依賴便可
dependencies { # required, enough for most devices. compile 'tv.danmaku.ijk.media:ijkplayer-java:0.4.5.1' compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.4.5.1' # Other ABIs: optional compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.4.5.1' compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.4.5.1' compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.4.5.1' # ExoPlayer as IMediaPlayer: optional, experimental compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.4.5.1' }
固然如何你想對其源碼進行修改,採用以下方式
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android
git checkout -B latest k0.4.5.1
./init-android.sh //此步用於下載ffmpeg,初始化配置
cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
cd ..
./compile-ijk.sh all
而後經過androidstudio把生成的project導入工程
能夠根據須要對音視頻編解碼庫進行裁剪.編譯出最小的知足須要的庫 bilibili提供三種裁剪方式 If you prefer more codec/format
cd config
rm module.sh
ln -s module-default.sh module.sh
cd android/contrib
sh compile-ffmpeg clean
If you prefer less codec/format for smaller binary size (include hevc function)
cd config
rm module.sh
ln -s module-lite-hevc.sh module.sh
cd android/contrib
sh compile-ffmpeg clean
If you prefer less codec/format for smaller binary size (by default)
cd config
rm module.sh
ln -s module-lite.sh module.sh
cd android/contrib
sh compile-ffmpeg clean
固然也能夠根據須要本身裁剪. 咱們來看下ijkplayer/config/module-lite.sh 即default裁剪模式支持哪些編解碼方式 咱們能夠看到 export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=hls" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=aac" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=h264" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=rtp" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtmp" ### 四. ijkplayer的java層源碼分析 【先佔坑,接下來詳解】 ### 五. 項目中ijkplayer的封裝以及mediaview的封裝以及使用 【先佔坑,接下來詳解】 ### 六. ijkplayer底層學習 【先佔坑,接下來重點學習】 ### 七. 開源項目 【接下來仿網易雲音樂,寫一個開源項目,歡迎多多關注】 ### 七. 常見問題以及解決方案 1. [ijkplayer播放rtmp直播流,延遲明顯 ](https://github.com/Bilibili/ijkplayer/issues/210) 2. 全屏播放 3. 有時候會開始直播時出現黑屏 4. 有時候會出現花屏 5. 解碼方式設置 6. 如何區分點播直播 7. 是否須要開啓硬件加速 8. [How to set up only listen to the sound does not show video?](https://github.com/Bilibili/ijkplayer/issues/1074) 9. 如何設置後臺播放 10. 視頻加載速度慢 The traffic speed is mostly depending on the quality of video CDN, not player itself. 11. 怎麼靜音 和非靜音 mute/unmute system volume.There is no mute/unmute API in ijkplayer. 12. 視頻黑屏,可是有聲音 肯定下視頻源的編碼方式,ijk默認只帶了h264解碼code 13. 適配問題,對於不一樣的cpu架構,須要編譯不一樣的so庫 14. 播放視頻有的設備聲畫不一樣步 15. 如何查看m3u8時長 cat game05.m3u8 | grep EXTINF | wc -l 32 16. how to change the video quality? Video quality is determined when being encoded.I don't think it can be changed by player. 17. 倍速播放 Not until Android 6.0 18. 爲何往前拖動進度條後,還會日後退幾秒 seek只支持關鍵幀,出現這個狀況就是原始的視頻文件中i 幀比較少,播放器會在拖動的位置找最近的關鍵幀。 19. how to change URL when ijkplayer is playing RTMP video Create new player. 20. 怎樣添加字幕呢? 若是但願字幕時間精確,能夠在native層作解析和時間同步,到了時間後回調給java層,通常字幕文件加載都是在java層作的,解析文件格式,而後按照時間區間來顯示。 21. 如何設置硬解? ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "analyzeduration", "2000000");
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "probsize", "4096");
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 0);
```
視頻基礎知識
多媒體編解碼基礎知識
流媒體中用到的幾個協議簡介
流媒體協議介紹(rtp/rtcp/rtsp/rtmp/mms/hls)
android-developer
No RTSP keep-alive packets in 2.3 causing streaming server to close the connection
H264解碼器源碼(Android 1.6 版)
Android VLC播放器二次開發1——程序結構分析
能夠用WebRTC來作視頻直播嗎?
WebRTC音視頻開發總結
雷霄驊(leixiaohua1020)的專欄
MediaPlayer