前不久抽空對目前比較火的視頻直播,做了下研究與探索,了解其整體實現(xiàn)流程,以及探討移動端HTML5直播可行性方案。
發(fā)現(xiàn)目前 WEB 上主流的視頻直播方案有 HLS 和 RTMP,移動 WEB 端目前以 HLS 為主(HLS存在延遲性問題,也可以借助 video.js 采用RTMP),PC端則以 RTMP 為主實時性較好,接下來將圍繞這兩種視頻流協(xié)議來展開H5直播主題分享。
HTTP Live Streaming(簡稱 HLS)是一個基于 HTTP 的視頻流協(xié)議,由 Apple 公司實現(xiàn),Mac OS 上的 QuickTime、Safari 以及 iOS 上的 Safari 都能很好的支持 HLS,高版本 Android 也增加了對 HLS 的支持。一些常見的客戶端如:MPlayerX、VLC 也都支持 HLS 協(xié)議。
HLS 協(xié)議基于 HTTP,而一個提供 HLS 的服務(wù)器需要做兩件事:
瀏覽器使用的是 m3u8 文件。m3u8 跟音頻列表格式 m3u 很像,可以簡單的認為 m3u8 就是包含多個 ts 文件的播放列表。播放器按順序逐個播放,全部放完再請求一下 m3u8 文件,獲得包含最新 ts 文件的播放列表繼續(xù)播,周而復(fù)始。整個直播過程就是依靠一個不斷更新的 m3u8 和一堆小的 ts 文件組成,m3u8 必須動態(tài)更新,ts 可以走 CDN。一個典型的 m3u8 文件格式如下:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=200000
gear1/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=311111
gear2/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=484444
gear3/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=737777
gear4/prog_index.m3u8
可以看到 HLS 協(xié)議本質(zhì)還是一個個的 HTTP 請求 / 響應(yīng),所以適應(yīng)性很好,不會受到防火墻影響。但它也有一個致命的弱點:延遲現(xiàn)象非常明顯。如果每個 ts 按照 5 秒來切分,一個 m3u8 放 6 個 ts 索引,那么至少就會帶來 30 秒的延遲。如果減少每個 ts 的長度,減少 m3u8 中的索引數(shù),延時確實會減少,但會帶來更頻繁的緩沖,對服務(wù)端的請求壓力也會成倍增加。所以只能根據(jù)實際情況找到一個折中的點。
對于支持 HLS 的瀏覽器來說,直接這樣寫就能播放了:
<video src="http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"height="300"width="400"preload="auto"autoplay="autoplay"loop="loop"webkit-playsinline="true"></video>
注意
:HLS 在 PC 端僅支持safari瀏覽器,類似chrome瀏覽器使用 HTML5 video
標簽無法播放 m3u8 格式,可直接采用網(wǎng)上一些比較成熟的方案,如: sewise-player 、 MediaElement 、 videojs-contrib-hls 、 jwplayer 。
Real Time Messaging Protocol(簡稱 RTMP)是 Macromedia 開發(fā)的一套視頻直播協(xié)議,現(xiàn)在屬于 Adobe。這套方案需要搭建專門的 RTMP 流媒體服務(wù)如 Adobe Media Server,并且在瀏覽器中只能使用 Flash 實現(xiàn)播放器。它的實時性非常好,延遲很小,但無法支持移動端 WEB 播放是它的硬傷。
雖然無法在iOS的H5頁面播放,但是對于iOS原生應(yīng)用是可以自己寫解碼去解析的, RTMP 延遲低、實時性較好。
瀏覽器端, HTML5 video
標簽無法播放 RTMP 協(xié)議的視頻,可以通過 video.js 來實現(xiàn)。
<linkvideo-js vjs-default-skin"controlspreload="auto"width="640"height="264"loop="loop"webkit-playsinline><sourcesrc="rtmp://10.14.221.17:1935/rtmplive/home"type='rtmp/flv'></video><scriptsrc="http://vjs.zencdn.net/5.8.8/video.js"></script><script>videojs.options.flash.swf = 'video.swf';videojs('example_video_1').ready(function(){this.play();});</script>
協(xié)議 | 原理 | 延時 | 優(yōu)點 | 使用場景 | |
---|---|---|---|---|---|
HLS | 短鏈接Http | 集合一段時間數(shù)據(jù)生成ts切片文件更新m3u8文件 | 10s - 30s | 跨平臺 | 移動端為主 |
RTMP | 長鏈接Tcp | 每個時刻的數(shù)據(jù)收到后立即發(fā)送 | 2s | 延時低、實時性好 | PC+直播+實時性要求高+互動性強 |
目前直播展示形式,通常以YY直播、映客直播這種頁面居多,可以看到其結(jié)構(gòu)可以分成三層:① 背景視頻層 ② 關(guān)注、評論模塊 ③ 點贊動畫
而現(xiàn)行H5類似直播頁面,實現(xiàn)技術(shù)難點不大,其可以通過實現(xiàn)方式分為:① 底部視頻背景使用video視頻標簽實現(xiàn)播放 ② 關(guān)注、評論模塊利用 WebScoket 來實時發(fā)送和接收新的消息通過DOM 和 CSS3 實現(xiàn) ③ 點贊利用 CSS3 動畫
了解完直播形式之后,接下來整體了解直播流程。
直播整體流程大致可分為:
視頻采集端:可以是電腦上的音視頻輸入設(shè)備、或手機端的攝像頭、或麥克風,目前以移動端手機視頻為主。
直播流視頻服務(wù)端:一臺Nginx服務(wù)器,采集視頻錄制端傳輸?shù)囊曨l流(H264/ACC編碼),由服務(wù)器端進行解析編碼,推送RTMP/HLS格式視頻流至視頻播放端。
視頻播放端:可以是電腦上的播放器(QuickTime Player、VLC),手機端的native播放器,還有就是 H5 的video標簽等,目前還是以手機端的native播放器為主。
對于H5視頻錄制,可以使用強大的 webRTC (Web Real-Time Communication)是一個支持網(wǎng)頁瀏覽器進行實時語音對話或視頻對話的技術(shù),缺點是只在 PC 的 Chrome 上支持較好,移動端支持不太理想。
① 調(diào)用 window.navigator.webkitGetUserMedia()
獲取用戶的PC攝像頭視頻數(shù)據(jù)。
② 將獲取到視頻流數(shù)據(jù)轉(zhuǎn)換成 window.webkitRTCPeerConnection
(一種視頻流數(shù)據(jù)格式)。
③ 利用 WebScoket
將視頻流數(shù)據(jù)傳輸?shù)椒?wù)端。
注意
:雖然Google一直在推WebRTC,目前已有不少成型的產(chǎn)品出現(xiàn),但是大部分移動端的瀏覽器還不支持 webRTC(最新iOS 10.0也不支持),所以真正的視頻錄制還是要靠客戶端(iOS,Android)來實現(xiàn),效果會好一些。
① 音視頻的采集,利用AVCaptureSession和AVCaptureDevice可以采集到原始的音視頻數(shù)據(jù)流。
② 對視頻進行H264編碼,對音頻進行AAC編碼,在iOS中分別有已經(jīng)封裝好的編碼庫( x264編碼 、 faac編碼 、 ffmpeg編碼 )來實現(xiàn)對音視頻的編碼。
③ 對編碼后的音、視頻數(shù)據(jù)進行組裝封包。
④ 建立RTMP連接并上推到服務(wù)端。
① 先clone nginx項目到本地:
brew tap homebrew/nginx
② 執(zhí)行安裝 nginx-rtmp-module
brew install nginx-full --with-rtmp-module
查找到nginx.conf配置文件(路徑/usr/local/etc/nginx/nginx.conf),配置RTMP、HLS。
① 在http節(jié)點之前添加 rtmp 的配置內(nèi)容:
rtmp{server{#監(jiān)聽的端口listen1935;# RTMP 直播流配置applicationrtmplive {liveon;#為 rtmp 引擎設(shè)置最大連接數(shù)。默認為 offmax_connections1024; }# HLS 直播流配置applicationhls{liveon;hlson;hls_path/usr/local/var/www/hls;hls_fragment1s; } }}
② 在http中添加 hls 的配置
location /hls{# Serve HLS fragments types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } root /usr/local/var/www;#add_header Cache-Controll no-cache; expires -1; }
重啟nginx服務(wù),瀏覽器中輸入 http://localhost:8080 ,是否出現(xiàn)歡迎界面確定nginx重啟成功。
nginx -sreload
當服務(wù)器端接收到采集視頻錄制端傳輸過來的視頻流時,需要對其進行解析編碼,推送RTMP/HLS格式視頻流至視頻播放端。通常使用的常見編碼庫方案,如 x264編碼 、 faac編碼 、 ffmpeg編碼 等。
鑒于 FFmpeg 工具集合了多種音頻、視頻格式編碼,我們可以優(yōu)先選用FFmpeg進行轉(zhuǎn)換格式、編碼推流。
1.安裝 FFmpeg 工具
brew installffmpeg
2.推流MP4文件
視頻文件地址:/Users/gao/Desktop/video/test.mp4
推流拉流地址:rtmp://localhost:1935/rtmplive/home,rtmp://localhost:1935/rtmplive/home
//RTMP 協(xié)議流ffmpeg -re -i/Users/gao/Desktop/video/test.mp4-vcodec libx264 -acodec aac -f flv rtmp://10.14.221.17:1935/rtmplive/home//HLS 協(xié)議流ffmpeg -re -i/Users/gao/Desktop/video/test.mp4-vcodec libx264 -vprofile baseline -acodec aac -ar44100-strict -2-ac1-f flv -q10rtmp://10.14.221.17:1935/hls/test
注意
: 當我們進行推流之后,可以安裝 VLC 、ffplay(支持rtmp協(xié)議的視頻播放器)本地拉流進行演示
3.FFmpeg推流命令
① 視頻文件進行直播
ffmpeg -re -i/Users/gao/Desktop/video/test.mp4-vcodec libx264 -vprofile baseline -acodec aac -ar44100-strict -2-ac1-f flv -q10rtmp://192.168.1.101:1935/hls/testffmpeg -re -i/Users/gao/Desktop/video/test.mp4-vcodec libx264 -vprofile baseline -acodec aac -ar44100-strict -2-ac1-f flv -q10rtmp://10.14.221.17:1935/hls/test
② 推流攝像頭+桌面+麥克風錄制進行直播
ffmpeg -f avfoundation -framerate 30-i"1:0"\-f avfoundation -framerate30-video_size640x480 -i"0"\-c:v libx264 -preset ultrafast \-filter_complex'overlay=main_w-overlay_w-10:main_h-overlay_h-10'-acodec libmp3lame -ar44100-ac1-f flv rtmp://192.168.1.101:1935/hls/test
移動端iOS和 Android 都天然支持HLS協(xié)議,做好視頻采集端、視頻流推流服務(wù)之后,便可以直接在H5頁面配置 video 標簽播放直播視頻。
<videocontrols preload="auto"autoplay="autoplay"loop="loop"webkit-playsinline> <source src="http://10.14.221.8/hls/test.m3u8"type="application/vnd.apple.mpegurl"/> <pclass="warning">Your browser does not support HTML5video.</p></video>
ps
:① video標簽添加 webkit-playsinline
屬性(iOS支持)是保證視頻在網(wǎng)頁中內(nèi)嵌播放。
② 針對微信瀏覽器,video標簽層級最高的問題,需要申請?zhí)砑影酌麊?,請參?http://bbs.mb.qq.com/thread-1242581-1-1.html?ptlang=2052。
本文從視頻采集上傳,服務(wù)器處理視頻推流,以及H5頁面播放直播視頻一整套流程,具體闡述了直播實現(xiàn)原理,實現(xiàn)過程中會遇到很多性能優(yōu)化問題。
① H5 HLS 限制必須是H264+AAC編碼。
② H5 HLS 播放卡頓問題,server 端可以做好分片策略,將 ts 文件放在 CDN 上,前端可盡量做到 DNS 緩存等。
③ H5 直播為了達到更好的實時互動,也可以采用RTMP協(xié)議,通過 video.js
實現(xiàn)播放。
參考資料: