從任何元素擷取影片串流

François Beaufort
François Beaufort

使用 Screen Capture API,即可擷取整個目前分頁。元素擷取 API 可讓您擷取及錄製特定 HTML 元素。這項功能會將整個分頁的擷取畫面,轉換為特定 DOM 子樹狀結構的擷取畫面,只擷取目標元素的直接後代。換句話說,這項功能會裁剪並移除遮蔽和被遮蔽的內容。

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

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

Chrome 中的視訊會議通話畫面截圖。
Elad 在與 François 進行視訊會議通話時使用第三方應用程式。

呼叫 getDisplayMedia() 並讓使用者選擇目前的分頁,會傳輸整個目前的分頁。這可能會將使用者的視訊傳回給他們。你可以使用「區域擷取」裁剪掉這部分。

不過,如果簡報者與視訊會議應用程式互動,而下拉式清單等內容剛好繪製在要擷取的內容上方,該怎麼辦?

螢幕截圖:下拉式清單遮蓋了要擷取的內容。
要擷取的內容上方會顯示下拉式清單。

這時區域擷取功能就派不上用場。遠端參與者的螢幕上可能會顯示部分下拉式清單。

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

區域擷取功能會以這種方式擷取元素部分內容 (稱為遮蔽內容),因此會產生多個問題:

  • 遮蓋內容可能會妨礙使用者分享內容。
  • 遮蔽的內容可能是私人內容 (例如即時通訊通知)。
  • 遮蔽內容可能會造成混淆。(舉例來說,重新配置應用程式版面可能會暫時將遠端參與者的影片移至擷取的目標上方)。

Element Capture API 可讓您指定要分享的元素,解決上述所有問題。

螢幕截圖:目標元素,但沒有顯示下拉式清單。
François 看不到 Elad 的下拉式清單。

如何使用元素擷取功能?

captureTarget 是網頁上的 Element,內含使用者想擷取的內容。您希望視訊會議網頁應用程式擷取 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);

然後以 RestrictionTarget 做為輸入內容,在視訊軌上呼叫 restrictTo()。最後一個 Promise 解決後,所有後續影格都會受到限制。

// 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)。如果成功,傳回的 Promise 會以新的 RestrictionTarget 物件解析。否則,如果您鑄造的 RestrictionTarget 物件數量不合理,系統就會拒絕。

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

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

受限

擷取分頁時,影片軌會公開 restrictTo()。擷取目前分頁時,使用 null 或從目前分頁中的 Element 衍生出的任何 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 就會解決。

如果失敗,Promise 會遭到拒絕。如果對 restrictTo() 的呼叫失敗,可能原因如下:

  • 如果 restrictionTarget 是在擷取畫面以外的分頁中鑄造,(請注意,使用者可以隨時使用「改為分享這個分頁」按鈕,變更要擷取的分頁)。
  • 如果 restrictionTarget 是衍生自已不存在的 Element。
  • 如果曲目有複製版本,(請參閱問題 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 132 以上版本。

安全性和隱私權

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

Chrome 瀏覽器會在擷取的分頁邊緣繪製藍色框線。

示範

您可以執行示範,試用元素擷取功能。

意見回饋

Chrome 團隊和網路標準社群很想聽聽您使用 Element Capture 的體驗。

請說明設計內容

Element Capture 是否有任何不符預期的問題?或者缺少實作構想所需的方法或屬性?對安全模型有任何疑問或意見嗎?

  • GitHub 存放區中提出規格問題,或在現有問題中新增想法。

導入時發生問題嗎?

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

致謝

相片來源:Paul Skorupskas 發表於 Unsplash 網站上