音訊和影片傳輸
我們可以在網路上以多種方式交付音訊和影片,從“靜態”媒體檔案到自適應直播流。本文旨在作為一個起點,探索基於網路的媒體的各種交付機制以及與流行瀏覽器的相容性。
音訊和影片 HTML 元素
無論是預錄製的音訊檔案還是直播流,透過瀏覽器的 <audio> 和 <video> 元素使其可用的機制基本相同。目前,為了支援所有瀏覽器,我們需要指定兩種格式,儘管隨著 MP3 和 MP4 格式在 Firefox 和 Opera 中的採用,這種情況正在迅速改變。您可以在網路媒體型別和格式指南中找到相容性資訊。
要交付影片和音訊,通常的工作流程如下:
- 透過功能檢測檢查瀏覽器支援哪種格式(通常如上所述,有兩種選擇)。
- 如果瀏覽器原生不支援任何提供的格式的播放,則顯示靜止影像或使用備用技術來呈現影片。
- 確定您希望如何播放/例項化媒體(例如,一個
<video>元素,或者document.createElement('video')怎麼樣?)。 - 將媒體檔案交付給播放器。
HTML 音訊
<audio controls preload="auto">
<source src="audio-file.mp3" type="audio/mpeg" />
<!-- fallback for browsers that don't support mp3 -->
<source src="audio-file.ogg" type="audio/ogg" />
<!-- fallback for browsers that don't support audio element -->
<a href="audio-file.mp3">download audio</a>
</audio>
上面的程式碼將建立一個音訊播放器,該播放器會嘗試儘可能多地預載入音訊以實現流暢播放。
注意: preload 屬性可能會被某些移動瀏覽器忽略。
有關更多資訊,請參閱跨瀏覽器音訊基礎 (HTML 音訊詳解)
HTML 影片
<video
controls
width="640"
height="480"
poster="initial-image.png"
autoplay
muted>
<source src="video-file.mp4" type="video/mp4" />
<!-- fallback for browsers that don't support mp4 -->
<source src="video-file.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 element -->
<a href="video-file.mp4">download video</a>
</video>
上面的程式碼建立了一個尺寸為 640x480 畫素的影片播放器,在影片播放之前顯示海報影像。我們指示影片自動播放但預設靜音。
注意: autoplay 屬性可能會被某些移動瀏覽器忽略。此外,自動播放功能如果濫用可能會引起爭議。強烈建議您閱讀媒體和 Web 音訊 API 自動播放指南,以瞭解如何明智地使用自動播放。
有關更多資訊,請參閱<video> 元素和建立跨瀏覽器影片播放器。
JavaScript 音訊
const myAudio = document.createElement("audio");
if (myAudio.canPlayType("audio/mpeg")) {
myAudio.setAttribute("src", "audio-file.mp3");
} else if (myAudio.canPlayType("audio/ogg")) {
myAudio.setAttribute("src", "audio-file.ogg");
}
myAudio.currentTime = 5;
myAudio.play();
我們根據瀏覽器支援的音訊檔案型別設定音訊源,然後將播放頭設定在 5 秒處並嘗試播放它。
注意: 除非由使用者啟動的事件觸發,否則大多數瀏覽器將忽略播放。
還可以向 <audio> 元素提供 Base64 編碼的 WAV 檔案,從而能夠即時生成音訊。
<audio id="player" src="data:audio/x-wav;base64,UklGRvC…"></audio>
Speak.js 採用了這種技術。
JavaScript 影片
const myVideo = document.createElement("video");
if (myVideo.canPlayType("video/mp4")) {
myVideo.setAttribute("src", "video-file.mp4");
} else if (myVideo.canPlayType("video/webm")) {
myVideo.setAttribute("src", "video-file.webm");
}
myVideo.width = 480;
myVideo.height = 320;
我們根據瀏覽器支援的影片檔案型別設定影片源,然後設定影片的寬度和高度。
Web Audio API
在此示例中,我們使用 fetch() API 檢索 MP3 檔案,將其載入到源中,然後播放。
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;
});
在使用 Web Audio API中查詢有關 Web Audio API 基礎知識的更多資訊。
getUserMedia / Stream API
還可以使用 getUserMedia 和 Stream API 從網路攝像頭和/或麥克風獲取直播流。這是 WebRTC(Web 即時通訊)這項更廣泛技術的一部分,並與最新版本的 Chrome、Firefox 和 Opera 相容。
要從網路攝像頭獲取流,首先設定一個 <video> 元素
<video id="webcam" width="480" height="360"></video>
接下來,如果支援,將網路攝像頭源連線到影片元素
if (navigator.mediaDevices) {
navigator.mediaDevices
.getUserMedia({ video: true, audio: false })
.then((stream) => {
const video = document.getElementById("webcam");
video.autoplay = true;
video.srcObject = stream;
})
.catch(() => {
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 Recording
正在推出新標準,允許您的瀏覽器使用 getUserMedia 從麥克風或攝像頭獲取媒體,並使用新的 MediaStream Recording API 立即錄製。您從 getUserMedia 接收到的流,將其傳遞給 MediaRecorder 物件,獲取結果輸出並將其饋送到您的音訊或影片源*。
主要機制如下所述
navigator.mediaDevices
.getUserMedia({ audio: true })
.then((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((error) => {
console.log(error.message);
});
有關更多詳細資訊,請參閱MediaStream Recording API。
媒體源擴充套件 (MSE)
媒體源擴充套件 (Media Source Extensions) 是 W3C 的一個工作草案,旨在擴充套件 HTMLMediaElement,允許 JavaScript 生成媒體流進行播放。允許 JavaScript 生成流有助於實現各種用例,例如自適應流媒體和即時流媒體的時間平移。
加密媒體擴充套件 (EME)
加密媒體擴充套件 (Encrypted Media Extensions) 是 W3C 提出的一個提案,旨在擴充套件 HTMLMediaElement,提供 API 來控制受保護內容的播放。
該 API 支援從基本明文金鑰解密到高價值影片的各種用例(如果使用者代理實現得當)。許可證/金鑰交換由應用程式控制,有助於開發支援各種內容解密和保護技術的健壯播放應用程式。
EME 的主要用途之一是允許瀏覽器實施 DRM (數字版權管理),這有助於防止基於網路的內容(尤其是影片)被複制。
自適應流媒體
正在推出新的格式和協議以促進自適應流媒體。自適應流媒體意味著流的頻寬和通常的質量可以即時變化,以響應使用者的可用頻寬。自適應流媒體通常與直播流媒體結合使用,其中音訊或影片的流暢交付至關重要。
用於自適應流媒體的主要格式是 HLS 和 MPEG-DASH。MSE 的設計考慮了 DASH。MSE 根據 ISOBMFF 和 M2TS 定義位元組流(兩者都受 DASH 支援,後者受 HLS 支援)。一般來說,如果您對標準感興趣,正在尋找靈活性,或者希望支援大多數現代瀏覽器,那麼使用 DASH 可能更好。
注意: 目前 Safari 不支援 DASH,儘管 dash.js 將在計劃與 OS X Yosemite 一起釋出的新版本 Safari 上執行。
DASH 還提供了許多配置檔案,包括不需要預處理和拆分媒體檔案的點播配置檔案。還有許多基於雲的服務可以將您的媒體轉換為 HLS 和 DASH。
有關更多資訊,請參閱直播網路音訊和影片。
自定義您的媒體播放器
您可能希望您的音訊或影片播放器在所有瀏覽器中都具有一致的外觀,或者只是希望對其進行調整以匹配您的網站。實現這一目標的通用技術是省略 controls 屬性,以便不顯示預設瀏覽器控制元件,使用 HTML 和 CSS 建立自定義控制元件,然後使用 JavaScript 將您的控制元件連結到音訊/影片 API。
如果您需要額外功能,可以新增預設播放器中目前不存在的功能,例如播放速率、質量流切換甚至音訊頻譜。您還可以選擇如何使播放器響應式——例如,您可以在某些條件下移除進度條。
您可以檢測點選、觸控和/或鍵盤事件來觸發諸如播放、暫停和擦洗等操作。為了方便使用者和可訪問性,記住鍵盤控制通常很重要。
一個快速示例——首先在 HTML 中設定您的音訊和自定義控制元件
<audio id="my-audio" src="/shared-assets/audio/guitar.mp3"></audio>
<button id="my-control">play</button>
新增一些 JavaScript 來檢測播放和暫停音訊的事件
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();
});
window.addEventListener("keypress", checkKey);
有關更多資訊,請參閱建立您自己的自定義音訊播放器。
音訊/影片的其他技巧
停止媒體下載
停止媒體播放就像呼叫元素的 pause() 方法一樣簡單,但瀏覽器會繼續下載媒體,直到透過垃圾回收處理掉媒體元素。
這裡有一個技巧可以立即停止下載
const mediaElement = document.querySelector("#myMediaElementID");
mediaElement.removeAttribute("src");
mediaElement.load();
透過刪除媒體元素的 src 屬性並呼叫 load() 方法,您可以釋放與影片相關的資源,從而停止網路下載。您必須在刪除屬性後呼叫 load(),因為僅僅刪除 src 屬性不會呼叫載入演算法。如果 <video> 元素還有 <source> 元素後代,則在呼叫 load() 之前也應將其刪除。
請注意,僅僅將 src 屬性設定為空字串實際上會導致瀏覽器將其視為您正在將影片源設定為相對路徑。這會導致瀏覽器嘗試另一次下載可能不是有效影片的內容。
在媒體中搜索
媒體元素支援將當前播放位置移動到媒體內容的特定點。這是透過設定元素上的 currentTime 屬性值來完成的;有關元素屬性的更多詳細資訊,請參閱 HTMLMediaElement。將值設定為您希望播放繼續的秒數。
您可以使用元素的 seekable 屬性來確定當前可供查詢的媒體範圍。這會返回一個 TimeRanges 物件,其中列出了您可以查詢的時間範圍。
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-
指定影片應從頭開始播放到兩小時。
http://example.com/video.ogv#t=60-
指定影片應從 60 秒開始播放,並播放到影片結束。
錯誤處理
錯誤會傳遞給導致錯誤的子 <source> 元素對應的源。
這讓您可以檢測哪些源載入失敗,這可能很有用。考慮以下 HTML
<video>
<source
id="mp4_src"
src="video.mp4"
type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
<source
id="3gp_src"
src="video.3gp"
type='video/3gpp; codecs="mp4v.20.8, samr"' />
<source
id="ogg_src"
src="video.ogv"
type='video/ogv; codecs="theora, vorbis"' />
</video>
由於 Firefox 在某些平臺上由於專利受限的性質不支援 MP4 和 3GP,ID 為“mp4_src”和“3gp_src”的 <source> 元素將在 Ogg 資源載入之前接收 error 事件。源按它們出現的順序嘗試,一旦一個成功載入,其餘的源根本不會嘗試。
檢查瀏覽器是否支援所提供的格式
媒體格式的支援可在Can I Use上找到。
- 音訊 MP3 (
type="audio/mpeg") - 音訊 Ogg (
type="audio/ogg") - 影片 MP4 (
type="video/mp4") - 影片 WebM (
type="video/webm") - 影片 Ogg (
type="video/ogg")
您還可以搜尋其他媒體格式。
如果媒體格式應該支援但您提供的檔案無法播放,則可能存在兩個問題
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 會嘗試載入指定的資源。
當無法解碼任何源時顯示備用內容
在當前瀏覽器中無法解碼任何源時顯示影片備用內容的另一種方法是在最後一個源元素上新增一個錯誤處理程式。然後,您可以將影片替換為備用內容
<video controls>
<source src="dynamicsearch.mp4" type="video/mp4" />
<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>
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);
});
音訊/影片 JavaScript 庫
存在許多音訊和影片 JavaScript 庫。最流行的庫允許您在所有瀏覽器中選擇一致的播放器設計,併為不支援音訊和影片的瀏覽器提供備用方案。備用方案歷來使用現在已過時的外掛,如 Adobe Flash 或 Microsoft Silverlight 外掛,以在不支援的瀏覽器中提供媒體播放器,儘管這些外掛在現代計算機上不再受支援。字幕的 <track> 元素等其他功能也可以透過媒體庫提供。
僅音訊
僅影片
- flowplayer:免費提供 flowplayer 徽標水印。開源(GPL 許可)。
- JWPlayer:需要註冊才能下載。開源版(Creative Commons 許可)。
- SublimeVideo:需要註冊。基於表單設定,帶有特定域連結到 CDN 託管庫。
- Video.js:免費和開源(Apache 2 許可)。
音訊和影片
- jPlayer:免費和開源(MIT 許可)。
- mediaelement.js:免費和開源(MIT 許可)。
Web Audio API
- AudioContext monkeypatch:Web Audio API 舊版本的 Polyfill;開源(Apache 2 許可)。
指南
- 建立跨瀏覽器影片播放器
-
使用
<video>元素建立基本跨瀏覽器影片播放器的指南。 - 影片播放器樣式基礎
-
在前一篇文章中放置了跨瀏覽器影片播放器之後,本文現在著眼於為播放器提供一些基本的響應式樣式。
- 為 HTML 影片新增字幕和副標題
-
本文解釋瞭如何使用 Web_Video_Text_Tracks_Format 和
<track>元素為 HTML<video>新增字幕和副標題。 - 跨瀏覽器音訊基礎
-
本文提供了一份建立跨瀏覽器 HTML 音訊播放器的基本指南,其中解釋了所有相關的屬性、特性和事件,並提供了使用媒體 API 建立自定義控制元件的快速指南。
- 媒體緩衝、查詢和時間範圍
-
有時瞭解
<audio>或<video>已下載或可以無延遲播放多少內容會很有用——一個很好的例子是音訊或影片播放器的緩衝進度條。本文討論瞭如何使用 TimeRanges 以及媒體 API 的其他功能來構建緩衝/查詢條。 - HTML playbackRate 詳解
-
playbackRate屬性允許我們改變網路音訊或影片播放的速度或速率。本文詳細解釋了它。 - 使用 Web Audio API
-
解釋了使用 Web Audio API 獲取、操作和播放音訊源的基礎知識。
流媒體
- 直播網路音訊和影片
-
直播流技術通常用於轉播體育賽事、音樂會以及更普遍的電視和廣播節目的直播。通常簡稱為流媒體,直播流是將媒體“即時”傳輸到計算機和裝置的過程。這是一個相當複雜且新興的主題,有很多變數,因此在本文中,我們將向您介紹該主題,並讓您瞭解如何入門。
- 設定自適應流媒體源
-
假設您想在伺服器上設定自適應流媒體源,以便在 HTML 媒體元素中進行消費。您將如何做到這一點?本文將解釋如何實現,並著眼於兩種最常見的格式:MPEG-DASH 和 HLS(HTTP Live Streaming)。
- 適用於 HTML 5 影片的 DASH 自適應流媒體
-
詳細說明如何使用 DASH 和 WebM 設定自適應流媒體。
高階主題
- Web Audio API 跨瀏覽器支援
-
編寫跨瀏覽器 Web Audio API 程式碼的指南。
- 使用 MediaRecorder API 輕鬆捕獲音訊
-
解釋了使用 MediaStream Recording API 直接錄製媒體流的基礎知識。