版權聲明:本文為博主原創文章,未經博主允許不得轉載。
前言
隨着音視頻領域的火熱,在很多領域(教育,游戲,娛樂,體育,跑步,餐飲,音樂等)嘗試做音視頻直播/點播功能,那么作為開發一個小白,如何快速學習音視頻基礎知識,了解音視頻編解碼的傳輸協議,編解碼方式,以及如何技術選型,如何解決遇到的坑,本文拋磚引玉,歡迎大咖交流。
一. 音視頻的基礎知識
1.1 基本概念
視頻是什么
靜止的畫面叫圖像(picture)。連續的圖像變化每秒超過24幀(frame)畫面以上時,根椐視覺暫留原理, 人眼無法辨別每付單獨的靜態畫面,看上去是平滑連續的視覺效果。這樣的連續畫面叫視頻。 當連續圖像變化每秒低於24幀畫面時,人眼有不連續的感覺叫動畫(cartoon)
流媒體
指采用流式傳輸的方式在Internet / Intranet播放的媒體格式.流媒體的數據流隨時傳送隨 時播放,只是在開始時有些延遲
邊下載邊播入的流式傳輸方式不僅使啟動延時大幅度地縮短,而且對系統緩存容量的需求也大大降低,極大地減少用戶用在等待的時間
分辨率
分辨率是一個表示平面圖像精細程度的概念,通常它是以橫向和縱向點的數量來衡量的,表示成水平點數垂直點數的形式,
在計算機顯示領域我們也表示成“每英寸像素”(ppi).在一個固定的平面內,分辨率越高,意味着可使用的點數越多,圖像越細致
碼流
數據傳輸時單位時間傳送的數據位數,可以理解其為取樣率,單位時間內取樣率越大,精度就越高,處理出來的文件就越接近原始文件,但是文件體積與取樣率是成正比的
如何用最低的碼率達到最少的失真,一般我們用的單位是kbps即千位每秒
幀率
幀/秒(frames per second)的縮寫,也稱為幀速率,測量用於保存、顯示動態視頻的信息數量。每一幀都是靜止的圖象,快速連續地顯示幀便形成了運動的假象。 每秒鍾幀數 (fps) 愈多,所顯示的動作就會愈流暢,可理解為1秒鍾時間里刷新的圖片的幀數,也可以理解為圖形處理器每秒鍾能夠刷新幾次,也就是指每秒鍾能夠播放(或者錄制)多少格畫面。
1.2 多媒體的格式分類
封裝格式(專業上講叫容器,通俗的叫文件格式),視頻編解碼,音頻編解碼
####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 壓縮編碼
等等
1.3 流媒體協議(RTP RTCP RTSP RTMP HLS)
- RTP RTCP RTSP
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協議的網絡應用層協議
- RTMP
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的這種技術特點,決定了它的延遲一般總是會高於普通的流媒體直播協議。
二. android音視頻的開發
播放流程: 獲取流–>解碼–>播放
錄制播放路程: 錄制音頻視頻–>剪輯–>編碼–>上傳服務器 別人播放.
直播過程 : 錄制音視頻–>編碼–>流媒體傳輸–>服務器—>流媒體傳輸到其他app–>解碼–>播放
幾個重要的環節
- 錄制音視頻 AudioRecord/MediaRecord
- 視頻剪輯 mp4parser 或ffmpeg
- 音視頻編碼 aac&h264
- 上傳大文件 網絡框架,進度監聽,斷點續傳
- 流媒體傳輸 流媒體傳輸協議rtmp rtsp hls
- 音視頻解碼 aac&h264
- 渲染播放 MediaPlayer
問題
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.
三. ijkplayer的引入&介紹&使用
正如上文所說,android本事對音視頻流媒體傳輸協議,以及音視頻編解碼支持有限.所以對於直播類應用,要自己解碼
3.1 調研過程
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嘗試過,稍微復雜些.
3.2 ijkplayer的導入&編譯&使用
如果不需要對源碼進行修改,在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' }
當然如何你想對其源碼進行修改,采用如下方式
1. 需要
下載配置 NDK r10e
配置androidsdk
# add these lines to your ~/.bash_profile or ~/.profile
# export ANDROID_SDK=
# export ANDROID_NDK=
2.
Build Android
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導入工程 # Android Studio: # Open an existing Android Studio project # Select android/ijkplayer/ and import
可以根據需要對音視頻編解碼庫進行裁剪.編譯出最小的滿足需要的庫
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-parser=aac”
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底層學習
【先占坑,接下來重點學習】
七. 開源項目
【接下來仿網易雲音樂,寫一個開源項目,歡迎多多關注】
七. 常見問題以及解決方案
- ijkplayer播放rtmp直播流,延遲明顯
- 全屏播放
- 有時候會開始直播時出現黑屏
- 有時候會出現花屏
- 解碼方式設置
- 如何區分點播直播
- 是否需要開啟硬件加速
- How to set up only listen to the sound does not show video?
- 如何設置后台播放
- 視頻加載速度慢
The traffic speed is mostly depending on the quality of video CDN, not player itself. - 怎么靜音 和非靜音
mute/unmute system volume.There is no mute/unmute API in ijkplayer. - 視頻黑屏,但是有聲音
確定下視頻源的編碼方式,ijk默認只帶了h264解碼code - 適配問題,對於不同的cpu架構,需要編譯不同的so庫
- 播放視頻有的設備聲畫不同步
- 如何查看m3u8時長
cat game05.m3u8 | grep EXTINF | wc -l 32 - how to change the video quality?
Video quality is determined when being encoded.I don’t think it can be changed by player. - 倍速播放
Not until Android 6.0 - 為什么往前拖動進度條后,還會往后退幾秒
seek只支持關鍵幀,出現這個情況就是原始的視頻文件中i 幀比較少,播放器會在拖動的位置找最近的關鍵幀。 - how to change URL when ijkplayer is playing RTMP video
Create new player. - 怎樣添加字幕呢?
如果希望字幕時間精確,可以在native層做解析和時間同步,到了時間后回調給java層,一般字幕文件加載都是在java層做的,解析文件格式,然后按照時間區間來顯示。 - 如何設置硬解?
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