音訊和影片交付

我們可以在網頁上以多種方式交付音訊和影片,從“靜態”媒體檔案到自適應直播流。本文旨在作為探索基於網頁的媒體的各種交付機制以及與流行瀏覽器的相容性的起點。

音訊和影片元素

無論我們處理的是預先錄製的音訊檔案還是直播流,使它們透過瀏覽器的 <audio><video> 元素可用的機制基本相同。目前,為了支援所有瀏覽器,我們需要指定兩種格式,儘管隨著 MP3 和 MP4 格式在 Firefox 和 Opera 中的採用,這種情況正在迅速改變。您可以在 網頁媒體型別和格式指南 中找到相容性資訊。

為了交付影片和音訊,通常的通用工作流程如下

  1. 透過特徵檢測檢查瀏覽器支援哪些格式(如上所述,通常是兩種)。
  2. 如果瀏覽器不支援任何提供的格式的本機播放,則顯示靜止影像或使用備用技術來顯示影片。
  3. 確定您希望如何播放/例項化媒體(例如 <video> 元素,或者可能是 document.createElement('video')?)。
  4. 將媒體檔案傳遞到播放器。

HTML 音訊

html
<audio controls preload="auto">
  <source src="audiofile.mp3" type="audio/mpeg" />

  <!-- fallback for browsers that don't support mp3 -->
  <source src="audiofile.ogg" type="audio/ogg" />

  <!-- fallback for browsers that don't support audio tag -->
  <a href="audiofile.mp3">download audio</a>
</audio>

上面的程式碼將建立一個音訊播放器,該播放器將嘗試預載入儘可能多的音訊以實現流暢的播放。

注意:preload 屬性可能會被一些移動瀏覽器忽略。

有關更多資訊,請參閱 跨瀏覽器音訊基礎知識(HTML 音訊詳解)

HTML 影片

html
<video
  controls
  width="640"
  height="480"
  poster="initialimage.png"
  autoplay
  muted>
  <source src="videofile.mp4" type="video/mp4" />

  <!-- fallback for browsers that don't support mp4 -->
  <source src="videofile.webm" type="video/webm" />

  <!-- specifying subtitle files -->
  <track src="subtitles_en.vtt" kind="subtitles" srclang="en" label="English" />
  <track
    src="subtitles_no.vtt"
    kind="subtitles"
    srclang="no"
    label="Norwegian" />

  <!-- fallback for browsers that don't support video tag -->
  <a href="videofile.mp4">download video</a>
</video>

上面的程式碼建立了一個 640x480 畫素的影片播放器,在播放影片之前顯示一張海報影像。我們指示影片自動播放,但預設情況下靜音。

注意:autoplay 屬性可能會被一些移動瀏覽器忽略。此外,自動播放功能在被誤用時可能存在爭議。強烈建議您閱讀 媒體和網頁音訊 API 的自動播放指南 以瞭解如何明智地使用自動播放。

有關更多資訊,請參閱 <video> 元素建立跨瀏覽器影片播放器

JavaScript 音訊

js
const myAudio = document.createElement("audio");

if (myAudio.canPlayType("audio/mpeg")) {
  myAudio.setAttribute("src", "audiofile.mp3");
} else if (myAudio.canPlayType("audio/ogg")) {
  myAudio.setAttribute("src", "audiofile.ogg");
}

myAudio.currentTime = 5;
myAudio.play();

我們根據瀏覽器支援的音訊檔案型別設定音訊源,然後將播放頭設定在 5 秒處並嘗試播放它。

注意:除非由使用者發起的事件發出,否則大多數瀏覽器將忽略播放。

還可以使用 <audio> 元素向其提供一個 base64 編碼的 WAV 檔案,從而允許動態生成音訊

html
<audio id="player" src="data:audio/x-wav;base64,UklGRvC…"></audio>

Speak.js 使用這種技術。

JavaScript 影片

js
const myVideo = document.createElement("video");

if (myVideo.canPlayType("video/mp4")) {
  myVideo.setAttribute("src", "videofile.mp4");
} else if (myVideo.canPlayType("video/webm")) {
  myVideo.setAttribute("src", "videofile.webm");
}

myVideo.width = 480;
myVideo.height = 320;

我們根據瀏覽器支援的影片檔案型別設定影片源,然後設定影片的寬度和高度。

網頁音訊 API

在此示例中,我們使用 fetch() API 檢索 MP3 檔案,將其載入到源中,然後播放它。

js
let audioCtx;
let buffer;
let source;

async function loadAudio() {
  try {
    // Load an audio file
    const response = await fetch("viper.mp3");
    // Decode it
    buffer = await audioCtx.decodeAudioData(await response.arrayBuffer());
  } catch (err) {
    console.error(`Unable to fetch the audio file. Error: ${err.message}`);
  }
}

const play = document.getElementById("play");
play.addEventListener("click", async () => {
  if (!audioCtx) {
    audioCtx = new AudioContext();
    await loadAudio();
  }
  source = audioCtx.createBufferSource();
  source.buffer = buffer;
  source.connect(audioCtx.destination);
  source.start();
  play.disabled = true;
});

您可以 線上執行完整示例,或 檢視原始碼

使用網頁音訊 API 中瞭解有關網頁音訊 API 基礎知識的更多資訊。

getUserMedia / 流 API

還可以使用 getUserMedia 和流 API 從網路攝像頭和/或麥克風獲取直播流。這構成了更廣泛的技術(稱為 WebRTC(網頁即時通訊))的一部分,並且與最新版本的 Chrome、Firefox 和 Opera 相容。

要從您的網路攝像頭獲取流,首先設定一個 <video> 元素

html
<video id="webcam" width="480" height="360"></video>

接下來,如果受支援,將網路攝像頭源連線到影片元素

js
if (navigator.mediaDevices) {
  navigator.mediaDevices
    .getUserMedia({ video: true, audio: false })
    .then(function onSuccess(stream) {
      const video = document.getElementById("webcam");
      video.autoplay = true;
      video.srcObject = stream;
    })
    .catch(function onError() {
      alert(
        "There has been a problem retrieving the streams - are you running on file:/// or did you disallow access?",
      );
    });
} else {
  alert("getUserMedia is not supported in this browser.");
}

要了解更多資訊,請閱讀我們的 MediaDevices.getUserMedia 頁面。

Mediastream 錄製

正在推出新的標準,允許您的瀏覽器使用 getUserMedia 從麥克風或攝像頭獲取媒體,並使用新的 MediaStream 錄製 API 即時錄製媒體。您獲取從 getUserMedia 收到的流,將其傳遞給 MediaRecorder 物件,獲取結果輸出,然後將其傳遞到音訊或影片源*。

主要機制概述如下

js
navigator.mediaDevices
  .getUserMedia({ audio: true })
  .then(function onSuccess(stream) {
    const recorder = new MediaRecorder(stream);

    const data = [];
    recorder.ondataavailable = (e) => {
      data.push(e.data);
    };
    recorder.start();
    recorder.onerror = (e) => {
      throw e.error || new Error(e.name); // e.name is FF non-spec
    };
    recorder.onstop = (e) => {
      const audio = document.createElement("audio");
      audio.src = window.URL.createObjectURL(new Blob(data));
    };
    setTimeout(() => {
      rec.stop();
    }, 5000);
  })
  .catch(function onError(error) {
    console.log(error.message);
  });

有關更多詳細資訊,請參閱 MediaStream 錄製 API

媒體源擴充套件 (MSE)

媒體源擴充套件 是 W3C 的一個工作草案,計劃擴充套件 HTMLMediaElement 以允許 JavaScript 生成用於播放的媒體流。允許 JavaScript 生成流有助於實現各種用例,例如自適應流和時間推移直播流。

加密媒體擴充套件 (EME)

加密媒體擴充套件 是 W3C 的一項提案,用於擴充套件 HTMLMediaElement,提供用於控制受保護內容播放的 API。

該 API 支援從簡單的明文金鑰解密到高價值影片(在適當的使用者代理實現的情況下)的各種用例。許可證/金鑰交換由應用程式控制,有助於開發支援各種內容解密和保護技術的強大播放應用程式。

EME 的主要用途之一是允許瀏覽器實現 DRM (數字版權管理),這有助於防止基於網頁的內容(尤其是影片)被複制。

自適應流

正在推出新的格式和協議來簡化自適應流。自適應流媒體意味著流的頻寬和通常的質量可以根據使用者的可用頻寬即時改變。自適應流通常與直播流結合使用,在直播流中,音訊或影片的平滑交付至關重要。

用於自適應流的主要格式是 HLSMPEG-DASH。MSE 是專為 DASH 而設計的。MSE 根據 ISOBMFFM2TS(DASH 都支援,後者在 HLS 中受支援)定義位元組流。一般而言,如果您對標準感興趣,正在尋求靈活性,或者希望支援大多數現代瀏覽器,您可能更適合使用 DASH。

注意:目前 Safari 不支援 DASH,儘管 dash.js 將在計劃與 OSX Yosemite 一起釋出的更新版本的 Safari 中執行。

DASH 還提供了一些配置檔案,包括簡單的按需配置檔案,這些配置檔案不需要預處理和拆分媒體檔案。還有一些基於雲的服務可以將您的媒體轉換為 HLS 和 DASH。

有關更多資訊,請參閱 直播網頁音訊和影片

自定義您的媒體播放器

您可能希望您的音訊或影片播放器在所有瀏覽器中都具有統一的外觀,或者只是希望調整它以匹配您的網站。實現此目的的通用技術是省略 controls 屬性,以便不顯示預設的瀏覽器控制元件,使用 HTML 和 CSS 建立自定義控制元件,然後使用 JavaScript 將控制元件連結到音訊/影片 API。

如果您需要其他功能,可以新增目前預設播放器中不存在的功能,例如播放速度、質量流切換,甚至音訊頻譜。您還可以選擇如何使播放器響應——例如,您可以在特定條件下刪除進度條。

您可以檢測點選、觸控和/或鍵盤事件來觸發播放、暫停和拖動等操作。為了使用者方便和可訪問性,記住鍵盤控制通常很重要。

一個簡單的例子 - 首先在 HTML 中設定您的音訊和自定義控制元件

html
<audio
  id="my-audio"
  src="http://jPlayer.org/audio/mp3/Miaow-01-Tempered-song.mp3"></audio>
<button id="my-control">play</button>

新增一些 JavaScript 程式碼來檢測播放和暫停音訊的事件

js
window.onload = () => {
  const myAudio = document.getElementById("my-audio");
  const myControl = document.getElementById("my-control");

  function switchState() {
    if (myAudio.paused) {
      myAudio.play();
      myControl.textContent = "pause";
    } else {
      myAudio.pause();
      myControl.textContent = "play";
    }
  }

  function checkKey(e) {
    if (e.code === "Space") {
      // space bar
      switchState();
    }
  }

  myControl.addEventListener(
    "click",
    () => {
      switchState();
    },
    false,
  );

  window.addEventListener("keypress", checkKey, false);
};

您可以 在這裡試用這個例子。有關更多資訊,請參閱 建立您自己的自定義音訊播放器

音訊/影片的其他提示

停止媒體下載

雖然停止媒體播放與呼叫元素的 pause() 方法一樣簡單,但瀏覽器會繼續下載媒體,直到媒體元素透過垃圾回收被處理掉。

這裡有一個立即停止下載的技巧

js
const mediaElement = document.querySelector("#myMediaElementID");
mediaElement.removeAttribute("src");
mediaElement.load();

透過刪除媒體元素的 src 屬性並呼叫 load() 方法,您可以釋放與影片相關的資源,從而停止網路下載。您必須在刪除屬性後呼叫 load(),因為僅僅刪除 src 屬性不會呼叫載入演算法。如果 <video> 元素還有 <source> 元素子節點,則在呼叫 load() 之前也應該刪除這些子節點。

請注意,將 src 屬性設定為一個空字串實際上會導致瀏覽器將其視為將影片源設定為相對路徑。這會導致瀏覽器嘗試下載另一個不太可能是有效影片的內容。

在媒體中搜索

媒體元素支援將當前播放位置移動到媒體內容中的特定點。這是透過設定元素的 currentTime 屬性的值來完成的;有關元素屬性的更多詳細資訊,請參閱 HTMLMediaElement。將值設定為您想要繼續播放的時間(以秒為單位)。

您可以使用元素的 seekable 屬性來確定當前可用於搜尋的媒體範圍。這將返回一個 TimeRanges 物件,列出您可以搜尋到的時間範圍。

js
const mediaElement = document.querySelector("#mediaElementID");
mediaElement.seekable.start(0); // Returns the starting time (in seconds)
mediaElement.seekable.end(0); // Returns the ending time (in seconds)
mediaElement.currentTime = 122; // Seek to 122 seconds
mediaElement.played.end(0); // Returns the number of seconds the browser has played

指定播放範圍

在為 <audio><video> 元素指定媒體的 URI 時,您可以選擇性地包含其他資訊來指定要播放的媒體部分。為此,請附加一個井號(“#”),後面跟著媒體片段描述。

時間範圍使用以下語法指定

#t=[starttime][,endtime]

時間可以指定為秒數(作為浮點值),也可以指定為以冒號分隔的小時/分鐘/秒時間(例如 2:05:01 代表 2 小時 5 分鐘 1 秒)。

一些例子

http://example.com/video.ogv#t=10,20

指定影片應該播放 10 秒到 20 秒的範圍。

http://example.com/video.ogv#t=,10.5

指定影片應該從開始播放到 10.5 秒。

http://example.com/video.ogv#t=,02:00:00

指定影片應該從開始播放到 2 個小時。

http://example.com/video.ogv#t=60

指定影片應該從 60 秒開始播放,並播放到影片結束。

錯誤處理

錯誤將傳遞到與導致錯誤的源相對應的子 <source> 元素。

這使您可以檢測哪些源載入失敗,這可能很有用。考慮以下 HTML

html
<video>
<source id="mp4_src"
  src="video.mp4"
  type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
</source>
<source id="3gp_src"
  src="video.3gp"
  type='video/3gpp; codecs="mp4v.20.8, samr"'>
</source>
<source id="ogg_src"
  src="video.ogv"
  type='video/ogv; codecs="theora, vorbis"'>
</source>
</video>

由於 Firefox 在某些平臺上不支援 MP4 和 3GP(由於其專利受限的性質),因此具有 ID“mp4_src”和“3gp_src”的 <source> 元素將在載入 Ogg 資源之前收到 error 事件。源按照它們出現的順序進行嘗試,一旦一個源成功載入,其餘的源將不再嘗試。

檢查瀏覽器是否支援提供的格式

在您的音訊和影片元素中使用以下經過驗證的源來檢查支援情況。

如果這些無法播放,那麼您正在測試的瀏覽器不支援給定的格式。請考慮使用其他格式或使用備用方案。

如果這些工作但您提供的檔案不起作用,則可能存在兩個問題

1. 媒體伺服器沒有使用檔案傳遞正確的 MIME 型別

雖然這通常得到支援,但您可能需要在媒體伺服器的 .htaccess 檔案中新增以下內容。

# AddType TYPE/SUBTYPE EXTENSION

AddType audio/mpeg mp3
AddType audio/mp4 m4a
AddType audio/ogg ogg
AddType audio/ogg oga

AddType video/mp4 mp4
AddType video/mp4 m4v
AddType video/ogg ogv
AddType video/webm webm
AddType video/webm webmv

2. 您的檔案編碼不正確

您的檔案可能編碼不正確 - 請嘗試使用以下工具之一進行編碼,這些工具已被證明非常可靠

檢測何時沒有源載入

要檢測所有子 <source> 元素是否載入失敗,請檢查媒體元素的 networkState 屬性的值。如果這是 HTMLMediaElement.NETWORK_NO_SOURCE,那麼您就知道所有源都載入失敗了。

如果您在那時添加了另一個源(透過將新的 <source> 元素作為媒體元素的子元素插入),Gecko 將嘗試載入指定的資源。

當無法解碼任何源時顯示備用內容

另一種方法是在最後一個源元素上新增錯誤處理程式,以便在當前瀏覽器中無法解碼任何源時顯示影片的備用內容。然後,您可以將影片替換為其備用內容

html
<video controls>
  <source src="dynamicsearch.mp4" type="video/mp4"></source>
  <a href="dynamicsearch.mp4">
    <img src="dynamicsearch.jpg" alt="Dynamic app search in Firefox OS">
  </a>
  <p>Click image to play a video demo of dynamic app search</p>
</video>
js
const v = document.querySelector("video");
const sources = v.querySelectorAll("source");
const lastsource = sources[sources.length - 1];
lastsource.addEventListener(
  "error",
  (ev) => {
    const d = document.createElement("div");
    d.innerHTML = v.innerHTML;
    v.parentNode.replaceChild(d, v);
  },
  false,
);

音訊/影片 JavaScript 庫

存在許多音訊和影片 JavaScript 庫。最流行的庫允許您在所有瀏覽器中選擇一致的播放器設計,併為不支援音訊和影片的瀏覽器提供備用方案。備用方案歷史上使用現在已過時的外掛(如 Adobe Flash 或 Microsoft Silverlight 外掛)在不支援的瀏覽器中提供媒體播放器,儘管這些外掛在現代計算機上不再受支援。其他功能(如字幕的 <track> 元素)也可以透過媒體庫提供。

僅音訊

僅影片

  • flowplayer: 免費,帶有 flowplayer 徽標水印。開源(GPL 許可。)
  • JWPlayer: 需要註冊才能下載。開源版(知識共享許可。)
  • SublimeVideo: 需要註冊。基於表單的設定,帶有指向 CDN 託管庫的域特定連結。
  • Video.js: 免費開源(Apache 2 許可。)

音訊和影片

網頁音訊 API

基本教程

建立跨瀏覽器影片播放器

使用 <video> 元素建立基本跨瀏覽器影片播放器的指南。

影片播放器樣式基礎知識

在上一篇文章中,我們已經使用跨瀏覽器影片播放器,本文將介紹如何為播放器提供一些基本的響應式樣式。

跨瀏覽器音訊基礎知識

本文提供建立跨瀏覽器 HTML 音訊播放器的基本指南,並解釋了所有相關屬性、特性和事件,以及使用媒體 API 建立自定義控制元件的快速指南。

媒體緩衝、查詢和時間範圍

有時,瞭解 <audio><video> 下載了多少內容或可以無延遲播放非常有用 - 音訊或影片播放器的緩衝進度條就是一個很好的例子。本文討論瞭如何使用 TimeRanges 和媒體 API 的其他功能構建緩衝/搜尋條。

HTML playbackRate 解釋

playbackRate 屬性允許我們更改播放網頁音訊或影片的速度或速率。本文對此進行了詳細解釋。

使用 Web Audio API

解釋了使用 Web Audio API 抓取、操作和回放音訊源的基本知識。

流媒體教程

即時流式傳輸網頁音訊和影片

即時流式傳輸技術通常用於轉播體育賽事、音樂會以及更普遍的直播的電視和廣播節目。即時流式傳輸通常簡稱為流式傳輸,它是將媒體“即時”傳輸到計算機和裝置的過程。這是一個相當複雜且新興的主題,涉及很多變數,因此在本篇文章中,我們將向您介紹這個主題,並告訴您如何開始。

設定自適應流媒體源

假設您想在伺服器上設定一個自適應流媒體源,以便在 HTML 媒體元素中使用。您將如何做到這一點?本文解釋瞭如何做到這一點,並介紹了兩種最常見的格式:MPEG-DASH 和 HLS(HTTP 即時流)。

適用於 HTML 5 影片的 DASH 自適應流

詳細介紹瞭如何使用 DASH 和 WebM 設定自適應流式傳輸。

高階教程

將字幕和旁白新增到 HTML 影片

本文解釋瞭如何使用 Web_Video_Text_Tracks_Format<track> 元素為 HTML <video> 新增字幕和旁白。

Web Audio API 跨瀏覽器支援

編寫跨瀏覽器 Web Audio API 程式碼的指南。

使用 MediaRecorder API 簡易音訊捕獲

解釋了使用 MediaStream Recording API 直接錄製媒體流的基本知識。

注意: Firefox OS 1.3 及以上版本支援用於流式影片傳輸的 RTSP 協議。對於舊版本,可以使用 <video> 以及適合 Gecko 的格式(如 WebM)來提供備用內容作為解決方案。這方面的資訊將在合適的時間釋出。

參考資料