前言
隨著音視頻領域的火熱,在很多領域(教育,游戲,娛樂,體育,跑步,餐飲,音樂等)嘗試做音視頻直播/點播功能,那么作為開發一個小白,如何快速學習音視頻基礎知識,了解音視頻編解碼的傳輸協議,編解碼方式,以及如何技術選型,如何解決遇到的坑,本文拋磚引玉,歡迎大咖交流。
視頻是什么
靜止的畫面叫圖像(picture)。連續的圖像變化每秒超過24幀(frame)畫面以上時,根椐視覺暫留原理,人眼無法辨別每付單獨的靜態畫面,看上去是平滑連續的視覺效果。這樣的連續畫面叫視頻。當連續圖像變化每秒低于24幀畫面時,人眼有不連續的感覺叫動畫(cartoon)
流媒體
指采用流式傳輸的方式在Internet / Intranet播放的媒體格式.流媒體的數據流隨時傳送隨 時播放,只是在開始時有些延遲
邊下載邊播入的流式傳輸方式不僅使啟動延時大幅度地縮短,而且對系統緩存容量的需求也大大降低,極大地減少用戶用在等待的時間
分辨率
分辨率是一個表示平面圖像精細程度的概念,通常它是以橫向和縱向點的數量來衡量的,表示成水平點數垂直點數的形式,
在計算機顯示領域我們也表示成“每英寸像素”(ppi).在一個固定的平面內,分辨率越高,意味著可使用的點數越多,圖像越細致
碼流
數據傳輸時單位時間傳送的數據位數,可以理解其為取樣率,單位時間內取樣率越大,精度就越高,處理出來的文件就越接近原始文件,但是文件體積與取樣率是成正比的
如何用最低的碼率達到最少的失真,一般我們用的單位是kbps即千位每秒
幀率
幀/秒(frames persecond)的縮寫,也稱為幀速率,測量用于保存、顯示動態視頻的信息數量。每一幀都是靜止的圖象,快速連續地顯示幀便形成了運動的假象。每秒鐘幀數 (fps) 愈多,所顯示的動作就會愈流暢,可理解為1秒鐘時間里刷新的圖片的幀數,也可以理解為圖形處理器每秒鐘能夠刷新幾次,也就是指每秒鐘能夠播放(或者錄制)多少格畫面。
封裝格式(專業上講叫容器,通俗的叫文件格式),視頻編解碼,音頻編解碼####1.1常見的封裝格式*MPEG: 編碼采用的容器,具有流的特性。里面又分為 PS,TS 等,PS 主要用于 DVD 存儲,TS 主要用于 HDTV.*MPEGAudio Layer3:大名鼎鼎的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 壓縮編碼等等
1.3 流媒體協議(RTP RTCP RTSP RTMP HLS)
RTP RTCP RTSP
RTP :(Real-timeTransport Protocol)是用于Internet上針對多媒體數據流的一種傳輸層協議.RTP協議和RTP控制協議RTCP一起使用,而且它是建立在UDP協議上的RTCP:Real-timeTransport Control Protocol或RTP Control Protocol或簡寫RTCP)實時傳輸控制協議,是實時傳輸協議(RTP)的一個姐妹協議RTP協議和RTP控制協議RTCP一起使用,而且它是建立在UDP協議上的RTSP:(RealTimeStreaming Protocol)是用來控制聲音或影像的多媒體串流協議,RTSP提供了一個可擴展框架,使實時數據,如音頻與視頻的受控、點播成為可能。數據源包括現場數據與存儲在剪輯中的數據。該協議目的在于控制多個數據發送連接,為選擇發送通道,如UDP、多播UDP與TCP提供途徑,并為選擇基于RTP上發送機制提供方法傳輸時所用的網絡通訊協定并不在其定義的范圍內,服務器端可以自行選擇使用TCP或UDP來傳送串流內容,比較能容忍網絡延遲RTP不像http和ftp可完整的下載整個影視文件,它是以固定的數據率在網絡上發送數據,客戶端也是按照這種速度觀看影視文件,當影視畫面播放過后,就不可以再重復播放,除非重新向服務器端要求數據。RTSP與RTP最大的區別在于:RTSP是一種雙向實時數據傳輸協議,它允許客戶端向服務器端發送請求,如回放、快進、倒退等操作。當然,RTSP可基于RTP來傳送數據,還可以選擇TCP、UDP、組播UDP等通道來發送數據,具有很好的擴展性。它時一種類似與http協議的網絡應用層協議
RTMP
RTMP(Real Time Messaging Protocol)實時消息傳送協議是Adobe Systems公司為Flash播放器和服務器之間音頻、視頻和數據傳輸 開發的開放協議
HLS
HTTPLiveStreaming(HLS)是蘋果公司(AppleInc.)實現的基于HTTP的流媒體傳輸協議,可實現流媒體的直播和點播,主要應用在iOS系統,為iOS設備(如iPhone、iPad)提供音視頻直播和點播方案。HLS點播,基本上就是常見的分段HTTP點播,不同在于,它的分段非常小。相對于常見的流媒體直播協議,例如RTMP協議、RTSP協議、MMS協議等,HLS直播最大的不同在于,直播客戶端獲取到的,并不是一個完整的數據流。HLS協議在服務器端將直播數據流存儲為連續的、很短時長的媒體文件(MPEG-TS格式),而客戶端則不斷的下載并播放這些小文件,因為服務器端總是會將最新的直播數據生成新的小文件,這樣客戶端只要不停的按順序播放從服務器獲取到的文件,就實現了直播。由此可見,基本上可以認為,HLS是以點播的技術方式來實現直播。由于數據通過HTTP協議傳輸,所以完全不用考慮防火墻或者代理的問題,而且分段文件的時長很短,客戶端可以很快的選擇和切換碼率,以適應不同帶寬條件下的播放。不過HLS的這種技術特點,決定了它的延遲一般總是會高于普通的流媒體直播協議。
播放流程: 獲取流-->解碼-->播放
錄制播放路程: 錄制音頻視頻-->剪輯-->編碼-->上傳服務器 別人播放.
直播過程 : 錄制音視頻-->編碼-->流媒體傳輸-->服務器--->流媒體傳輸到其他app-->解碼-->播放
幾個重要的環節
錄制音視頻 AudioRecord/MediaRecord
視頻剪輯 mp4parser 或ffmpeg
音視頻編碼 aac&h264
上傳大文件 網絡框架,進度監聽,斷點續傳
流媒體傳輸 流媒體傳輸協議rtmp rtsp hls
音視頻解碼 aac&h264
渲染播放 MediaPlayer
問題
Android本身有提供MediaPlayer,那么mediaplayer支持哪些格式的流媒體協議吶?又支持哪些解碼器吶?兼容性如何,性功能如何?
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只適合小范圍(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'}
當然如何你想對其源碼進行修改,采用如下方式
需要
下載配置 NDK r10e
配置androidsdk
add these lines to your ~/.bash_profile or ~/.profile
export ANDROID_SDK=
export ANDROID_NDK=
2.
```
Build Android
Gitclonehttps://github.com/Bilibili/ijkplayer.gitijkplayer-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導入工程
Android Studio:
Open an existing Android Studio project
Select android/ijkplayer/ and import
可以根據需要對音視頻編解碼庫進行裁剪.編譯出最小的滿足需要的庫bilibili提供三種裁剪方式Ifyou prefermorecodec/format
cd config
rm module.sh
ln -s module-default.sh module.sh
cd android/contrib
sh compile-ffmpeg clean
Ifyou prefer less codec/formatfor smaller binarysize(includehevcfunction)
cd config
rm module.sh
ln -s module-lite-hevc.sh module.sh
cd android/contrib
sh compile-ffmpeg clean
Ifyou prefer less codec/formatforsmaller binarysize(bydefault)
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的封裝以及mediaview的封裝以及使用
【先占坑,接下來詳解】
【先占坑,接下來重點學習】
【接下來仿網易云音樂,寫一個開源項目,歡迎多多關注】### 七. 常見問題以及解決方案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解碼code13.適配問題,對于不同的cpu架構,需要編譯不同的so庫14.播放視頻有的設備聲畫不同步15.如何查看m3u8時長? ? cat game05.m3u8 | grep EXTINF | wc -l 3216.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.018.為什么往前拖動進度條后,還會往后退幾秒seek只支持關鍵幀,出現這個情況就是原始的視頻文件中i 幀比較少,播放器會在拖動的位置找最近的關鍵幀。19.how to change URL when ijkplayer is playing RTMP videoCreate new player.20.怎樣添加字幕呢?如果希望字幕時間精確,可以在native層做解析和時間同步,到了時間后回調給java層,一般字幕文件加載都是在java層做的,解析文件格式,然后按照時間區間來顯示。21.如何設置硬解?ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
```
流媒體協議介紹(rtp/rtcp/rtsp/rtmp/mms/hls)
No RTSP keep-alive packets in 2.3 causing streaming server to close the connection