天天看點

【騰訊bugly幹貨分享】HTML 5 視訊直播一站式掃盲

本文來自于騰訊bugly開發者社群,非經作者同意,請勿轉載,原文位址:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1277

視訊直播這麼火,再不學就 out 了。

為了緊跟潮流,本文将向大家介紹一下視訊直播中的基本流程和主要的技術點,包括但不限于前端技術。

當然可以, H5 火了這麼久,涵蓋了各個方面的技術。

對于視訊錄制,可以使用強大的 webRTC(Web Real-Time Communication)是一個支援網頁浏覽器進行實時語音對話或視訊對話的技術,缺點是隻在 PC 的 chrome 上支援較好,移動端支援不太理想。

對于視訊播放,可以使用 HLS(HTTP Live Streaming)協定播放直播流, ios 和 android 都天然支援這種協定,配置簡單,直接使用 video 标簽即可。

webRTC 相容性:

video 标簽播放 hls 協定視訊:

簡單講就是把整個流分成一個個小的,基于 HTTP 的檔案來下載下傳,每次隻下載下傳一些,前面提到了用于 H5 播放直播視訊時引入的一個 .m3u8 的檔案,這個檔案就是基于 HLS 協定,存放視訊流中繼資料的檔案。

每一個 .m3u8 檔案,分别對應若幹個 ts 檔案,這些 ts 檔案才是真正存放視訊的資料,m3u8 檔案隻是存放了一些 ts 檔案的配置資訊和相關路徑,當視訊播放時,.m3u8 是動态改變的,video 标簽會解析這個檔案,并找到對應的 ts 檔案來播放,是以一般為了加快速度,.m3u8 放在 web 伺服器上,ts 檔案放在 cdn 上。

.m3u8 檔案,其實就是以 UTF-8 編碼的 m3u 檔案,這個檔案本身不能播放,隻是存放了播放資訊的文本檔案:

ts 檔案:

HLS 的請求流程是:

1 http 請求 m3u8 的 url。

2 服務端傳回一個 m3u8 的播放清單,這個播放清單是實時更新的,一般一次給出5段資料的 url。

3 用戶端解析 m3u8 的播放清單,再按序請求每一段的 url,擷取 ts 資料流。

簡單流程:

我們知道 hls 協定是将直播流分成一段一段的小段視訊去下載下傳播放的,是以假設清單裡面的包含5個 ts 檔案,每個 TS 檔案包含5秒的視訊内容,那麼整體的延遲就是25秒。因為當你看到這些視訊時,主播已經将視訊錄制好上傳上去了,是以時這樣産生的延遲。當然可以縮短清單的長度和單個 ts 檔案的大小來降低延遲,極緻來說可以縮減清單長度為1,并且 ts 的時長為1s,但是這樣會造成請求次數增加,增大伺服器壓力,當網速慢時回造成更多的緩沖,是以蘋果官方推薦的ts時長時10s,是以這樣就會大改有30s的延遲。參考資料:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html

當視訊直播可大緻分為:

1 視訊錄制端:一般是電腦上的音視訊輸入裝置或者手機端的攝像頭或者麥克風,目前以移動端的手機視訊為主。

2 視訊播放端:可以是電腦上的播放器,手機端的 native 播放器,還有就是 h5 的 video 标簽等,目前還是已手機端的 native 播放器為主。

3 視訊伺服器端:一般是一台 nginx 伺服器,用來接受視訊錄制端提供的視訊源,同時提供給視訊播放端流服務。

當首先明确幾個概念:

視訊編碼:所謂視訊編碼就是指通過特定的壓縮技術,将某個視訊格式的檔案轉換成另一種視訊格式檔案的方式,我們使用的 iphone 錄制的視訊,必須要經過編碼,上傳,解碼,才能真正的在使用者端的播放器裡播放。

編解碼标準:視訊流傳輸中最為重要的編解碼标準有國際電聯的H.261、H.263、H.264,其中 HLS 協定支援 H.264 格式的編碼。

音頻編碼:同視訊編碼類似,将原始的音頻流按照一定的标準進行編碼,上傳,解碼,同時在播放器裡播放,當然音頻也有許多編碼标準,例如 PCM 編碼,WMA 編碼,AAC 編碼等等,這裡我們 HLS 協定支援的音頻編碼方式是AAC編碼。

下面将利用 ios 上的攝像頭,進行音視訊的資料采集,主要分為以下幾個步驟:

1 音視訊的采集,ios 中,利用 AVCaptureSession和AVCaptureDevice 可以采集到原始的音視訊資料流。

2 對視訊進行 H264 編碼,對音頻進行 AAC 編碼,在 ios 中分别有已經封裝好的編碼庫來實作對音視訊的編碼。

3 對編碼後的音、視訊資料進行組裝封包;

4 建立 RTMP 連接配接并上推到服務端。

ps:由于編碼庫大多使用 c 語言編寫,需要自己使用時編譯,對于 ios,可以使用已經編譯好的編碼庫。

x264編碼:https://github.com/kewlbear/x264-ios

faac編碼:https://github.com/fflydev/faac-ios-build

ffmpeg編碼:https://github.com/kewlbear/FFmpeg-iOS-build-script

關于如果想給視訊增加一些特殊效果,例如增加濾鏡等,一般在編碼前給使用濾鏡庫,但是這樣也會造成一些耗時,導緻上傳視訊資料有一定延時。

和之前的 x264 一樣,ffmpeg 其實也是一套編碼庫,類似的還有 Xvid,Xvid 是基于 MPEG4 協定的編解碼器,x264是基于 H.264 協定的編碼器, ffmpeg 集合了各種音頻,視訊編解碼協定,通過設定參數可以完成基于 MPEG4,H.264 等協定的編解碼,demo 這裡使用的是 x264 編碼庫。

Real Time Messaging Protocol(簡稱 RTMP)是 Macromedia 開發的一套視訊直播協定,現在屬于 Adobe。和 HLS 一樣都可以應用于視訊直播,差別是 RTMP 基于 flash 無法在 ios 的浏覽器裡播放,但是實時性比 HLS 要好。是以一般使用這種協定來上傳視訊流,也就是視訊流推送到伺服器。

這裡列舉一下 hls 和 rtmp 對比:

簡所謂推流,就是将我們已經編碼好的音視訊資料發往視訊流伺服器中,一般常用的是使用 rtmp 推流,可以使用第三方庫 librtmp-iOS 進行推流,librtmp 封裝了一些核心的 api 供使用者調用,如果覺得麻煩,可以使用現成的 ios 視訊推流sdk,也是基于 rtmp 的,https://github.com/runner365/LiveVideoCoreSDK

簡簡單的推流伺服器搭建,由于我們上傳的視訊流都是基于 rtmp 協定的,是以伺服器也必須要支援 rtmp 才行,大概需要以下幾個步驟:

1 安裝一台 nginx 伺服器。

2 安裝 nginx 的 rtmp 擴充,目前使用比較多的是https://github.com/arut/nginx-rtmp-module

3 配置 nginx 的 conf 檔案:

4 重新開機 nginx,将 rtmp 的推流位址寫為 rtmp://ip:1935/hls/mystream,其中 hls_path 表示生成的 .m3u8 和 ts 檔案所存放的位址,hls_fragment 表示切片時長,mysteam 表示一個執行個體,即将來要生成的檔案名可以先自己随便設定一個。更多配置可以參考:https://github.com/arut/nginx-rtmp-module/wiki/

根據以上步驟基本上已經實作了一個支援 rtmp 的視訊伺服器了。

簡單來說,直接使用 video 标簽即可播放 hls 協定的直播視訊:

需要注意的是,給 video 标簽增加 webkit-playsinline 屬性,這個屬性是為了讓 video 視訊在 ios 的 uiwebview 裡面可以不全屏播放,預設 ios 會全屏播放視訊,需要給 uiwebview 設定 allowsInlineMediaPlayback=YES。 業界比較成熟的 videojs,可以根據不同平台選擇不同的政策,例如 ios 使用 video 标簽,pc 使用 flash 等。

簡根據以上步驟,筆者寫了一個 demo,從實作 ios 視訊錄制,采集,上傳,nginx 伺服器下發直播流,h5 頁面播放直播視訊者一整套流程,總結出以下幾點比較坑的地方:

1 在使用 AVCaptureSession 進行采集視訊時,需要實作 AVCaptureVideoDataOutputSampleBufferDelegate 協定,同時在- (void)captureOutput:(AVCaptureOutput )captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection )connection 捕獲到視訊流,要注意的是 didOutputSampleBuffer 這個方法不是 didDropSampleBuffer 方法,後者隻會觸發一次,當時開始寫的是 didDropSampleBuffer 方法,差了半天才發現方法調用錯了。

2 在使用 rtmp 推流時,rmtp 位址要以 rtmp:// 開頭,ip 位址要寫實際 ip 位址,不要寫成 localhost,同時要加上端口号,因為手機端上傳時是無法識别 localhos t的。

這裡後續會補充上一些坑點,有的需要貼代碼,這裡先列這麼多。

目前,騰訊雲,百度雲,阿裡雲都已經有了基于視訊直播的解決方案,從視訊錄制到視訊播放,推流,都有一系列的 sdk 可以使用,缺點就是需要收費,如果可以的話,自己實作一套也并不是難事哈。

demo位址:https://github.com/lvming6816077/LMVideoTest/

參考資料:http://www.nihaoshijie.com.cn/index.php/archives/615

更多精彩内容歡迎關注bugly的微信公衆賬号:

騰訊 Bugly是一款專為移動開發者打造的品質監控工具,幫助開發者快速,便捷的定位線上應用崩潰的情況以及解決方案。智能合并功能幫助開發同學把每天上報的數千條 Crash 根據根因合并分類,每日日報會列出影響使用者數最多的崩潰,精準定位功能幫助開發同學定位到出問題的代碼行,實時上報可以在釋出後快速的了解應用的品質情況,适配最新的 iOS, Android 官方作業系統,鵝廠的工程師都在使用,快來加入我們吧!

繼續閱讀