La API de Screen Capture permite que el usuario seleccione una pestaña, una ventana o una pantalla para capturar como una transmisión de medios. Luego, esta transmisión se puede grabar o compartir con otras personas a través de la red. En esta documentación, se presenta el enfoque condicional, un mecanismo para que las apps web controlen si la pestaña o la ventana capturadas se enfocarán cuando comience la captura, o si la página de captura permanecerá enfocada.
Navegadores compatibles
El Enfoque condicional está disponible a partir de Chrome 109.
Fondo
Cuando una app web comienza a capturar una pestaña o una ventana, el navegador debe tomar una decisión: ¿Se debe llevar la superficie capturada al primer plano o se debe mantener el enfoque en la página de captura? La respuesta depende del motivo de la llamada a getDisplayMedia()
y de la plataforma que el usuario termina seleccionando.
Considera una app web de videoconferencias hipotética. Al leer track.getSettings().displaySurface
y, posiblemente, examinar el controlador de captura, la app web de videoconferencias puede comprender qué eligió compartir el usuario. Luego:
- Si la pestaña o la ventana capturada se pueden controlar de forma remota, mantén el enfoque en la videoconferencia.
- De lo contrario, enfoca la pestaña o la ventana capturada.
En el ejemplo anterior, la app web de videoconferencias mantendría el enfoque si se compartiera una presentación de diapositivas, lo que permitiría al usuario pasar las diapositivas de forma remota. Sin embargo, si el usuario eligiera compartir un editor de texto, la app web de videoconferencias cambiaría inmediatamente el enfoque a la pestaña o ventana capturada.
Cómo usar la API de Conditional Focus
Crea una instancia de CaptureController
y pásala a getDisplayMedia()
. Si llamas a setFocusBehavior()
inmediatamente después de que se resuelva la promesa que devolvió getDiplayMedia()
, puedes controlar si la pestaña o la ventana capturadas se enfocarán o no. Esto solo se puede hacer si el usuario compartió una pestaña o una ventana.
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"); }
Cuando decidas si enfocar o no, puedes tener en cuenta el control de captura.
// 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"); }
Incluso es posible decidir si se debe enfocar antes de llamar a 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 });
Puedes llamar a setFocusBehavior()
una cantidad arbitraria de veces antes de que se resuelva la promesa, o como máximo una vez inmediatamente después de que se resuelva la promesa. La última invocación anula todas las anteriores.
Más precisamente: - La promesa devuelta por getDisplayMedia()
se resuelve en una microtarea. Llamar a setFocusBehavior()
después de que se complete esa microtarea arroja un error. - Llamar a setFocusBehavior()
más de un segundo después de que se inicia la captura es una no-op.
Es decir, ambos fragmentos siguientes fallarán:
// 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");
Llamar a setFocusBehavior()
también arroja una excepción en los siguientes casos:
- La pista de video de la transmisión que devuelve
getDisplayMedia()
no es "en vivo". - Después de que se resuelva la promesa devuelta por
getDisplayMedia()
, si el usuario compartió una pantalla (no una pestaña ni una ventana).
Muestra
Puedes probar el enfoque condicional ejecutando la demostración.
Detección de características
Para verificar si se admite CaptureController.setFocusBehavior()
, usa lo siguiente:
if ( "CaptureController" in window && "setFocusBehavior" in CaptureController.prototype ) { // CaptureController.setFocusBehavior() is supported. }
Comentarios
El equipo de Chrome y la comunidad de estándares web quieren conocer tu experiencia con el enfoque condicional.
Cuéntanos sobre el diseño
¿Hay algo sobre el Enfoque condicional que no funciona como esperabas? ¿O faltan métodos o propiedades que necesitas para implementar tu idea? ¿Tienes alguna pregunta o comentario sobre el modelo de seguridad?
- Informa un problema de especificación en el repositorio de GitHub o agrega tu opinión a un problema existente.
¿Tienes problemas con la implementación?
¿Encontraste un error en la implementación de Chrome? ¿O la implementación es diferente de la especificación?
- Informa un error en https://new.crbug.com. Asegúrate de incluir tantos detalles como sea posible y sencillas instrucciones para reproducir el error.
Mostrar apoyo
¿Planeas usar el Enfoque condicional? Tu apoyo público ayuda al equipo de Chrome a priorizar funciones y muestra a otros proveedores de navegadores lo importante que es admitirlas.
Envía un tweet a @ChromiumDev y cuéntanos dónde y cómo lo usas.
Vínculos útiles
Agradecimientos
Imagen hero de Elena Taranenko.
Gracias a Rachel Andrew por revisar este artículo.