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,即 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 上提供。