iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 27
1
Modern Web

深入現代前端開發系列 第 27

Day27 開發直播應用要知道的事

前言

今天來談談前端實作串流這件事。

在早期,如果想要做影片相關的應用的話,只能用像是 flash 之類的方式嵌入,不像現在那麼奢侈,不過自從 <video> tag 出現後,我們不需要再使用 flash 就可以播放影片了。

最近直播應用一個接著一個,如果要讓體驗好一些的話,開發上就要注意許多細節。不過今天可能沒辦法一一介紹,我們會從最基礎串流協定與前端上常用開發方式來做介紹。

編碼與常見影片格式

首先我們來了解一下編碼以及影片格式。對於電腦來說,因為內部只看得動二進制的位元碼,所以需要一個編碼方式來將影像轉換成二進位的文件,而為了讓各個系統通用,所以目前有幾個主流的編碼方式:H.264 與 VP8。

對於影片來說,如果我們將資料原封不動地傳上去,絕對是大到不行,在傳輸上不太可能達到即時,效益也不大,因此在編碼的時候也會將影片做適當的壓縮。

目前主流的編碼方式有:

  • H.264:目前主流的影片編碼方式,可以很有效率地壓縮影片大小,目前許多服務都使用此編碼方式。
  • VP8:由 Google 釋出,希望透過 HTML 和開放的 VP8 編碼來取代 H.264。

這是目前 video tag 在各大瀏覽器的支援格式情形:

Browser MP4 WebM Ogg
Internet Explorer YES NO NO
Chrome YES YES YES
Firefox YES YES YES
Safari YES NO NO
Opera YES (from Opera 25) YES YES

咦?阿怎麼都沒看到剛剛的編碼方式,接下來就來淺談影片格式。

影片格式

上述我們簡單介紹了主流的影片編碼方式,但瀏覽器或解碼方要怎麼知道該怎麼解碼呢?例如我該如何知道這一坨二進制編碼是 H.264 還是 VP8?總有有資訊來紀錄吧?要怎麼紀錄?資料又該怎麼存放,就是容器在做的事情。

一個影片的容器可以包涵:標頭(記錄編碼資訊等)、聲音編碼與影像編碼。有了容器包裝後我們才能順利解析影片與聲音,也知道要採用哪個方式編碼。而上述的 MP4、WebM、Ogg 就屬於一種封裝。

例如 mp4 這個最常見的影片格式,在影片編碼上就可以選擇 H.26x、VP9 等等,而聲音編碼則可以選擇(AAC、ALAC 等)。

而 WebM 則採用了 VP9 為影片編碼與 Vorbis、Opus 當作聲音編碼當作封裝。

直播串流協定

如果要做直播串流應用,有幾個蠻重要的傳輸協定:

  • RTP(Real Time Protocol):用來規範多媒體的格式如何傳輸
  • RTMP:由 Adobe 所規範的協定,將資料切成 message chunk 來傳輸
  • HLS(Http Live Streaming):由 apple 開發,為了對抗 flash player 而提出的規範。
  • HTTP-FLV:如果在網頁要做到觀看直播通常會選擇 http-flv,原因在於 http 協定與低延遲,而且也可以透過 http-chunked 的方式來做分段。

比較要特別注意的是在 hls 當中會有兩份檔案:

  • m3u8:索引檔來表示影片與聲音是如何切分的
  • .ts:實際的影片與聲音資料

因此在解碼的時候會先請求 m3u8 檔,再依照目前的時間來拿曲對應的 .ts 檔。但也因為需要先有索引才能拿檔案,代表延遲相對會高一些,如果是要求即時性的話,通常不會用這種協定,但不要求那麼即時的話,用 HLS 也算是不錯的選擇。

Media Source Extension(MSE)

前面我們有提到各種傳輸協定,不過如果要在網頁上套用的話,目前只有上述提到的 mp4、ogg、webM 可以使用,對於一個比較進階的應用來說不太足夠,例如當時要做串流,還是得仰賴 flash 的幫助。

Media Source Extension 是 JavaScript 為了加強多媒體檔案的控制而推出 API。在以前我們或許只能用 video tag 然後塞個 URL,加幾個 event listener 做控制,然後就這樣了。

搭配 MSE 的 API,我們可以有相對細膩的操作,例如透過 fetch 拿取影像資料(ArrayBuffer 等),送給 MediaSource,再把資料餵給 video。

flv.jshls.js

如果是要做影片相關應用的話,這兩個函式庫應該是大宗,flv.js 使用 Media Source Extension 來支援 flv 格式;hls.js 則是可以幫你處理 hls 在瀏覽器端播放要處理的麻煩事。目前主流的函式庫大概就 flv.js 與 hls.js 了,差別在於支援的編碼格式不同。

WebRTC

雖然做直播應用的話不太可能會用 WebRTC,但實作像是小型會議室的話,webRTC 還是蠻常見的。WebRTC 想要解決的事是不透過 server/client 這種架構,而是讓兩個 client 之間直接溝通,不透過任何 server(但還是要有個 signaling server)。

不過在實作上還真的是挺麻煩的,但因為瀏覽器有支援 API,如果是想要練習小型會議的應用開發的話,可以考慮使用 WebRTC。

小結

今天介紹了前端在做直播的時候要理解的概念與常見的函式庫介紹。這些基本的東西先了解才不會哪天要做網頁版的時候心浮氣躁,或是出現像是後端使用 HLS 協定,卻在前端用 flv.js 串接結果發現怎麼串都串不好的類似窘境發生。

如果真正想做直播應用,最好的方法還是進入一間大公司,如果只是小專案,自己開個 server 玩玩還好,但如果要承受大流量的話(例如 200, 300 人就好),不燒錢是絕對玩不起來的,光是 CDN 的費用就貴死人。

另外除了串接影片之外,在做直播應用的時候也有許多要考慮的地方,例如:

  • 聊天室的實作
  • 禮物系統
  • 美膚美肌等功能(通常是後端先過濾好才送來前端,但如果在前端也能做一些效果也挺酷的)
  • 加解密
  • 字幕與影片同步

現在直播服務越來越多,參考各大網站的實作也是很好的學習機會。

在瀏覽器雖然不像 App 端那樣有那麼豐富的 API 可供使用,但透過 WebGL 或是 AudioNode 之類的 API,或許在直播的應用上可以變得更有趣也說不定,至於 WebGL 與 AudioNode,就看有沒有機會再來介紹了。


上一篇
Day26 前端可以不只是前端
下一篇
Day26 前端中的效能優化
系列文
深入現代前端開發32

尚未有邦友留言

立即登入留言