MediaStreamTrack
的內容會以串流形式公開,可供操弄或用來生成新內容
背景
在媒體擷取和串流 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.
}
核心概念
可插入串流是根據 WebCodecs 先前提出的概念建構,並從概念上將 MediaStreamTrack
分成兩個元件:MediaStreamTrack
MediaStreamTrackProcessor
會取用MediaStreamTrack
物件的來源,並產生媒體影格串流,具體來說是VideoFrame
或AudioFrame
物件。您可以將此視為軌道接收器,能夠將軌道中的未編碼影格公開為ReadableStream
。MediaStreamTrackGenerator
,會耗用媒體影格串流並公開MediaStreamTrack
介面。可以提供給任何接收器,就像getUserMedia()
中的音軌一樣。並以媒體影格做為輸入內容。
MediaStreamTrackProcessor
MediaStreamTrackProcessor
物件會顯示一個屬性,即 readable
。這項功能可讀取 MediaStreamTrack
中的影格。如果音軌是視訊音軌,從 readable
讀取的區塊會是 VideoFrame
物件。如果軌道是音軌,從 readable
讀取的區塊會是 AudioFrame
物件。
MediaStreamTrackGenerator
MediaStreamTrackGenerator
物件同樣會公開一個屬性 writable
,也就是 WritableStream
,可將媒體影格寫入 MediaStreamTrackGenerator
,而 MediaStreamTrackGenerator
本身就是 MediaStreamTrack
。如果 kind
屬性為 "audio"
,則串流會接受 AudioFrame
物件,並在收到任何其他類型時失敗。如果種類為 "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 放在相機鏡頭前,應用程式會偵測並醒目顯示 QR code。您可以在 GitHub 上查看應用程式的原始碼。
安全性和隱私權注意事項
這項 API 的安全性取決於網頁平台現有的機制。由於資料是透過 VideoFrame
和 AudioFrame
介面公開,因此適用於處理來源汙染資料的介面規則。舉例來說,由於存取這類資源有現行限制 (例如無法存取跨來源圖片或影片元素的像素),因此無法存取跨來源資源的資料。此外,存取攝影機、麥克風或螢幕的媒體資料時,也必須取得使用者授權。這個 API 公開的媒體資料已可透過其他 API 取得。
意見回饋
Chromium 團隊想瞭解您使用可插入串流的體驗,請填寫MediaStreamTrack
。
介紹 API 設計
API 是否有任何不符合預期的運作方式?或者,是否有缺少的屬性或方法需要實作,才能實現您的想法?你對安全模式有任何疑問或意見嗎?在對應的 GitHub 存放區中提出規格問題,或在現有問題中新增想法。
回報導入問題
您是否發現 Chromium 實作有錯誤?還是實作方式與規格不同?
在 new.crbug.com 提出錯誤回報。請務必盡可能提供詳細資料、重現問題的簡單操作說明,並在「Components」(元件) 方塊中輸入 Blink>MediaStream
。
支援 API
您是否打算使用可插入的 MediaStreamTrack
串流?您的公開支持有助於 Chromium 團隊優先處理功能,並向其他瀏覽器供應商展現支援這些功能的重要性。
使用 #InsertableStreams
主題標記傳送推文給 @ChromiumDev,告訴我們您在何處使用這項功能,以及使用方式。
實用連結
特別銘謝
MediaStreamTrack
規格的可插入串流是由 Harald Alvestrand 和 Guido Urdaneta 編寫。本文由 Harald Alvestrand、Joe Medley、Ben Wagner、Huib Kleinhout 和 François Beaufort 審查。圖片來源:
Chris Montgomery (Unsplash)。