Screen Capture API 可讓使用者選取要擷取做為媒體串流的分頁、視窗或螢幕畫面。然後錄製這部直播節目,或透過網路與他人分享。本文件說明了條件焦點,這是一種機制,可讓網路應用程式控制擷取開始時,擷取的分頁或視窗是否會聚焦,或是擷取頁面是否會保持聚焦。
瀏覽器支援
Chrome 109 以上版本才有條件聚焦功能。
背景
當網頁應用程式開始擷取分頁或視窗時,瀏覽器必須做出決定:應將擷取的畫面移至前景,還是讓擷取頁面保持焦點?答案取決於呼叫 getDisplayMedia()
的原因,以及使用者最終選取的介面。
請考慮以下假設的視訊會議網路應用程式。透過讀取 track.getSettings().displaySurface
,並可能檢查 Capture Handle,視訊會議網路應用程式就能瞭解使用者選擇分享的內容。然後執行下列步驟:
- 如果擷取的分頁或視窗可透過遠端控制,請將焦點放在視訊會議上。
- 否則,請將焦點移至擷取的分頁或視窗。
在上例中,如果分享投影片,視訊會議網頁應用程式會保留焦點,讓使用者可遠端翻閱投影片;但如果使用者選擇分享文字編輯器,視訊會議網頁應用程式會立即將焦點切換至已擷取的分頁或視窗。
使用條件聚焦 API
例項化 CaptureController
,並將其傳遞至 getDisplayMedia()
。在傳回的 getDiplayMedia()
承諾解析後立即呼叫 setFocusBehavior()
,即可控制擷取的分頁或視窗是否會聚焦。只有在使用者分享分頁或視窗時,才能執行這項操作。
const controller = new CaptureController();
// Prompt the user to share a tab, a window or a screen.
const stream =
await navigator.mediaDevices.getDisplayMedia({ controller });
const [track] = stream.getVideoTracks();
const displaySurface = track.getSettings().displaySurface;
if (displaySurface == "browser") {
// Focus the captured tab.
controller.setFocusBehavior("focus-captured-surface");
} else if (displaySurface == "window") {
// Do not move focus to the captured window.
// Keep the capturing page focused.
controller.setFocusBehavior("focus-capturing-application");
}
在決定是否要聚焦時,可以考慮擷取句柄。
// Retain focus if capturing a tab dialed to example.com.
// Focus anything else.
const origin = track.getCaptureHandle().origin;
if (displaySurface == "browser" && origin == "https://example.com") {
controller.setFocusBehavior("focus-capturing-application");
} else if (displaySurface != "monitor") {
controller.setFocusBehavior("focus-captured-surface");
}
甚至可以決定是否要在呼叫 getDisplayMedia()
之前進行聚焦。
// Focus the captured tab or window when capture starts.
const controller = new CaptureController();
controller.setFocusBehavior("focus-captured-surface");
// Prompt the user to share their screen.
const stream =
await navigator.mediaDevices.getDisplayMedia({ controller });
您可以在承諾解析前任意呼叫 setFocusBehavior()
,或是在承諾解析後最多呼叫一次。最後一次叫用會覆寫先前的所有叫用。
更精確地說:
- getDisplayMedia()
傳回的承諾會在微型工作項中解析。在微型工作完成後呼叫 setFocusBehavior()
會擲回錯誤。- 在開始擷取後超過一秒鐘才呼叫 setFocusBehavior()
會導致無操作。
也就是說,以下兩個程式碼片段都會失敗:
// Prompt the user to share their screen.
const stream =
await navigator.mediaDevices.getDisplayMedia({ controller });
// Too late, because it follows the completion of the task
// on which the getDisplayMedia() promise resolved.
// This will throw.
setTimeout(() => {
controller.setFocusBehavior("focus-captured-surface");
});
// Prompt the user to share their screen.
const stream =
await navigator.mediaDevices.getDisplayMedia({ controller });
const start = new Date();
while (new Date() - start <= 1000) {
// Idle for ≈1s.
}
// Because too much time has elapsed, the browser will have
// already decided whether to focus.
// This fails silently.
controller.setFocusBehavior("focus-captured-surface");
在下列情況下,呼叫 setFocusBehavior()
也會擲回:
getDisplayMedia()
傳回串流的視訊軌並非「直播」。- 之後,如果使用者分享某個畫面 (而非分頁或視窗),則
getDisplayMedia()
傳回的承諾都會解析。
範例
您可以在 Glitch 上執行示範,體驗條件焦點功能。請務必查看原始碼。
特徵偵測
如要確認是否支援 CaptureController.setFocusBehavior()
,請使用:
if (
"CaptureController" in window &&
"setFocusBehavior" in CaptureController.prototype
) {
// CaptureController.setFocusBehavior() is supported.
}
意見回饋
Chrome 團隊和網路標準社群想瞭解你的條件式焦點功能使用體驗。
請與我們分享設計
有任何條件式專注模式無法正常運作的情況嗎?或者,您是否缺少實作想法所需的方法或屬性?對安全性模型有任何疑問或意見嗎?
- 在 GitHub 存放區中提出規格問題,或在現有問題中加入您的想法。
導入時發生問題?
您發現 Chrome 實作錯誤嗎?或者實作方式與規格不同?
- 請前往 https://new.crbug.com 提交錯誤。請務必提供盡可能多的詳細資料,以及重現問題的簡單操作說明。Glitch 適合用於分享程式碼。
顯示支援
您是否打算使用條件焦點?你的公開聲援有助於 Chrome 團隊決定功能的優先順序,並向其他瀏覽器供應商顯示支援這些功能的重要性。
請發推文給 @ChromiumDev,告訴我們你在哪裡使用這項功能,以及使用方式。
實用連結
特別銘謝
主頁橫幅圖片由 Elena Taranenko 製作。
感謝 Rachel Andrew 審查本文。