使用 Media Capabilities API
Baseline 廣泛可用 *
媒體能力 API(Media Capabilities API)提供了幾個關鍵功能,可以幫助您更好地決定如何處理媒體,以及即時確定媒體的處理效果。
這些功能包括:
- 能夠查詢瀏覽器,以確定在給定一組特定的編碼引數(可能包括編解碼器、解析度、位元率、幀率等)的情況下,瀏覽器編碼或解碼媒體的能力。藉助媒體能力 API,您不僅可以確定瀏覽器是否支援某種格式,還可以確定它是否能高效、流暢地支援。
- 更精細、更詳細的顯示器屬性資訊,以便在為使用者裝置選擇最佳播放格式時做出明智的決策。例如,您可以使用該 API 來確保您不會嘗試在標準動態範圍(SDR)螢幕上播放高動態範圍(HDR)內容。
- 支援獲取媒體播放的即時反饋,以便您的程式碼可以根據此資訊調整流的質量或其他設定,從而管理使用者感知到的媒體效能和質量。其中一項功能是能夠檢測裝置何時切換 GPU,以便您可以根據新 GPU 的能力進行相應調整。
注意: 上述第三點中提到的顯示器能力功能尚未在任何瀏覽器中實現。一旦可用,它們將成為該 API 的有用功能,但在此功能在瀏覽器中實現之前,很可能會發生很大變化。
MediaCapabilities 介面
可以使用 `navigator` 物件和 `WorkerNavigator` 物件提供的 `mediaCapabilities` 屬性來訪問 MediaCapabilities。換句話說,媒體能力 API 既可以在主執行緒中使用,也可以在 worker 中使用。
如果該物件存在,則媒體能力 API 可用。因此,您可以像這樣測試 API 的存在性:
if ("mediaCapabilities" in navigator) {
// mediaCapabilities is available
} else {
// mediaCapabilities IS NOT available
}
以影片為例,要獲取有關影片解碼能力的資訊,您需要建立一個影片解碼配置,並將其作為引數傳遞給 MediaCapabilities.decodingInfo() 方法。該方法返回一個 Promise,該 Promise 會解析出關於媒體能力的以下資訊:影片是否可以解碼,以及解碼是否會流暢且節能。您也可以測試音訊解碼以及影片和音訊編碼。
建立影片解碼配置
MediaCapabilities.decodingInfo() 方法接受一個媒體解碼配置作為引數。
在我們的示例中,我們正在測試影片配置的解碼能力。該配置需要被測試媒體的型別——例如,一個普通的 `file` 或 `MediaSource` —以及一個影片配置物件,該物件包含 `contentType`、`width`、`height`、`bitrate` 和 `framerate` 等值。
- `contentType` 必須是一個指定 有效影片 MIME 型別的字串。
- `width` 和 `height` 是影片的水平和垂直尺寸;它們也用於確定 縱橫比。
- `bitrate` 是編碼一秒鐘影片所使用的位元數。
- `framerate` 是播放影片時每秒鐘播放的幀數。
const videoConfiguration = {
type: "file",
video: {
contentType: "video/webm;codecs=vp8",
width: 800,
height: 600,
bitrate: 10000,
framerate: 15,
},
};
如果我們查詢的是音訊檔案的可解碼性,我們將建立一個包含聲道數和取樣率的音訊配置,並省略僅適用於影片的屬性——即尺寸和幀率。
const audioConfiguration = {
type: "file",
audio: {
contentType: "audio/ogg",
channels: 2,
bitrate: 132700,
samplerate: 5200,
},
};
如果我們測試的是編碼能力,我們將建立一個略有不同的配置。在這種情況下,被測試媒體的型別是 `record`(用於錄製媒體,即 MediaRecorder 物件)或 `transmission`(用於透過電子方式傳輸的媒體,如 RTCPeerConnection)—再加上一個音訊或影片配置,如上所述。
查詢瀏覽器關於解碼能力的資訊
現在我們已經建立了一個影片解碼配置,我們可以將其作為引數傳遞給 decodingInfo() 方法,以確定是否可以解碼符合此配置的影片,以及播放是否流暢且節能。
let promise = navigator.mediaCapabilities.decodingInfo(videoConfiguration);
`decodingInfo()` 和 `encodingInfo()` 方法都返回 Promise。一旦 Promise 狀態 fulfilled(已完成),您就可以從返回的物件中訪問 `supported`、`smooth` 和 `powerEfficient` 屬性。
處理響應
我們可以將 Promise 返回的值輸出到控制檯,而不是將 Promise 分配給一個變數:
navigator.mediaCapabilities.decodingInfo(videoConfiguration).then((result) => {
console.log(
`This configuration is ${result.supported ? "" : "not "}supported,`,
);
console.log(`${result.smooth ? "" : "not "}smooth, and`);
console.log(`${result.powerEfficient ? "" : "not "}power efficient.`);
});
處理錯誤
在我們的影片解碼示例中,如果傳遞給 decodingInfo() 方法的媒體配置無效,將會引發 `TypeError`。發生錯誤可能有幾個原因,包括:
- 指定的 `type` 不是兩個允許值之一:`file` 或 `media-source`。
- 提供的 `contentType` 是:
錯誤可能是由於 `type` 不是兩個可能值之一,`contentType` 不是有效的編解碼器 MIME 型別,或者影片配置物件中缺少無效或省略的定義。
navigator.mediaCapabilities
.decodingInfo(videoConfiguration)
.then(() => console.log("It worked"))
.catch((error) => console.error(`It failed: ${error}`));
媒體能力即時示例
CSS
li {
margin: 1em;
}
HTML
<form>
<p>
Select your video configuration and find out if this browser supports the
codec, and whether decoding will be smooth and power efficient:
</p>
<ul>
<li>
<label for="codec">Select a codec</label>
<select id="codec">
<option>video/webm; codecs=vp8</option>
<option>video/webm; codecs=vp9</option>
<option>video/mp4; codecs=avc1</option>
<option>video/mp4; codecs=avc1.420034</option>
<option>invalid</option>
</select>
</li>
<li>
<label for="size">Select a size</label>
<select id="size">
<option>7680x4320</option>
<option>3840x2160</option>
<option>2560x1440</option>
<option>1920x1080</option>
<option>1280x720</option>
<option selected>800x600</option>
<option>640x480</option>
<option>320x240</option>
<option value=" x ">none</option>
</select>
</li>
<li>
<label for="framerate">Select a framerate</label>
<select id="framerate">
<option>60</option>
<option>50</option>
<option>30</option>
<option>24</option>
<option selected>15</option>
</select>
</li>
<li>
<label for="bitrate">Select a bitrate</label>
<select id="bitrate">
<option>4000</option>
<option>2500</option>
<option>800</option>
</select>
</li>
</ul>
<p>
<input type="button" value="Test this Video Configuration" id="try-it" />
</p>
</form>
<ul id="results"></ul>
JavaScript
let mc = {
videoConfiguration: {},
tryIt() {
mc.createConfiguration();
mc.testIt();
},
createConfiguration() {
const size = document.getElementById("size").value.split("x");
mc.videoConfiguration = {
type: "file",
video: {
contentType: document.getElementById("codec").value,
width: size[0],
height: size[1],
bitrate: document.getElementById("bitrate").value,
framerate: document.getElementById("framerate").value,
},
};
},
testIt() {
let content = "";
navigator.mediaCapabilities
.decodingInfo(mc.videoConfiguration)
.then((result) => {
const li = document.createElement("li"),
mcv = mc.videoConfiguration.video;
content = `A ${mcv.width}x${mcv.height}, ${mcv.contentType} at ${
mcv.framerate
}fps and ${mcv.bitrate} bps video ${
result.supported ? " IS " : "IS NOT "
} supported,`;
content += `${result.smooth ? " IS " : " is NOT "} smooth, and`;
content += `${
result.powerEfficient ? " IS " : " IS NOT "
}power efficient.`;
const ul = document.getElementById("results");
li.textContent = content;
ul.appendChild(li);
})
.catch((error) => {
const li = document.createElement("li"),
ul = document.getElementById("results");
li.textContent = `Codec ${mc.videoConfiguration.video.contentType} threw an error: ${error}`;
ul.appendChild(li);
});
},
};
document.getElementById("try-it").addEventListener("click", mc.tryIt);
即時結果
瀏覽器相容性
載入中…