從任何元素擷取影片串流

François Beaufort
François Beaufort

您可以使用 Screen Capture API 擷取目前的整個分頁。Element Capture API 可讓您擷取及記錄特定 HTML 元素。它會將整個分頁的擷取畫面轉換為特定 DOM 子樹的擷取畫面,只擷取目標元素的直接子項。換句話說,它會裁剪並移除遮蔽和被遮蔽的內容。

為什麼要使用元素擷取功能?

考量視訊會議應用程式的需求,有助於您瞭解 Element Capture 的用途。如果您有視訊會議應用程式,可在 iframe 中嵌入第三方應用程式,您可能有時會想要擷取該 iframe 做為影片,並傳送給遠端參與者。

Chrome 視訊會議通話的螢幕截圖。
Elad 在與 François 的視訊會議通話中使用第三方應用程式。

呼叫 getDisplayMedia() 並讓使用者選擇目前的分頁,即可傳送整個目前的分頁。這麼做很可能會將使用者自己的影片傳回給他們。您可以使用「區域擷取」功能裁剪掉這部分。

不過,如果講者使用視訊會議應用程式,而某些內容 (例如下拉式選單) 剛好出現在要擷取的內容上方,該怎麼辦呢?

下拉式選單的螢幕截圖,遮住了要擷取的內容。
下拉式清單會顯示在要擷取的內容上方。

區域擷取功能無法提供這類協助。部分下拉式選單可能會顯示在遠端參與者的螢幕上。

下拉式選單的螢幕截圖。
Elad 的下拉式清單會顯示在 François 收到的內容上方。

區域擷取功能以這種方式擷取部分元素 (稱為「遮蔽內容」),會造成多項問題:

  • 遮蔽內容可能會遮蓋使用者要分享的內容。
  • 遮蔽的內容可能屬於私人內容 (例如即時通訊通知)。
  • 遮蔽內容可能會造成混淆。(舉例來說,應用程式的重新版面配置可能會讓遠端參與者自己的影片短暫出現在擷取目標上)。

元素擷取 API 可解決所有這些問題,讓您指定要分享的元素。

目標元素的螢幕截圖,畫面中沒有下拉式選單。
François 看不到 Elad 的下拉式清單。

如何使用 Element Capture?

captureTarget 是網頁上的元素,其中包含使用者要擷取的內容。您希望視訊會議網頁應用程式擷取 captureTarget,並與遠端參與者分享。因此,您可以從 captureTarget 衍生出 RestrictionTarget。使用這個 RestrictionTarget 限制影片軌後,該影片軌的幀只包含 captureTarget 和其直接 DOM 子項的像素。

如果 captureTarget 變更大小、形狀或位置,影片軌道也會隨之變更,不需要從任何一個網頁應用程式取得額外輸入內容。同樣地,遮蔽出現、消失或移動的內容也不需要特別處理。

請再次查看下列步驟:

首先,允許使用者擷取目前的分頁。

// Ask the user for permission to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
 preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();

請呼叫 RestrictionTarget.fromElement(),並將所選元素做為輸入內容,藉此定義 RestrictionTarget

// Associate captureTarget with a new RestrictionTarget
const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

接著,請在影片軌道上呼叫 restrictTo(),並將 RestrictionTarget 做為輸入內容。最後一個承諾解析後,所有後續影格都會受到限制。

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

// Enjoy! Transmit remotely.

深入探索

特徵偵測

如要檢查是否支援 RestrictionTarget.fromElement(),請使用:

if ("RestrictionTarget" in self && "fromElement" in RestrictionTarget) {
  // Deriving a restriction target is supported.
}

衍生 RestrictionTarget

將焦點放在名為 captureTarget元素上。如要從中衍生 RestrictionTarget,請呼叫 RestrictionTarget.fromElement(captureTarget)。如果成功,系統會使用新的 RestrictionTarget 物件解析傳回的 Promise。否則,如果您鑄造的 RestrictionTarget 物件數量不合理,系統就會拒絕。

const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

與元素不同,RestrictionTarget 物件是可序列化的。例如,您可以使用 Window.postMessage() 將其傳遞至其他文件。

受限

擷取分頁時,影片軌會顯示 restrictTo()。擷取目前分頁時,您可以使用 null 或任何 RestrictionTarget 呼叫 restrictTo(),這些 RestrictionTarget 是從目前分頁中的元素衍生而來。

restrictTo(restrictionTarget) 的呼叫會將影片軌道變更為 captureTarget 的擷取畫面,就好像是獨立於 DOM 的其他部分一樣。系統也會擷取 captureTarget 的所有子項;captureTarget 的兄弟項目則會從擷取作業中排除。結果是,軌道上傳送的任何影格都會顯示為裁剪至 captureTarget 輪廓,且會移除所有遮蔽和被遮蔽的內容。

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

呼叫 restrictTo(null) 會將音軌還原為原始狀態。

// Stop restricting.
await track.restrictTo(null);

如果對 restrictTo() 的呼叫成功,且可保證所有後續的影片影格都會限制為 captureTarget,系統就會解析傳回的 Promise。

如果失敗,則會拒絕承諾。呼叫 restrictTo() 失敗的原因如下:

  • 如果 restrictionTarget 是在擷取畫面的分頁以外鑄造,(請注意,使用「改為分享這個分頁」按鈕時,使用者可能會在任何時間變更要擷取的分頁)。
  • 如果 restrictionTarget 是從已不存在的元素衍生而來。
  • 如果曲目有副本,(請參閱問題 1509418)。
  • 如果目前的音軌不是自拍影片音軌。
  • 如果 restrictionTarget 衍生自的元素不符合限制條件。

自行擷取影像的考量因素

當應用程式呼叫 getDisplayMedia(),且使用者選擇擷取應用程式自己的分頁時,我們稱之為「自我擷取」。

restrictTo() 方法會在任何分頁擷取影片軌道上公開,而不僅限於自拍。不過,元素擷取功能目前僅支援自拍。因此,建議您在嘗試限制曲目之前,先確認使用者是否選取了目前的分頁。您可以使用擷取句柄完成這項操作。您也可以使用 preferCurrentTab,要求瀏覽器提醒使用者進行自拍。

透明度

應用程式透過 getDisplayMedia() 取得的影片影格不含 Alpha 通道。如果應用程式設定部分透明的擷取目標,去除 alpha 通道可能會導致以下情況:

  • 顏色可能會有所不同。在淺色背景上繪製的部分透明目標元素,在移除 alpha 通道後可能會變暗,而在深色背景上繪製的目標元素則可能會變亮。
  • 當您將 Alpha 通道設為最大值時,使用者看不到或無法察覺的顏色,會在移除 Alpha 通道後才會顯示。舉例來說,如果透明區域使用 RGBA 代碼 rgba(0, 0, 0, 0),這可能會導致擷取的畫面出現意外的黑色區域。
非矩形透明擷取目標的結果螢幕截圖。
非矩形透明擷取目標影片串流 (右圖) 是包含不透明藍色圓形的黑色背景矩形。

不符資格的擷取目標

您隨時可以開始將音軌限制為任何有效的擷取目標。不過,在特定情況下,系統不會產生影格,例如元素或祖系為 display:none 的情況。一般來說,這項限制只適用於單一、緊密連結的二維矩形區域,且該區域的像素可在邏輯上與任何父項或同層元素分開。

為確保元素符合限制條件,請務必考量到它必須形成自己的堆疊內容。為確保這項功能,您可以指定 isolation CSS 屬性,並將其設為 isolate

<div id="captureTarget" style="isolation: isolate;"></iframe>

請注意,目標元素可以在任何任意時間點切換為符合或不符合限制資格,例如,如果應用程式變更其 CSS 屬性。應用程式必須使用合理的擷取目標,並避免意外變更屬性。如果目標元素變得不符合條件,系統就不會在軌道上發出新影格,直到目標元素再次符合限制條件為止。

啟用元素擷取功能

在 Chrome 電腦版中,Element Capture API 可透過 Element Capture 旗標使用,並可在 chrome://flags/#element-capture 中啟用。

這項功能也在 Chrome 121 版的電腦上進入原點試用階段,開發人員可以為網站訪客啟用這項功能,收集真實使用者的資料。如要進一步瞭解原點測試,請參閱「開始進行原點測試」。

安全性和隱私權

如要瞭解安全性取捨,請參閱「Element Capture」規格中的「隱私權和安全性考量事項」一節。

Chrome 瀏覽器會在擷取的分頁邊緣畫上藍色邊框。

示範

您可以在 Glitch 上執行示範,體驗 Element Capture 的功能。請務必查看原始碼

意見回饋

Chrome 團隊和網路標準社群希望瞭解你使用 Element Capture 的體驗。

請提供設計相關資訊

有任何區域擷取功能無法正常運作嗎?或者,您是否缺少實作想法所需的方法或屬性?您對安全性模型有疑問或意見嗎?

  • GitHub 存放區中提出規格問題,或在現有問題中加入您的想法。

導入時發生問題?

你是否發現 Chrome 實作項目有錯誤?或者實作方式與規格不同?

  • 請前往 https://new.crbug.com 提交錯誤。請務必提供盡可能多的詳細資料,以及重現問題的簡單操作說明。Glitch 可讓您輕鬆快速地分享重現內容。

特別銘謝

相片來源:Paul SkorupskasUnsplash 網站上提供