今天來談談前端實作串流這件事。
在早期,如果想要做影片相關的應用的話,只能用像是 flash 之類的方式嵌入,不像現在那麼奢侈,不過自從 <video>
tag 出現後,我們不需要再使用 flash 就可以播放影片了。
最近直播應用一個接著一個,如果要讓體驗好一些的話,開發上就要注意許多細節。不過今天可能沒辦法一一介紹,我們會從最基礎串流協定與前端上常用開發方式來做介紹。
首先我們來了解一下編碼以及影片格式。對於電腦來說,因為內部只看得動二進制的位元碼,所以需要一個編碼方式來將影像轉換成二進位的文件,而為了讓各個系統通用,所以目前有幾個主流的編碼方式:H.264 與 VP8。
對於影片來說,如果我們將資料原封不動地傳上去,絕對是大到不行,在傳輸上不太可能達到即時,效益也不大,因此在編碼的時候也會將影片做適當的壓縮。
目前主流的編碼方式有:
這是目前 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 當作聲音編碼當作封裝。
如果要做直播串流應用,有幾個蠻重要的傳輸協定:
比較要特別注意的是在 hls 當中會有兩份檔案:
因此在解碼的時候會先請求 m3u8 檔,再依照目前的時間來拿曲對應的 .ts 檔。但也因為需要先有索引才能拿檔案,代表延遲相對會高一些,如果是要求即時性的話,通常不會用這種協定,但不要求那麼即時的話,用 HLS 也算是不錯的選擇。
前面我們有提到各種傳輸協定,不過如果要在網頁上套用的話,目前只有上述提到的 mp4、ogg、webM 可以使用,對於一個比較進階的應用來說不太足夠,例如當時要做串流,還是得仰賴 flash 的幫助。
Media Source Extension 是 JavaScript 為了加強多媒體檔案的控制而推出 API。在以前我們或許只能用 video tag 然後塞個 URL,加幾個 event listener 做控制,然後就這樣了。
搭配 MSE 的 API,我們可以有相對細膩的操作,例如透過 fetch 拿取影像資料(ArrayBuffer 等),送給 MediaSource,再把資料餵給 video。
如果是要做影片相關應用的話,這兩個函式庫應該是大宗,flv.js 使用 Media Source Extension 來支援 flv 格式;hls.js 則是可以幫你處理 hls 在瀏覽器端播放要處理的麻煩事。目前主流的函式庫大概就 flv.js 與 hls.js 了,差別在於支援的編碼格式不同。
雖然做直播應用的話不太可能會用 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,就看有沒有機會再來介紹了。