Ya es posible compartir pestañas, ventanas y pantallas en la plataforma web con la API de Screen Capture. Cuando una app web llama a getDisplayMedia()
, Chrome le solicita al usuario que comparta una pestaña, una ventana o una pantalla con la app web como un video de MediaStreamTrack
.
Muchas apps web que usan getDisplayMedia()
muestran al usuario una vista previa en video de la superficie capturada. Por ejemplo, las apps de videoconferencias suelen transmitir este video a los usuarios remotos y, al mismo tiempo, renderizarlo en un HTMLVideoElement
local para que el usuario local vea constantemente una vista previa de lo que está compartiendo.
En esta documentación, se presenta la nueva API de Captured Surface Control en Chrome, que permite que tu app web se desplace por una pestaña capturada, así como leer y escribir el nivel de zoom de una pestaña capturada.
¿Por qué usar el Control de superficie capturada?
Todas las apps para videoconferencias tienen el mismo inconveniente. Si el usuario desea interactuar con una pestaña o ventana capturada, debe cambiar a esa superficie, lo que lo aleja de la app de videoconferencias. Esto presenta algunos desafíos:
- El usuario no puede ver la app capturada y las transmisiones de video de los usuarios remotos al mismo tiempo, a menos que use la función Pantalla en pantalla o ventanas separadas una al lado de la otra para la pestaña de la videoconferencia y la pestaña compartida. En una pantalla más pequeña, esto podría ser difícil.
- El usuario debe cambiar constantemente entre la app de videoconferencias y la superficie capturada.
- El usuario pierde el acceso a los controles que expone la app de videoconferencias mientras no la usa, por ejemplo, una app de chat integrada, reacciones con emojis, notificaciones sobre usuarios que solicitan unirse a la llamada, controles de diseño y multimedia, y otras funciones útiles de videoconferencias.
- El presentador no puede delegar el control a los participantes remotos. Esto lleva a la situación demasiado familiar en la que los usuarios remotos le piden al presentador que cambie la diapositiva, se desplace un poco hacia arriba y hacia abajo, o ajuste el nivel de zoom.
La API de Captured Surface Control aborda estos problemas.
¿Cómo uso el Control de superficie capturada?
Para usar el Control de superficie capturada correctamente, se requieren algunos pasos, como capturar explícitamente una pestaña del navegador y obtener permiso del usuario antes de poder desplazarse y hacer zoom en la pestaña capturada.
Cómo capturar una pestaña del navegador
Comienza por solicitarle al usuario que elija una superficie para compartir con getDisplayMedia()
y, en el proceso, asocia un objeto CaptureController
con la sesión de captura. Usaremos ese objeto para controlar la superficie capturada en breve.
const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });
A continuación, genera una vista previa local de la superficie capturada en forma de un elemento <video>
:
const previewTile = document.querySelector('video');
previewTile.srcObject = stream;
Si el usuario elige compartir una ventana o una pantalla, eso está fuera del alcance por el momento, pero si elige compartir una pestaña, podemos continuar.
const [track] = stream.getVideoTracks();
if (track.getSettings().displaySurface !== 'browser') {
// Bail out early if the user didn't pick a tab.
return;
}
Mensaje de permiso
La primera invocación de forwardWheel()
, increaseZoomLevel()
, decreaseZoomLevel()
o resetZoomLevel()
en un objeto CaptureController
determinado genera un mensaje de permiso. Si el usuario otorga el permiso, se permitirán más invocaciones de estos métodos.
Se requiere un gesto del usuario para mostrarle un mensaje de permiso, por lo que la app solo debe llamar a los métodos mencionados si ya tiene el permiso o en respuesta a un gesto del usuario, como un click
en un botón relevante de la app web.
Desplazamiento
Con forwardWheel()
, una app de captura puede reenviar eventos de rueda desde un elemento fuente dentro de la propia app de captura al viewport de la pestaña capturada. Estos eventos son indistinguibles para la app capturada de la interacción directa del usuario.
Suponiendo que la app de captura emplea un elemento <video>
llamado "previewTile"
, el siguiente código muestra cómo retransmitir eventos de la rueda de desplazamiento a la pestaña capturada:
const previewTile = document.querySelector('video');
try {
// Relay the user's action to the captured tab.
await controller.forwardWheel(previewTile);
} catch (error) {
// Inspect the error.
// ...
}
El método forwardWheel()
toma una sola entrada que puede ser una de las siguientes:
- Es un elemento HTML desde el que se reenviarán los eventos de rueda a la pestaña capturada.
null
, lo que indica que se debe detener el reenvío.
Una llamada exitosa a forwardWheel()
anula las llamadas anteriores.
La promesa que devuelve forwardWheel()
se puede rechazar en los siguientes casos:
- Si la sesión de captura aún no comenzó o ya se detuvo.
- Si el usuario no otorgó el permiso pertinente
Zoom
La interacción con el nivel de zoom de la pestaña capturada se realiza a través de las siguientes superficies de la API de CaptureController
:
getSupportedZoomLevels()
Este método devuelve una lista de los niveles de zoom que admite el navegador para el tipo de superficie que se captura. Los valores de esta lista se representan como un porcentaje en relación con el "nivel de zoom predeterminado", que se define como el 100%. La lista aumenta de forma monótona y contiene el valor 100.
Este método solo se puede llamar para los tipos de superficies de visualización admitidos, que, por el momento, solo son pestañas.
Se puede llamar a controller.getSupportedZoomLevels()
si se cumplen las siguientes condiciones:
controller
está asociado con una captura activa.- La captura es de una pestaña.
De lo contrario, se generará un error.
El permiso "captured-surface-control"
no es obligatorio para llamar a este método.
zoomLevel
Este atributo de solo lectura contiene el nivel de zoom actual de la pestaña capturada. Es un atributo que acepta valores nulos y contiene null
si el tipo de superficie capturada no tiene una definición significativa del nivel de zoom. Por el momento, el nivel de zoom solo se define para las pestañas, no para las ventanas ni las pantallas.
Una vez que finalice la captura, el atributo contendrá el último valor del nivel de zoom.
El permiso "captured-surface-control"
no es obligatorio para leer este atributo.
onzoomlevelchange
Este controlador de eventos facilita la detección de cambios en el nivel de zoom de la pestaña capturada. Estos eventos pueden ocurrir de las siguientes maneras:
- Cuando el usuario interactúa con el navegador para cambiar manualmente el nivel de zoom de la pestaña capturada.
- En respuesta a las llamadas de la app de captura a los métodos de configuración del zoom (que se describen a continuación).
El permiso "captured-surface-control"
no es obligatorio para leer este atributo.
increaseZoomLevel()
, decreaseZoomLevel()
y resetZoomLevel()
Estos métodos permiten manipular el nivel de zoom de la pestaña capturada.
increaseZoomLevel()
y decreaseZoomLevel()
cambian el nivel de zoom al siguiente o anterior, respectivamente, según el orden que devuelve getSupportedZoomLevels()
. resetZoomLevel()
establece el valor en 100.
Se requiere el permiso "captured-surface-control"
para llamar a estos métodos. Si la app de captura no tiene este permiso, se le pedirá al usuario que lo otorgue o lo rechace.
Todos estos métodos devuelven una promesa que se resuelve si la llamada se realiza correctamente y se rechaza en caso contrario. Entre las posibles causas de rechazo, se incluyen las siguientes:
- Faltan permisos.
- Se llama antes de que comience la captura.
- Se llama después de que finaliza la captura.
- Se llama en un
controller
asociado con una captura de un tipo de superficie de visualización no admitido. (es decir, cualquier cosa que no sea la captura de pestañas). - Se intenta aumentar o disminuir el valor más allá del valor máximo o mínimo, respectivamente.
En particular, se recomienda evitar llamar a decreaseZoomLevel()
si controller.zoomLevel == controller.getSupportedZoomLevels().at(0)
y proteger las llamadas a increaseZoomLevel()
de manera similar con .at(-1)
.
En el siguiente ejemplo, se muestra cómo permitir que el usuario aumente el nivel de zoom de una pestaña capturada directamente desde la app de captura:
const zoomIncreaseButton = document.getElementById('zoomInButton');
zoomIncreaseButton.addEventListener('click', async (event) => {
if (controller.zoomLevel >= controller.getSupportedZoomLevels().at(-1)) {
return;
}
try {
await controller.increaseZoomLevel();
} catch (error) {
// Inspect the error.
// ...
}
});
En el siguiente ejemplo, se muestra cómo reaccionar a los cambios en el nivel de zoom de una pestaña capturada:
controller.addEventListener('zoomlevelchange', (event) => {
const zoomLevelLabel = document.querySelector('#zoomLevelLabel');
zoomLevelLabel.textContent = `${controller.zoomLevel}%`;
});
Detección de características
Para verificar si se admiten las APIs de Captured Surface Control, usa lo siguiente:
if (!!window.CaptureController?.prototype.forwardWheel) {
// CaptureController forwardWheel() is supported.
}
También es posible usar cualquiera de las otras plataformas de la API de Captured Surface Control, como increaseZoomLevel
o decreaseZoomLevel
, o incluso verificarlas todas.
Navegadores compatibles
El Control de superficie capturado está disponible a partir de Chrome 136 solo en computadoras de escritorio.
Seguridad y privacidad
La política de permisos de "captured-surface-control"
te permite administrar cómo tu app de captura y los iframes de terceros incorporados tienen acceso a Captured Surface Control. Para comprender las compensaciones de seguridad, consulta la sección Consideraciones sobre la seguridad y la privacidad del explicador de Captured Surface Control.
Demostración
Puedes probar el control de superficie capturada ejecutando la demostración.
Comentarios
Al equipo de Chrome y a la comunidad de estándares web les interesa conocer tu experiencia con Captured Surface Control.
Cuéntanos sobre el diseño
¿Hay algo sobre la captura de superficie capturada 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, así como instrucciones para reproducir el error.