流媒體協(xié)議介紹
偽流媒體 :
偽流技術(shù)是一種能在常見HTTP服務(wù)器如APACHE、tomcat、IIS或lighttpd上安裝提供的一種協(xié)議。它使用服務(wù)端腳本來提供FLASH到服務(wù)器的視頻交互。播放器在URL上攜帶start time的參數(shù)發(fā)送HTTP請求到服務(wù)端,服務(wù)端的腳本處理視頻流并且給予回復(fù),保證提供的視頻流起始位置與START TIME參數(shù)所對應(yīng)。使用偽流或其他流式的解決方案最大的好處是:能跳轉(zhuǎn)到尚未下載到的視頻部分。
特點(diǎn):
- 漸進(jìn)式下載, 邊下邊存, 文件會(huì)保存
- 使用Http協(xié)議, 支持快進(jìn), 時(shí)間跳轉(zhuǎn)等, 體驗(yàn)上跟流媒體很像
- 支持FLV和H.264的視頻
流媒體 :
流媒體是指采用流式傳輸?shù)姆绞皆贗nternet播放的媒體格式。 又叫流式媒體,利用視頻傳送服務(wù)器把數(shù)據(jù)包傳送到網(wǎng)絡(luò)上。用戶通過對這些數(shù)據(jù)進(jìn)行解析后,還原發(fā)送的內(nèi)容.
特點(diǎn):
- 邊下邊播, 不會(huì)保存文件
- 以數(shù)據(jù)流的形式傳遞數(shù)據(jù), 流過就沒有了
常見的流媒體協(xié)議
常見公開的直播協(xié)議有:RTMP、HLS、HDL(HTTP-FLV)、RTP, 其中以RTMP, HLS居多.
RTMP協(xié)議
RTMP (Real Time Messaging Protocol, 實(shí)時(shí)消息傳輸協(xié)議) 協(xié)議基于TCP,是一個(gè)協(xié)議族,包括RTMP基本協(xié)議及RTMPT/RTMPS/RTMPE等多種變種。RTMP是一種設(shè)計(jì)用來進(jìn)行實(shí)時(shí)數(shù)據(jù)通信的網(wǎng)絡(luò)協(xié)議,主要用來在Flash/AIR平臺(tái)和支持RTMP協(xié)議的流媒體/交互服務(wù)器之間進(jìn)行音視頻和數(shù)據(jù)通信.
RTMP實(shí)時(shí)消息傳送協(xié), 是Adobe的專利協(xié)議, 專為Flash播放器和服務(wù)器之間的音頻, 視頻和數(shù)據(jù)傳輸所定義的開放協(xié)議。默認(rèn)使用1935端口.
使用RTMP協(xié)議的優(yōu)勢:
- 開源軟件和開源庫的支持穩(wěn)定完整, 如開源的librtmp庫,服務(wù)端有nginx-rtmp插件
- 播放端安裝率高。只要瀏覽器支持FlashPlayer就能非常簡易的播放RTMP的直播
HLS協(xié)議
HLS (Http Live Streaming) 是由蘋果提出基于HTTP的流媒體傳輸協(xié)議. 主要用于Mac和iOS音視頻服務(wù)。支持推流和播放. 基于HLS的直播流URL是一個(gè).m3u8文件, 里面包含了最近的若干個(gè).TS視頻
使用HLS協(xié)議的使用:
- iOS系統(tǒng)和masOS系統(tǒng)自帶的播放器, Safari都可以直接播放基于HLS協(xié)議的視頻
- HTML5可以直接打開播放, 只要瀏覽器即可完成播放
使用IJKPLayer實(shí)現(xiàn)直播
IJKPlayer是Bilibili對開源框架FFmpeg(一個(gè)基于C的軟解碼視頻播放開源框架)的封裝, 使用相對簡單
編譯iOS版的IJKPlayer
1.安裝Homebrew, git, yasm
# 安裝Homebrew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
#安裝yasm
brew install yasm
#mac系統(tǒng)已經(jīng)安裝了git, 不需要再安裝
#brew install git
2.模塊選擇
#進(jìn)入ijkplayer / config 目錄
cd config
#移除module.sh文件
rm module.sh
#根據(jù)需要, 執(zhí)行下面3句代碼的其中一句
# 打包的庫支持更多視頻格式和解碼器
ln -s module-default.sh module.sh
# 打包出來的庫體積更小
ln -s module-lite.sh module.sh
# 打包出來的庫體積更小, 支持HEVC (High Efficiency Video Coding, 高效視頻編碼, 即H-265)
ln -s module-lite-hevc.sh module.sh
- 偏好更多的解碼器/視頻格式支持, 則鏈接module-default.sh
- 偏好打包出來的庫體積更小 (默認(rèn)格式支持), 則鏈接module-lite.sh module.sh
- 偏好打包出來的庫體積更小 (包含HEVC支持), 則鏈接module-lite-hevc.sh
3.編譯iOS版本
# 執(zhí)行ijkplayer目錄下初始化ios腳本
./init-ios.sh
#腳本運(yùn)行后會(huì)下載數(shù)據(jù), 需要一點(diǎn)時(shí)間, 等待操作完成, 再繼續(xù)
# cd 到 ijkplayer / ios 目錄
cd ios
# 清空編譯的文件
./compile-ffmpeg.sh clean
# 編譯全部, 比較耗時(shí)
./compile-ffmpeg.sh all
完成上述操作后, 在ijkplayer / ios 目錄中, 會(huì)多出4個(gè)文件夾, 是針對不同架構(gòu)平臺(tái)的ffmpeg庫
- ffmpeg-arm64
- ffmpeg-armv7
- ffmpeg-X86_64
- ffmpeg-i386
編譯出IJKMediaFramework.framework文件
運(yùn)行 ijkplayer / ios / IJKMediaPlayer 目錄中的xcode項(xiàng)目, 分別在模擬器與真機(jī)設(shè)備下Build出對應(yīng)版本的framework文件
-
可考慮在開發(fā)階段將真機(jī)與模擬器的庫文件使用lipo合并, 方便開發(fā)測試
- 最終發(fā)布時(shí)應(yīng)該換回真機(jī)版庫文件, 減少項(xiàng)目文件的體積
lipo -create 模擬器版本庫路徑 真機(jī)版本庫路徑 -output 輸出文件路徑
- 發(fā)布應(yīng)用時(shí), 應(yīng)該將庫打包成Release版本, 而不是默認(rèn)的Debug版本
根據(jù)編譯的錯(cuò)誤信息, 添加對應(yīng)的系統(tǒng)框架
libz.tbd // 以_deflate開頭, _inflate開頭的相關(guān)錯(cuò)誤
libbz2.tbd // 以_BZ2_開頭的相關(guān)錯(cuò)誤
// 實(shí)測僅需要上面的兩個(gè)庫, 下列庫為錯(cuò)誤時(shí)的備選
AudioToolbox.framework
AVFoundation.framework
CoreGraphics.framework
CoreMedia.framework
CoreVideo.framework
MediaPlayer.framework
MobileCoreServices.framework
OpenGLES.framework
QuartzCore.framework
UIKit.framework
VideoToolbox.framework
代碼實(shí)現(xiàn)
使用IJKFFMoviePlayerController播放視頻 (類似于系統(tǒng)MPMoviePlayerController的使用)
- (void)viewDidLoad {
// 默認(rèn)選項(xiàng)配置
IJKFFOptions *options = [IJKFFOptions optionsByDefault];
// 創(chuàng)建播放控制器, 支持RTMP, HLS直播流, 本地視頻文件播放
IJKFFMoviePlayerController *moviePlayer = [[IJKFFMoviePlayerController alloc] initWithContentURLString:@"視頻鏈接" withOptions:options];
// IJKFFMoviePlayerController的view屬性是視頻內(nèi)容的展示視圖
[self.view addSubview:moviePlayer.view];
// 不要忽略frame值, 否則看不到內(nèi)容
moviePlayer.view.frame = self.view.bounds;
// 視頻內(nèi)容的拉伸樣式
moviePlayer.scalingMode = IJKMPMovieScalingModeAspectFit;
// 是否自動(dòng)開始播放
moviePlayer.shouldAutoplay = YES;
// moviePlayer.view簡單適配橫豎屏
self.moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
self.view.autoresizesSubviews = YES;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// 視圖即將顯示時(shí), 準(zhǔn)備播放
[self.moviePlayer prepareToPlay];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// 視圖要消失時(shí), 關(guān)閉播放
[self.moviePlayer shutdown];
}