利用條件式聚焦,提升分享螢幕畫面的效果

法蘭索瓦博福
François Beaufort
艾倫 (Elad Alon)
Elad Alon

瀏覽器支援

  • 109
  • 109
  • x
  • x

資料來源

Screen Capture API 可讓使用者選取分頁、視窗或螢幕畫面,做為媒體串流擷取。然後,你也可以錄製這個直播,或透過網路與他人分享。本文件將介紹條件式焦點,一種網頁應用程式機制,可在開始擷取時控制已擷取的分頁或視窗,或擷取網頁是否持續聚焦。

瀏覽器支援

條件式焦點功能自 Chrome 109 起。

背景

當網頁應用程式開始擷取分頁或視窗時,瀏覽器會面臨選擇:應將擷取的介面移至最前面,還是保持擷取網頁聚焦?答案取決於呼叫 getDisplayMedia() 的原因,且使用者會在介面上選取。

假設使用假想的視訊會議網頁應用程式。閱讀 track.getSettings().displaySurface 並檢查拍攝控制代碼後,視訊會議網頁應用程式就能瞭解使用者選擇分享的內容。然後執行下列步驟:

  • 如果拍攝的分頁或視窗可以遠端操控,請讓視訊會議對焦。
  • 否則,請將焦點移到原本擷取的分頁或視窗。

在上例中,如果視訊會議網頁應用程式分享簡報內容,以便使用者從遠端翻閱投影片,但是使用者選擇分享文字編輯器時,視訊會議網頁應用程式就會立即將焦點切換至已擷取的分頁或視窗。

使用 Conditional Focus API

CaptureController 例項化,並傳遞至 getDisplayMedia()。在 getDiplayMedia() 傳回的 promise 解析後立即呼叫 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() 傳回的 promise 可在微工作上解析。在該微工作完成後呼叫 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() 傳回的 promise 後,則為使用者分享螢幕 (而非分頁或視窗) 後。

範例

只要對 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 協助審查這篇文章。