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

François Beaufort
François Beaufort

Browser Support

  • Chrome: 109.
  • Edge: 109.
  • Firefox: not supported.
  • Safari: not supported.

Source

使用者可以透過螢幕畫面擷取 API 選取要擷取的分頁、視窗或螢幕畫面,並以媒體串流的形式擷取。然後透過網路錄製或與他人分享這項串流內容。這份文件將介紹「條件式焦點」,這項機制可供網路應用程式控管擷取作業開始時,要將焦點放在擷取的分頁或視窗,還是擷取網頁。

瀏覽器支援

條件式焦點自 Chrome 109 版起開放使用。

背景

網頁應用程式開始擷取分頁或視窗時,瀏覽器會面臨決策:是否要將擷取的表面帶到最前端,還是要讓擷取頁面保持焦點?答案取決於通話原因 getDisplayMedia(),以及使用者最終選取的介面。

假設有一個虛構的視訊會議網頁應用程式。視訊會議網頁應用程式可以讀取 track.getSettings().displaySurface,並可能檢查 Capture Handle,瞭解使用者選擇分享的內容。然後執行下列步驟:

  • 如果可以遠端控制擷取的索引標籤或視窗,請將視訊會議設為焦點。
  • 否則,請將焦點移至擷取的分頁或視窗。

以上述範例來說,如果使用者分享投影片,視訊會議網路應用程式就會保留焦點,讓使用者遠端瀏覽投影片;但如果使用者選擇分享文字編輯器,視訊會議網路應用程式就會立即將焦點切換至擷取的分頁或視窗。

使用 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 }); 

您可以在 Promise 解決前任意次數呼叫 setFocusBehavior(),或在 Promise 解決後立即呼叫一次。最後一次叫用會覆寫先前所有叫用。

更精確地說: - 傳回的 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() 傳回的串流影片軌不是「live」
  • getDisplayMedia() 傳回的 Promise 解析後,如果使用者分享的是螢幕 (而非分頁或視窗)。

範例

您可以執行示範,試用條件式焦點。

特徵偵測

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

if (   "CaptureController" in window &&   "setFocusBehavior" in CaptureController.prototype ) {   // CaptureController.setFocusBehavior() is supported. } 

意見回饋

Chrome 團隊和網路標準社群很想瞭解您使用條件式焦點的體驗。

請說明設計內容

條件式焦點功能是否無法正常運作?或者缺少實作構想所需的方法或屬性?對安全模型有任何疑問或意見嗎?

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

導入時發生問題嗎?

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

  • 前往 https://new.crbug.com 回報錯誤。請務必盡可能提供詳細資料,以及重現問題的簡單操作說明。

顯示支援

您是否打算使用條件式焦點?您的公開支持有助於 Chrome 團隊排定功能優先順序,並向其他瀏覽器供應商說明支援這些功能的重要性。

請傳送推文至 @ChromiumDev,告訴我們您在何處使用這項功能,以及使用方式。

特別銘謝

主頁橫幅圖片由 Elena Taranenko 提供。

感謝 Rachel Andrew 審查本文。