4 HTML躬行記——Web音視頻基礎( 二 )

  • 視覺冗余,相對于人眼的視覺特性而言 , 人類視覺系統對圖像的敏感性是非均勻和非線性的,并不是所有變化都能被觀察到 。
  • 結構冗余,在圖像的紋理區,以及圖像的像素值存在明顯的分布模式 。
  • 知識冗余,對許多圖像的理解與某些先驗知識有相當大的相關性 , 這類規律可由先驗知識和背景知識得到 。
  • 視頻播放器播放本地視頻文件或互聯網上的流媒體文件大概需要解協議、解封裝、解碼、音視頻同步、渲染等幾個步驟,如下圖所示 。
    4 HTML躬行記——Web音視頻基礎

    文章插圖
    二、Web中的音視頻HTML5 標準推出后,提供了播放視頻的 video 元素 , 以及播放音頻的 audio 元素 。
    為了能更精準的控制時間、容器格式轉換、媒體質量和內存釋放等復雜的媒體處理,W3C 推出了 MSE(Media Source Extensions)媒體源擴展標準 。
    若要訪問瀏覽器中已有的編解碼器,可以試試 WebCodecs,它可以訪問原始視頻幀、音頻數據塊、圖像解碼器、音頻和視頻編碼器和解碼器 。
    在瀏覽器中主流的視頻編碼格式是 H.264/MPEG-4,不過需要支付專利費 。
    4 HTML躬行記——Web音視頻基礎

    文章插圖
    而 Google 推出的開源編碼格式:VP8,除了 IE 之外,其他瀏覽器的高版本都能支持 。
    4 HTML躬行記——Web音視頻基礎

    文章插圖
    最新的 H.265 和 VP9 在瀏覽器的兼容性上都不理想,有些第三方庫會自己寫一個 H.265 的解碼器腳本,然后來播放視頻 。
    1)播放器
    直播使用 video 元素播放視頻很多功能都無法滿足,因此很多時候都會引入一個播放器,例如 video.js、react-player 等 。
    這些播放器都能支持多種格式的視頻,例如 flv、m3u8、mp4 等;并且有完整的控制鍵,例如音量、縮放、倍速等,覆蓋移動和 PC 兩個平臺,以及可引入插件等 。
    下圖是一種播放器的整體架構圖,來源于《Web端H.265播放器研發解密》 。
    4 HTML躬行記——Web音視頻基礎

    文章插圖
    除了常規的使用 video 元素播放視頻之外 , 還可以用 canvas 播放 , 具體實現可以參考 JSMpeg 。
    2)MSE
    在 MSE 規范中,提供了 MediaSource 對象,它可以附著在 HTMLMediaElement 中,即 video 元素的 src 的屬性值可以是它 。
    一個 MediaSource 包含一個或多個 SourceBuffer 實例(下圖來源于W3C官網),SourceBuffer 表示通過 MediaSource 傳遞到 HTMLMediaElement 并播放的媒體片段 。
    4 HTML躬行記——Web音視頻基礎

    文章插圖
    下面是一個使用 MSE 的完整示例,修改了 MDN 中的代碼首先是聲明視頻路徑和 MIME 參數,注意,要正確指定 codecs 參數,否則視頻無法播放 。
    const video = document.getElementById('video');const assetURL = 'demo.mp4';const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';然后實例化 MediaSource 類,并將其與 video 元素關聯,注冊 sourceopen 事件 。
    const mediaSource = new MediaSource();video.src = https://www.huyubaike.com/biancheng/URL.createObjectURL(mediaSource);mediaSource.addEventListener('sourceopen', sourceOpen);最后實現 sourceOpen 函數,通過 fetch() 請求視頻資源,將讀取到的 ArrayBuffer 數據附加到 sourceBuffer 中 。
    function sourceOpen(e) {URL.revokeObjectURL(video.src);const mediaSource = e.target;// 創建指定 MIME 類型的 SourceBuffer 并添加到 MediaSource 的 SourceBuffers 列表const sourceBuffer = mediaSource.addSourceBuffer(mime);// 請求資源fetch(assetURL).then(function(response) {return response.arrayBuffer();// 轉換成 ArrayBuffer}).then(function(buf) {sourceBuffer.addEventListener('updateend', function() {if (!sourceBuffer.updating && mediaSource.readyState === 'open') {mediaSource.endOfStream();// 視頻流傳輸完成后關閉流video.play();}});sourceBuffer.appendBuffer(buf); // 添加已轉換成 ArrayBuffer 的視頻流數據});}為 sourceBuffer 注冊 updateend 事件 , 并在視頻流傳輸完成后關閉流 。
    注意,要想看到視頻的播放 , 不能直接靜態 HTML 文件,需要將文件附加到 HTTP 服務器中 。
    本文借助 Node.js , 搭建了一個極簡的 HTTP 服務器,當然也可以將 HTML 文件掛載到 Nginx 或 IIS 服務器中 。
    const http = require('http');const fs = require('fs');// HTTP服務器const server = http.createServer((req, res) => {// 實例化 URL 類const url = new URL(req.url, 'http://localhost:1000');const { pathname } = url;// 路由if(pathname === '/') {res.writeHead(200, { 'Content-Type': 'text/html' });res.end(fs.readFileSync('./index.html'));}else if(pathname === '/demo.mp4') {res.writeHead(200, { 'Content-Type': 'video/mp4' });res.end(fs.readFileSync('./demo.mp4'));}else if(pathname === '/client.js') {res.writeHead(200, { 'Content-Type': 'application/javascript' });res.end(fs.readFileSync('./client.js'));}});server.listen(1000);

    推薦閱讀