La API de Captura de pantalla permite que el usuario seleccione una pestaña, una ventana o una pantalla para capturarla como transmisión de contenido multimedia. Luego, 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 ventana capturada se enfocará 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.
Segundo plano
Cuando una aplicación web comienza a capturar una pestaña o una ventana, el navegador se enfrenta a una decisión: ¿la superficie capturada debe aparecer en primer plano o debe permanecer enfocada la página de captura? La respuesta depende del motivo por el que se llama a getDisplayMedia()
y de la plataforma que el usuario termina seleccionando.
Considera usar una app web de videoconferencias hipotética. Si lees track.getSettings().displaySurface
y, potencialmente, examinas el controlador de captura, la app web de videoconferencias puede comprender lo que el usuario eligió compartir. Luego:
- Si la pestaña o ventana capturada se puede controlar de forma remota, mantén la videoconferencia en foco.
- De lo contrario, enfoca la pestaña o ventana capturada.
En el ejemplo anterior, la aplicación web de videoconferencia retendría el enfoque si compartiera una presentación de diapositivas, lo que permitiría al usuario pasar las diapositivas de forma remota; pero si el usuario eligió compartir un editor de texto, la aplicación web de videoconferencia cambiará de inmediato el enfoque a la pestaña o ventana capturada.
Usa la API de enfoque condicional
Crea una instancia de CaptureController
y pásala a getDisplayMedia()
. Si llamas a setFocusBehavior()
inmediatamente después de que se resuelva la promesa que muestra getDiplayMedia()
, puedes controlar si se enfocará o no la pestaña o ventana capturada. 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");
}
Para decidir si te enfocarás, es posible tener en cuenta el identificador 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 enfocarse 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()
de manera arbitraria muchas veces antes de que se resuelva la promesa o, como máximo, una vez inmediatamente después de que se resuelva. La última anulación anula todas las invocaciones anteriores.
Más precisamente:
- La promesa getDisplayMedia()
que se muestra se resuelve en una microtarea. Si llamas a setFocusBehavior()
después de que se completa esa microtarea, se muestra un error.
- Llamar a setFocusBehavior()
más de un segundo después de que comienza la captura no realiza ninguna acción.
Es decir, fallarán los siguientes fragmentos:
// 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");
Las llamadas a setFocusBehavior()
también arrojan errores en los siguientes casos:
- la pista de video de la transmisión que muestra
getDisplayMedia()
no es "en vivo". - después de que se resuelva la promesa que devuelve
getDisplayMedia()
, si el usuario compartió una pantalla (no una pestaña ni una ventana).
Muestra
Para experimentar con el enfoque condicional, ejecuta la demo en Glitch. Asegúrate de consultar el código fuente.
Detección de atributos
Para verificar si CaptureController.setFocusBehavior()
es compatible, 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 tus experiencias con el enfoque condicional.
Cuéntanos sobre el diseño
¿Hay algo en el enfoque condicional que no funciona como esperabas? ¿O faltan métodos o propiedades que necesites 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 tus comentarios a un problema existente.
¿Tiene 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 de proporcionar instrucciones sencillas para reproducirlo. Glitch funciona bien para compartir código.
Expresar apoyo
¿Planeas usar el enfoque condicional? Tu asistencia pública ayuda al equipo de Chrome a priorizar funciones y les muestra a otros proveedores de navegadores la importancia de brindar compatibilidad con ellas.
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.