Con la API de Screen Capture, puedes capturar toda la pestaña actual. La API de Element Capture te permite capturar y grabar un elemento HTML específico. Transforma una captura de toda la pestaña en una captura de un subárbol DOM específico, capturando solo los descendientes directos del elemento de destino. En otras palabras, recorta y quita el contenido ocluyente y ocluido.
¿Por qué usar la Captura de elementos?
Tener en cuenta los requisitos de una aplicación de videoconferencia puede ayudarte a comprender en qué situaciones es útil la Captura de elementos. Si tienes una aplicación de videoconferencia que te permite incorporar aplicaciones de terceros en un iframe, es posible que, en ocasiones, quieras capturar ese iframe como un video y transmitirlo a los participantes remotos.
Si llamas a getDisplayMedia()
y permites que el usuario elija la pestaña actual, se transmitirá toda la pestaña actual. Es probable que se les transmita su propio video. Puedes recortarlo con la Captura de región.
Sin embargo, ¿qué sucede si el presentador interactúa con la aplicación de videoconferencia y parte del contenido, como una lista desplegable, se dibuja sobre el contenido que se pretende capturar?
La Captura de región no te ayudaría en este caso. Es posible que parte de la lista desplegable sea visible en las pantallas de los participantes remotos.
El hecho de que la Captura de regiones capture partes de elementos de esta manera (conocido como contenido que oculta) crea varios problemas:
- El contenido que oculta el contenido que el usuario desea compartir.
- El contenido que se oculta puede ser privado (por ejemplo, las notificaciones de chat).
- El contenido que oculta información puede ser confuso. (por ejemplo, un nuevo diseño de la aplicación podría mostrar brevemente los videos de los participantes remotos sobre el objetivo capturado).
La API de Element Capture resuelve todos estos problemas, ya que te permite segmentar el elemento que deseas compartir.
¿Cómo uso la Captura de elementos?
captureTarget
es un elemento de tu página que contiene el contenido que el usuario desea capturar. Supongamos que quieres que la app web de videoconferencia capture captureTarget
y la comparta con participantes remotos. Por lo tanto, obtienes un RestrictionTarget
de captureTarget
. Después de restringir la pista de video con este RestrictionTarget
, los fotogramas de esa pista de video ahora solo consisten en los píxeles que forman parte de captureTarget
y sus descendientes directos del DOM.
Si captureTarget
cambia de tamaño, forma o ubicación, la pista de video lo sigue, sin requerir ninguna entrada adicional de ninguna de las apps web. De manera similar, la oclusión de contenido que aparece, desaparece o se mueve no requiere un tratamiento especial.
Revisa estos pasos nuevamente:
Para comenzar, permite que el usuario capture la pestaña actual.
// Ask the user for permission to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();
Para definir un RestrictionTarget
, llama a RestrictionTarget.fromElement()
con un elemento de tu elección como entrada.
// Associate captureTarget with a new RestrictionTarget
const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);
Luego, llama a restrictTo()
en la pista de video con RestrictionTarget
como entrada. Una vez que se resuelva la última promesa, se restringirán todos los fotogramas posteriores.
// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);
// Enjoy! Transmit remotely.
Análisis detallado
Detección de atributos
Para verificar si RestrictionTarget.fromElement()
es compatible, usa lo siguiente:
if ("RestrictionTarget" in self && "fromElement" in RestrictionTarget) {
// Deriving a restriction target is supported.
}
Deriva un RestrictionTarget
Enfócate en el elemento llamado captureTarget
. Para derivar un RestrictionTarget
de él, llama a RestrictionTarget.fromElement(captureTarget)
. Si se realiza correctamente, la promesa que se devuelve se resolverá con un nuevo objeto RestrictionTarget
. De lo contrario, se rechazará si creaste una cantidad irrazonable de objetos RestrictionTarget
.
const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);
A diferencia de un elemento, un objeto RestrictionTarget
es serializable. Por ejemplo, se puede pasar a otro documento con Window.postMessage()
.
Restringida
Cuando se captura una pestaña, la pista de video expone restrictTo()
. Cuando se captura la pestaña actual, es válido llamar a restrictTo()
con null
o cualquier RestrictionTarget
derivado de un elemento dentro de la pestaña actual.
Las llamadas a restrictTo(restrictionTarget)
mutarán la pista de video en una captura de captureTarget
, como si se dibujara por sí sola, independientemente del resto del DOM. También se capturan los descendientes de captureTarget
; los hermanos de captureTarget
se eliminan de la captura. El resultado es que los fotogramas entregados en la pista aparecen como si se hubieran recortado a los contornos de captureTarget
, y se quita todo el contenido ocluyente y ocluido.
// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);
Las llamadas a restrictTo(null)
revierten el segmento a su estado original.
// Stop restricting.
await track.restrictTo(null);
Si la llamada a restrictTo()
se realiza correctamente, la promesa que se muestra se resuelve cuando se puede garantizar que todos los fotogramas de video posteriores se restringirán a captureTarget
.
Si no se realiza correctamente, se rechaza la promesa. Una llamada a restrictTo()
que no se realice correctamente se debe a uno de los siguientes motivos:
- Si el
restrictionTarget
se acuñó en una pestaña distinta de la que se está capturando. (Ten en cuenta que, con el botón "Compartir esta pestaña en su lugar", los usuarios pueden cambiar la pestaña que se captura en cualquier momento). - Si el
restrictionTarget
se derivó de un elemento que ya no existe. - Si el segmento tiene clones. (consulta el problema 1509418).
- Si la pista actual no es una pista de video de captura propia.
- Si el elemento del que se derivó
restrictionTarget
no es apto para la restricción.
Consideraciones sobre la captura automática
Cuando una app llama a getDisplayMedia()
y el usuario elige capturar la propia pestaña de la app, lo llamamos "captura propia".
El método restrictTo()
se expone en cualquier pista de video de captura de pestañas, no solo para la captura automática. Sin embargo, por el momento, la Captura de elementos solo está habilitada para la captura automática. Por lo tanto, se recomienda verificar si el usuario seleccionó la pestaña actual antes de intentar restringir la pista. Esto se puede lograr con el control de captura. También es posible pedirle al navegador que le sugiera al usuario que realice la captura con preferCurrentTab
.
Transparencia
Los fotogramas de video que obtiene la app a través de getDisplayMedia()
no incluyen un canal alfa. Si una app establece un objetivo de captura parcialmente transparente, quitar el canal alfa tiene algunas consecuencias posibles:
- Es posible que los colores cambien. Es posible que los elementos de destino parcialmente transparentes dibujados sobre un fondo claro se vean más oscuros cuando se quita el canal alfa, y que los dibujados sobre un fondo oscuro se vean más claros.
- Los colores que eran invisibles o imperceptibles para el usuario cuando el canal alfa se configuraba en su máximo, aparecían una vez que se quitaba el canal alfa. Por ejemplo, esto podría generar regiones negras inesperadas en los fotogramas capturados, si las secciones transparentes tuvieran el código RGBA
rgba(0, 0, 0, 0)
.
Objetivos de captura no aptos
Siempre es posible comenzar a restringir un segmento a cualquier destino de captura válido. Sin embargo, no se producirán fotogramas en ciertas condiciones, por ejemplo, si el elemento o un ancestro es display:none
. La justificación general es que la restricción se aplica solo a un elemento que comprende un área rectangular, única, cohesiva y bidimensional, cuyos píxeles se pueden determinar de forma lógica de forma aislada de cualquier elemento superior o hermano.
Una consideración importante para garantizar que el elemento sea apto para la restricción es que debe formar su propio contexto de apilamiento. Para garantizar esto, puedes especificar la propiedad CSS isolation y establecerla en isolate
.
<div id="captureTarget" style="isolation: isolate;"></iframe>
Ten en cuenta que el elemento de destino puede alternar entre ser apto y no apto para la restricción en cualquier momento, por ejemplo, si la app cambia sus propiedades CSS. Depende de la app usar objetivos de captura razonables y evitar cambiar sus propiedades de forma inesperada. Si el elemento de destino deja de ser apto, simplemente no se emitirán fotogramas nuevos en la pista hasta que el elemento de destino vuelva a ser apto para la restricción.
Habilita la captura de elementos
La API de Element Capture está disponible en Chrome para computadoras de escritorio detrás de la marca de Element Capture y se puede habilitar en chrome://flags/#element-capture
.
Esta función también ingresará en una prueba de origen a partir de Chrome 121 para computadoras, lo que permitirá a los desarrolladores habilitar la función para que los visitantes de sus sitios recopilen datos de usuarios reales. Consulta Cómo comenzar a usar las pruebas de origen para obtener más información sobre ellas.
Seguridad y privacidad
Para comprender las compensaciones de seguridad, consulta la sección Consideraciones de privacidad y seguridad de la especificación de Captura de elementos.
El navegador Chrome dibuja un borde azul alrededor de los bordes de las pestañas capturadas.
Demostración
Para jugar con la Captura de elementos, ejecuta la demo en Glitch. Asegúrate de consultar el código fuente.
Comentarios
El equipo de Chrome y la comunidad de estándares web quieren conocer tus experiencias con la Captura de elementos.
Cuéntanos sobre el diseño
¿Hay algo relacionado con la Captura de región 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 tus comentarios 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 de proporcionar instrucciones sencillas para reproducirlo. Glitch es excelente para compartir reproducciones rápidas y fáciles.
Vínculos útiles
Agradecimientos
Foto de Paul Skorupskas en Unsplash