從任何元素擷取影片串流

François Beaufort
François Beaufort

只要使用螢幕畫面擷取 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()

呼叫 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 版本移除後,使用者看不到或無法看到的顏色。舉例來說,如果透明區域使用 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 的體驗。

請提供設計相關資訊

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

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

導入時發生問題?

你是否發現 Chrome 實作項目有錯誤?還是採用與規格不同?

  • 前往 https://new.crbug.com 回報錯誤。請盡可能提供所有細節,以及簡單的重製說明。Glitch 有便捷的報復工具,

特別銘謝

相片來源:Paul Skorupskas,來源為 Unsplash