串流媒體協定多種多樣,音視訊編碼格式更是繁多,要想在瀏覽器中正常瀏覽並非不容易。除開 WebRTC 這種瀏覽器已經支援的協定,HLS、FLV、RTSP、RTMP、DASH 等協定都需要預處理,不過流程大致都是:
目前市面上也有一些前端解碼的方案,如藉助 WASM
的高效能呼叫 c 解碼庫,或者直接使用瀏覽器的 WebCodecs API
進行編解碼......但都存在侷限性,WebCodecs
仍是實驗性功能;而 WASM
方案雖然突破瀏覽器沙盒限制(能播放瀏覽器不支援的編碼格式如H265等),但解碼和瀏覽器原始解碼之間仍有差距,並且由於只能走軟解導致多路效能也吃不消。所以,市面上更多的是採用另一種方式,解協定+封裝+這篇文章的主角 Media Source Extensions(以下簡稱MSE)。
HTML5 規範允許我們直接在網頁中嵌入視訊,
<video src="demo.mp4"></video>
但 src 指定的資源地址必須是一個完整的媒體檔案,如何在 Web 做到流式的媒體資源播放?MSE
提供了這樣的可能性,先看下 MDN 對它對描述:
媒體源擴充套件 API(MSE) 提供了實現無外掛且基於 Web 的串流媒體的功能。使用 MSE,媒體串流能夠通過 建立,並且能通過使用<audio>
和<video>
元素進行播放。
正如上面所說,MSE
讓我們可以通過 JS 建立媒體資源,使用起來也十分方便:
const mediaSource = new MediaSource();
const video = document.querySelector('video');
video.src = URL.createObjectURL(mediaSource);
媒體資源物件建立完畢,接下來就是餵給它視訊資料(片段),程式碼看上去就像是:
mediaSource.addEventListener('sourceopen', () => {
const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
const sourceBuffer = mediaSource.addSourceBuffer(mime);
const data = new ArrayBuffer([...]); // 視訊資料
sourceBuffer.appendBuffer(data);
});
此時,視訊就可以正常播放了。要想做到流式播放,只需要不停的呼叫 appendBuffer
喂音視訊資料就行了......但不禁有疑問, 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
這段字串什麼意思?音視訊資料又要從哪來的?