android音視頻點/直播模塊開發

前言

隨著音視頻領域的火熱,在很多領域(教育,遊戲,娛樂,體育,跑步,餐飲,音樂等)嘗試做音視頻直播/點播功能,那麼作為開發一個小白,如何快速學習音視頻基礎知識,瞭解音視頻編解碼的傳輸協議,編解碼方式,以及如何技術選型,如何解決遇到的坑,本文拋磚引玉,歡迎大咖交流。

一. 音視頻的基礎知識

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人以內)音視頻會議,不適合做直播

接下來介紹下 ffmpeg vlc ijkplayer以及選擇方案

ffmpeg是一個非常強大的音視頻編解碼開源庫,目前市場上流行的播放器,大部分都是基於此開發的,包括暴風,騰訊,等等以及上面提到的vitamio,vlc,ijkplayer

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=”COMMONFFCFGFLAGS–enable?demuxer=hls”exportCOMMONFFCFGFLAGS=”COMMON_FF_CFG_FLAGS –enable-parser=aac”

export COMMON_FF_CFG_FLAGS=”COMMONFFCFGFLAGS–enable?parser=h264”exportCOMMONFFCFGFLAGS=”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);

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *