MediaStreamTrack 的可插入串流

MediaStreamTrack 的內容會以可操控或用於產生新內容的串流形式公開

背景

Media Capture and Streams API 的情況下,MediaStreamTrack 介面代表串流中的單一媒體音軌;通常是音訊或視訊音軌,但也可能有其他類型的音軌。MediaStream 物件包含零個或多個 MediaStreamTrack 物件,代表各種音訊或影片音軌。每個 MediaStreamTrack 可能會有一或多個管道。頻道代表媒體串流的最小單位,例如與特定揚聲器相關聯的音訊訊號,例如立體聲音軌中的左聲或右聲。

MediaStreamTrack 的插入串流是什麼?

MediaStreamTrack 可插入串流的核心概念,是將 MediaStreamTrack 的內容公開為一系列串流 (由 WHATWG Streams API 定義)。您可以操控這些串流,以便引入新的元件。

授予開發人員直接存取影片 (或音訊) 串流的權限,即可讓他們直接對串流套用修改。相較之下,如果要使用傳統方法完成相同的影片操控作業,開發人員必須使用 <canvas> 元素等中介元件。(如要進一步瞭解這類程序,請參閱「影片 + 畫布 = 魔術」一文)。

瀏覽器支援

自 Chrome 94 起,系統支援 MediaStreamTrack 的可插入串流。

用途

MediaStreamTrack 可插入串流的用途包括但不限於:

  • 視訊會議小工具,例如「有趣的帽子」或虛擬背景。
  • 語音處理功能,例如軟體語音編碼器

如何為 MediaStreamTrack 使用可插入的串流

特徵偵測

您可以透過以下方式,為 MediaStreamTrack 支援功能偵測可插入的串流。

if ('MediaStreamTrackProcessor' in window && 'MediaStreamTrackGenerator' in window) {
  // Insertable streams for `MediaStreamTrack` is supported.
}

核心概念

MediaStreamTrack 的插入式串流會以 WebCodecs 先前提出的概念為基礎,並在概念上將 MediaStreamTrack 分成兩個元件:

  • MediaStreamTrackProcessor 會使用 MediaStreamTrack 物件的來源,並產生媒體影格串流,特別是 VideoFrameAudioFrame 物件。您可以將這項功能視為音軌匯流器,能夠將音軌中未編碼的影格公開為 ReadableStream
  • MediaStreamTrackGenerator:會耗用媒體影格串流並公開 MediaStreamTrack 介面。這可以提供給任何接收端,就像來自 getUserMedia() 的曲目一樣。並將媒體影格做為輸入內容。

MediaStreamTrackProcessor

MediaStreamTrackProcessor 物件會公開一個屬性 readable。可讀取 MediaStreamTrack 中的影格。如果音軌是影片音軌,從 readable 讀取的區塊會是 VideoFrame 物件。如果音軌是音訊音軌,從 readable 讀取的區塊將會是 AudioFrame 物件。

MediaStreamTrackGenerator

MediaStreamTrackGenerator 物件也會公開一個屬性 writable,這是一個 WritableStream,可將媒體影格寫入 MediaStreamTrackGenerator,而 MediaStreamTrackGenerator 本身就是 MediaStreamTrack。如果 kind 屬性為 "audio",串流會接受 AudioFrame 物件,但無法接受任何其他類型。如果 kind 為 "video",串流會接受 VideoFrame 物件,但無法接受任何其他類型。當影格寫入 writable 時,系統會自動叫用影格的 close() 方法,因此無法再透過 JavaScript 存取其媒體資源。

MediaStreamTrackGenerator 是可透過將媒體影格寫入其 writable 欄位,實作自訂來源的音軌。

合併運用各種策略

核心概念是建立以下的處理鏈結:

平台追蹤 → 處理器 → 轉換 → 產生器 → 平台接收端

以下範例說明瞭這個鏈結,針對條碼掃描器應用程式,在直播影片串流中醒目顯示偵測到的條碼。

const stream = await getUserMedia({ video: true });
const videoTrack = stream.getVideoTracks()[0];

const trackProcessor = new MediaStreamTrackProcessor({ track: videoTrack });
const trackGenerator = new MediaStreamTrackGenerator({ kind: 'video' });

const transformer = new TransformStream({
  async transform(videoFrame, controller) {
    const barcodes = await detectBarcodes(videoFrame);
    const newFrame = highlightBarcodes(videoFrame, barcodes);
    videoFrame.close();
    controller.enqueue(newFrame);
  },
});

trackProcessor.readable.pipeThrough(transformer).pipeTo(trackGenerator.writable);

const videoBefore = document.getElementById('video-before');
const videoAfter = document.getElementById('video-after');
videoBefore.srcObject = stream;
const streamAfter = new MediaStream([trackGenerator]);
videoAfter.srcObject = streamAfter;

示範

您可以查看上述章節中的QR code 掃描器示範,瞭解如何在電腦或行動瀏覽器上使用這項功能。將 QR code 放在相機鏡頭前,應用程式就會偵測並標示出來。您可以在 Glitch 上查看應用程式原始碼。

在電腦版瀏覽器分頁中執行的 QR code 掃描器,顯示使用者在筆電相機前方握住的手機上,已偵測到並標示為醒目標記的 QR code。

安全性和隱私權考量

這個 API 的安全性取決於網路平台中的現有機制。由於資料是使用 VideoFrameAudioFrame 介面公開,因此這些介面處理來源污染資料的規則會套用。舉例來說,由於存取這類資源的現有限制,無法存取跨來源資源的資料 (例如無法存取跨來源圖片或影片元素的像素)。此外,攝影機、麥克風或螢幕的媒體資料存取權,取決於使用者授權。這個 API 公開的媒體資料已可透過其他 API 取得。

意見回饋

Chromium 團隊希望瞭解您對 MediaStreamTrack 可插入式串流的使用體驗。

請告訴我們 API 設計

API 是否有任何功能無法正常運作?或者,您是否缺少實作想法所需的方法或屬性?您對安全性模型有疑問或意見嗎?在對應的 GitHub 存放區中提交規格問題,或在現有問題中加入您的想法。

回報實作問題

你是否發現 Chromium 實作項目有錯誤?或者實作方式與規格不同?請前往 new.crbug.com 回報錯誤。請務必盡可能提供詳細資訊,並在「Components」方塊中輸入 Blink>MediaStream,以便重現問題。Glitch 可讓您輕鬆快速地分享重現內容。

顯示對 API 的支援

您是否打算為 MediaStreamTrack 使用可插入的串流?您的公開支持有助於 Chromium 團隊決定功能優先順序,並向其他瀏覽器供應商顯示支援這些功能的重要性。

使用主題標記 #InsertableStreams 發送推文給 @ChromiumDev,告訴我們你在何處使用這項功能,以及使用方式。

特別銘謝

MediaStreamTrack 規格可插入串流是由 Harald AlvestrandGuido Urdaneta 編寫。本文經 Harald Alvestrand、Joe MedleyBen WagnerHuib KleinhoutFrançois Beaufort 審查。主頁橫幅圖片由 Chris MontgomeryUnsplash 上提供。