【騰訊Bugly乾貨分享】H5 視頻直播那些事

本文來自於騰訊bugly開發者社區,非經做者贊成,請勿轉載,原文地址:http://dev.qq.com/topic/57a42ee6503dfcb22007ede8html

Dev Club 是一個交流移動開發技術,結交朋友,擴展人脈的社羣,成員都是通過審覈的移動開發工程師。每週都會舉行嘉賓分享,話題討論等活動。前端

本期,咱們邀請了騰訊SNG Web前端開發工程師——呂鳴,爲你們分享**《H5 視頻直播那些事》**。android

如何加入 Dev Club?ios

移動端開發經驗 >= 2 年,微信掃描下方羣管理微信二維碼,備註姓名-公司(或產品) 申請加入。nginx

外部羣二維碼


分享內容簡介: 目前視頻直播,尤爲是移動端的視頻直播已經火到不行了,基本上各大互聯網公司都有了本身的直播產品,因此對於直播的一些基本知識和主要技術點也要有所瞭解,本次分享就向你們介紹一下其中的奧祕。git

內容大致框架:github

  1. 怎樣利用H5來播放直播視頻
  2. 怎樣錄製直播視頻
  3. 怎樣實時上傳直播視頻
  4. 直播中的用戶交互

分享人介紹:web

呂鳴 目前在騰訊SNG擔任手Q的web前端開發工做 博客:http://www.nihaoshijie.com.cn/後端


下面是本期分享內容整理瀏覽器


Hello, 你們好,我是呂鳴,目前是在騰訊 SNG 的即通應用部負責手Q的興趣部落 Web 前端開發工做。

針對目前比較火的視頻直播,我作了一些研究和探索,同時咱們的項目將會用到直播爲此打下技術基礎,下面就向你們分享一下直播的整個流程和一些技術點。

1、移動視頻直播發展

你們首先來看下面這張圖:

能夠看到,直播從 PC 到一直髮展到移動端,愈來愈多的直播類 App 上線,同時移動直播進入了史無前例的爆發階段,可是對於大多數移動直播來講,仍是要以 Native 客戶端實現爲主,可是 H5 在移動直播端也承載着不可替代的做用,例如 H5 有着傳播快,易發佈的優點,同時最爲關鍵的時 H5 一樣能夠播放直播視頻。

你們能夠看下面這張大概的實現圖

完整的直播能夠分爲如下幾塊:

  1. 視頻錄製端:通常是電腦上的音視頻輸入設備或者手機端的攝像頭或者麥克風,目前以移動端的手機視頻爲主。
  2. 視頻播放端:能夠是電腦上的播放器,手機端的 Native 播放器,還有就是 H5 的 video 標籤等,目前仍是已手機端的 Native 播放器爲主。
  3. 視頻服務器端:通常是一臺 nginx 服務器,用來接受視頻錄製端提供的視頻源,同時提供給視頻播放端流服務。

你們能夠看下大體的結構圖:

2、H5 錄製視頻:

對於H5視頻錄製,可使用強大的 webRTC (Web Real-Time Communication)是一個支持網頁瀏覽器進行實時語音對話或視頻對話的技術,缺點是隻在 PC 的 Chrome 上支持較好,移動端支持不太理想。

使用 webRTC 錄製視頻基本流程是:

  1. 調用 window.navigator.webkitGetUserMedia() 獲取用戶的PC攝像頭視頻數據。
  2. 將獲取到視頻流數據轉換成 window.webkitRTCPeerConnection (一種視頻流數據格式)。
  3. 利用 webscoket 將視頻流數據傳輸到服務端

因爲許多方法都要加上瀏覽器前綴,因此不少移動端的瀏覽器還不支持 webRTC,因此真正的視頻錄製仍是要靠客戶端(iOS,Android)來實現,效果會好一些。

3、H5 播放直播視頻:

對於視頻播放,可使用 HLS(HTTP Live Streaming)協議播放直播流,iOS和 Android 都自然支持這種協議,配置簡單,直接使用 video 標籤便可。

下面是簡單的代碼使用 video 播放直播視頻:

1.什麼是 HLS 協議:

簡單講就是把整個流分紅一個個小的,基於 HTTP 的文件來下載,每次只下載一些,前面提到了用於 H5 播放直播視頻時引入的一個 .m3u8 的文件,這個文件就是基於 HLS 協議,存放視頻流元數據的文件。

每個 .m3u8 文件,分別對應若干個 ts 文件,這些 ts 文件纔是真正存放視頻的數據,m3u8 文件只是存放了一些 ts 文件的配置信息和相關路徑,當視頻播放時,.m3u8 是動態改變的,video 標籤會解析這個文件,並找到對應的 ts 文件來播放,因此通常爲了加快速度,.m3u8 放在 Web 服務器上,ts 文件放在 CDN 上。

.m3u8 文件,其實就是以 UTF-8 編碼的 m3u 文件,這個文件自己不能播放,只是存放了播放信息的文本文件。

打開以後就是這個樣子:

下面這個是 ts 文件,就是存放視頻的文件:

2.HLS 的請求流程:

  1. HTTP 請求 m3u8 的 url。
  2. 服務端返回一個 m3u8 的播放列表,這個播放列表是實時更新的,通常一次給出5段數據的 url。
  3. 客戶端解析 m3u8 的播放列表,再按序請求每一段的 url,獲取 ts 數據流。

大概是這個流程:

3.HLS 直播延時:

咱們知道 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

可是 H5 直播視頻卻有一些不可替代的優點:

  1. 傳播性好,利於分享等操做。
  2. 能夠動態發佈,有利於實時迭代產品需求並迅速上線。
  3. 不用安裝 App,直接打開瀏覽器便可。

4、iOS 採集(錄製)音視頻數據OS

關於音視頻採集錄製,首先明確下面幾個概念:

  • 視頻編碼:所謂視頻編碼就是指經過特定的壓縮技術,將某個視頻格式的文件轉換成另外一種視頻格式文件的方式,咱們使用的 iPhone 錄製的視頻,必需要通過編碼,上傳,解碼,才能真正的在用戶端的播放器裏播放。
  • 編解碼標準:視頻流傳輸中最爲重要的編解碼標準有國際電聯的 H.26一、H.26三、H.264,其中 HLS 協議支持 H.264 格式的編碼。
  • 音頻編碼:同視頻編碼相似,將原始的音頻流按照必定的標準進行編碼,上傳,解碼,同時在播放器裏播放,固然音頻也有許多編碼標準,例如 PCM 編碼,WMA 編碼,AAC 編碼等等,這裏咱們 HLS 協議支持的音頻編碼方式是 AAC 編碼。

利用 iOS 上的攝像頭,進行音視頻的數據採集,主要分爲如下幾個步驟:

  1. 音視頻的採集,iOS 中,利用 AVCaptureSession 和 AVCaptureDevice 能夠採集到原始的音視頻數據流。
  2. 對視頻進行 H264 編碼,對音頻進行 AAC 編碼,在 iOS 中分別有已經封裝好的編碼庫來實現對音視頻的編碼。
  3. 對編碼後的音、視頻數據進行組裝封包;
  4. 創建 RTMP 鏈接並上推到服務端。

下面是具體的採集音視頻數據的流程:

1.關於 RTMP:

Real Time Messaging Protocol(簡稱 RTMP)是 Macromedia 開發的一套視頻直播協議,如今屬於 Adobe。和 HLS 同樣均可以應用於視頻直播,區別是 RTMP 基於 flash 沒法在 iOS 的瀏覽器裏播放,可是實時性比 HLS 要好。因此通常使用這種協議來上傳視頻流,也就是視頻流推送到服務器。

下面是 HLS 和 RTMP 的對比:

2.推流

所謂推流,就是將咱們已經編碼好的音視頻數據發往視頻流服務器中,在 iOS 代碼裏面通常經常使用的是使用 RTMP 推流,可使用第三方庫 librtmp-iOS 進行推流,librtmp 封裝了一些核心的 API 供使用者調用。例如推流 API 等等,配置服務器地址,便可將轉碼後的視頻流推往服務器。

那麼如何搭建一個推流服務器呢?

簡單的推流服務器搭建,因爲咱們上傳的視頻流都是基於 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/

下面是 nginx 的配置文件

5、直播中的用戶交互:

對於直播中的用戶交互大體能夠分爲:

  1. 送禮物
  2. 發表評論或者彈幕

對於送禮物,在 H5 端能夠利用 DOM 和 CSS3 實現送禮物邏輯和一些特殊的禮物動畫,實現技術難點不大。

對於彈幕來講,要稍微複雜一些,可能須要關注如下幾點:

  1. 彈幕實時性,能夠利用 webscoket 來實時發送和接收新的彈幕並渲染出來。
  2. 對於不支持 webscoket 的瀏覽器來講,只能降級爲長輪詢或者前端定時器發送請求來獲取實時彈幕。
  3. 彈幕渲染時的動畫和碰撞檢測(即彈幕不重疊)等等

6、總結

目前較爲成熟的直播產品,大體都是以 Server 端和 H5 和 Native(android,ios)搭配實現直播:

基本是下圖這個套路:

因此 H5 在整個直播中,仍是有着重要的地位的!

Demo 分享

最後,根據本次分享的內容,我這邊實現了一個 iOS 端錄製,推流,NGINX 接收流,同時分發的 HLS 直播流的一整套 Demo,感興趣的同窗能夠看下面這個連接:

https://github.com/lvming6816077/LMVideoTest

好了,本次分享先到這裏了,謝謝你們~

互動問答環節

Q1: Demo 包含 iOS 端的 RTMP 播放不?

答:Demo 裏面沒有 RTMP 的播放,Demo 主要是提供錄製,推流的。

Q2: 對於 H5 HLS 播放 卡頓問題,前端與 server 端,有什麼配置上的優化嗎?

答:server 端要作好分片策略,同時要將 ts 文件放在 CDN 上,前端這邊能夠儘可能作到 DNS 緩存等,因爲H5是使用的 video 標籤,因此要修改 video 的播放優化,仍是不那麼容易。

Q3: 在手機推流時的碼率是根據怎樣的策略作選擇的?不一樣機型和網絡下如何保持流暢?

答:能夠提供不一樣的視頻碼率來供用戶選擇,例如網速差的能夠選擇較爲低清晰度的碼率,網絡好的用戶能夠選擇更加清晰的碼率,同時作好視頻播放端的容錯和異常處理等等。

Q4: RTMP 比起 HTTP 他的優點主要是幾種在哪裏?

答:RTMP 是基於 TCP 的保持的是長鏈接,而 HTTP 是一次性的,每次都要三次握手,因此對於直播來講仍是 RTMP 好一些

Q5: 據我所知 nginx rtmp-module 好像性能不是很高.....爲何會採用這個來做爲後端服務?

答:這裏只是 Demo 用了這個 nginx rtmp-module,其實也可已選擇 SRS(simple-rtmp-server)都是能夠的哈

Q6: 移動端這邊怎麼進行編碼轉碼?用 ffmpeg 編譯時很麻煩

答:關於 iOS 這邊,其實不用關心轉碼問題,由於已經有了不少開源的庫提供給咱們了例如: x264 編碼:https://github.com/kewlbear/x264-ios faac 編碼:https://github.com/fflydev/faac-ios-build

Q7: 您介紹的都是 Native 播放和還有 H5 的 video 標籤播放, iOS 端有沒有考慮過整個用原生的 OC 或者 Swift 實現?

答:關於播放端,其實真正體驗好的仍是要用 native 來實現的,並且 native 實現能夠用 RTMP 來播放直播,延遲會好不少,H5 來播直播主要是考慮到易傳播性好。

Q8: 在用戶很是多的狀況下,或者網絡慢的狀況下,有什麼策略能夠保證質量?

答:能夠提供不一樣的視頻碼率來供用戶選擇,例如網速差的能夠選擇較爲低清晰度的碼率,網絡好的用戶能夠選擇更加清晰的碼率,同時作好視頻播放端的容錯和異常處理等等。

Q9: 請問直播這塊的測試中關注的幾個指標是什麼,有什麼比較好的測試方法呢?

答:主要就是:

  1. 首次打開的白屏時間
  2. 直播中的卡頓和緩衝
  3. 直播的延時

Q10: 您提供的 Demo 爲何不是 H5 的呢 iOS 推流和 nginx 服務器都有,能不能提供一個前面第二張葉子美女直播那個頁面的 Demo?

答:這個 Demo 你下載下拉運行的話,根據配置就可直接本身實現一個利用 H5 直播的頁面,很簡單,就像使用 video 標籤同樣,其餘的樣式你能夠本身定製的。

Q11: HLS 的延時有沒有比較好的方法解決?

答:HLS 確實是會有延遲,相對比較優的策略是調整好分片策略,在保證性能的狀況下,和延遲達到平衡。

Q12: 若是加入視頻電話功能,上面的結構須要做什麼改變?視頻電話的目的大概是:直播能夠選擇某一觀衆或者多個觀衆視頻對話

答:視頻電話,也就是說做爲視頻錄製端的同時也做爲視頻播放端,因此實現實時電話簡單就是:我在直播的同時觀看別人的直播視頻,別人在直播的同時觀看個人直播視頻,能夠這樣理解,上面的結構複製一份對調便可。

Q13: 如何實現濾鏡功能?

答:通常是在視頻錄製以後,在轉碼前給視頻數據增長濾鏡功能,在 iOS 裏可使用一些濾鏡庫等等實現濾鏡功能

Q14: 在 App 端若是不利用 H5 能實現直播嗎?

答:能夠啊,app 有更加豐富的播放接口,和開源播放器能夠實現直播的。

Q15: 既然 HLS 有較高的延遲 爲何蘋果推薦的的方式倒是 HLS?

答:並非說蘋果主要推薦使用 HLS,對於 H5 來講目前只有這一種比較好的方式來播放直播視頻,因此仍是很期待蘋果能對延遲問題作一些改進的。

Q16: 同濾鏡問題,音頻變聲是如何實現的?

答:一樣是能夠在對音頻轉碼前操做。

Q17: 若是針對網絡較差的觀看用戶,是須要直播推流到服務器後作多份不一樣分辨率的拷貝,以適應不一樣網絡的用戶觀看?若是是這樣的話,對延遲會不會影響很大? 畢竟編解碼也是須要時間的.

答:這個其實自己就應該作的,對於網絡差的用戶,徹底能夠提供給他們較低碼率的直播流來減小卡頓問題,延遲問題的話仍是要根據具體使用哪一種協議來定。

Q18: 推流目前大部分都是第三方在作,難度點在哪?而後目前業內比較成熟的主要哪些?

答:難點主要是服務器端的性能壓力和分發直播流的效率,業界都已經有了較成熟的方案,例如騰訊雲的直播。

點此查看 Dev Club 往期分享彙總

更多精彩內容歡迎關注bugly的微信公衆帳號:

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

相關文章
相關標籤/搜索