Transmisiones insertables para MediaStreamTrack

El contenido de un MediaStreamTrack se expone como una transmisión que se puede manipular o usar para generar contenido nuevo.

Información general

En el contexto de la API de transmisión y captura de contenido multimedia, la interfaz MediaStreamTrack representa una sola pista multimedia dentro de una transmisión. Por lo general, se trata de pistas de audio o video, pero pueden existir otros tipos de pistas. Los objetos MediaStream constan de cero o más objetos MediaStreamTrack, que representan varias pistas de audio o video. Cada MediaStreamTrack puede tener uno o más canales. El canal representa la unidad más pequeña de una transmisión multimedia, como una señal de audio asociada a una bocina determinada (por ejemplo, izquierda o derecha en una pista de audio estéreo).

¿Qué son las Novedades insertables para MediaStreamTrack?

La idea principal detrás de las transmisiones insertables para MediaStreamTrack es exponer el contenido de una MediaStreamTrack como una colección de transmisiones (como se define en la API de Streams de whatWG). Estas transmisiones se pueden manipular para ingresar componentes nuevos.

Otorgar a los desarrolladores acceso a la transmisión de video o audio de forma directa les permite aplicar modificaciones de forma directa a la transmisión. Por el contrario, para lograr la misma tarea de manipulación de video con métodos tradicionales, los desarrolladores deben usar intermediarios, como los elementos <canvas>. (para obtener detalles sobre este tipo de proceso, consulta, por ejemplo, video + lienzo = magia).

Navegadores compatibles

Las transmisiones insertables de MediaStreamTrack son compatibles con Chrome 94.

Casos de uso

Estos son algunos casos de uso de las transmisiones insertables de MediaStreamTrack:

  • Elementos para videoconferencias, como "sombreros divertidos" o fondos virtuales.
  • Procesamiento de voz, como vocoders de software

Cómo usar transmisiones insertables para MediaStreamTrack

Detección de funciones

Puedes detectar transmisiones que se pueden insertar para la compatibilidad con MediaStreamTrack de la siguiente manera.

if ('MediaStreamTrackProcessor' in window && 'MediaStreamTrackGenerator' in window) {
  // Insertable streams for `MediaStreamTrack` is supported.
}

Conceptos básicos

Las transmisiones insertables de MediaStreamTrack se basan en conceptos propuestos anteriormente por WebCodecs y dividen de forma conceptual el MediaStreamTrack en dos componentes:

  • El MediaStreamTrackProcessor, que consume la fuente de un objeto MediaStreamTrack y genera una transmisión de marcos multimedia, específicamente VideoFrame o AudioFrame. Puedes considerarlo como un receptor de seguimiento que puede exponer los fotogramas sin codificación del segmento como un ReadableStream.
  • El MediaStreamTrackGenerator, que consume una transmisión de marcos multimedia y expone una interfaz MediaStreamTrack. Se puede proporcionar a cualquier receptor, al igual que una pista de getUserMedia(). Toma los fotogramas multimedia como entrada.

MediaStreamTrackProcessor

Un objeto MediaStreamTrackProcessor expone una propiedad: readable. Permite leer los fotogramas de MediaStreamTrack. Si la pista es de video, los fragmentos leídos de readable serán objetos VideoFrame. Si la pista es una pista de audio, los fragmentos leídos de readable serán objetos AudioFrame.

MediaStreamTrackGenerator

Del mismo modo, un objeto MediaStreamTrackGenerator expone una propiedad, writable, que es un WritableStream que permite escribir fotogramas multimedia en MediaStreamTrackGenerator, que es un MediaStreamTrack. Si el atributo kind es "audio", la transmisión acepta objetos AudioFrame y falla con cualquier otro tipo. Si el tipo es "video", la transmisión acepta objetos VideoFrame y falla con cualquier otro tipo. Cuando se escribe un fotograma en writable, se invoca automáticamente el método close() del fotograma, por lo que ya no se puede acceder a los recursos multimedia desde JavaScript.

Un MediaStreamTrackGenerator es un segmento para el que se puede implementar una fuente personalizada escribiendo fotogramas multimedia en su campo writable.

Resumen

La idea central es crear una cadena de procesamiento de la siguiente manera:

Seguimiento de la plataforma → Procesador → Transformación → Generador → Receptores de la plataforma

En el siguiente ejemplo se ilustra esta cadena de una aplicación de escaneo de códigos de barras que destaca un código de barras detectado en una transmisión de video en vivo.

const stream = await getUserMedia({ video: true });
const videoTrack = stream.getVideoTracks()[0];

const trackProcessor = new MediaStreamTrackProcessor({ track: videoTrack });
const trackGenerator = new MediaStreamTrackGenerator({ kind: 'video' });

const transformer = new TransformStream({
  async transform(videoFrame, controller) {
    const barcodes = await detectBarcodes(videoFrame);
    const newFrame = highlightBarcodes(videoFrame, barcodes);
    videoFrame.close();
    controller.enqueue(newFrame);
  },
});

trackProcessor.readable.pipeThrough(transformer).pipeTo(trackGenerator.writable);

const videoBefore = document.getElementById('video-before');
const videoAfter = document.getElementById('video-after');
videoBefore.srcObject = stream;
const streamAfter = new MediaStream([trackGenerator]);
videoAfter.srcObject = streamAfter;

Demostración

Puedes ver la demostración del escáner de código QR de la sección anterior en acción en un navegador para computadoras o dispositivos móviles. Mantén un código QR frente a la cámara, y la app lo detectará y lo destacará. Puedes ver el código fuente de la aplicación en Glitch.

Escáner de códigos QR que se ejecuta en la pestaña del navegador para computadoras que muestra un código QR detectado y destacado en el teléfono que el usuario sostiene frente a la cámara de la laptop.

Consideraciones de seguridad y privacidad

La seguridad de esta API se basa en mecanismos existentes en la plataforma web. A medida que los datos se exponen mediante las interfaces VideoFrame y AudioFrame, se aplican las reglas de esas interfaces para abordar los datos afectados por el origen. Por ejemplo, no se puede acceder a los datos de los recursos de origen cruzado debido a restricciones existentes para el acceso a esos recursos (p.ej., no es posible acceder a los píxeles de una imagen o un elemento de video de origen cruzado). Además, el acceso a los datos de contenido multimedia desde cámaras, micrófonos o pantallas está sujeto a la autorización del usuario. Los datos multimedia que expone esta API ya están disponibles a través de otras APIs.

Comentarios

El equipo de Chromium quiere conocer tu experiencia con las transmisiones insertables de MediaStreamTrack.

Cuéntanos sobre el diseño de la API

¿Hay algo acerca de la API 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 especificaciones en el repositorio de GitHub correspondiente o agrega tus ideas a un problema existente.

Informar un problema con la implementación

¿Encontraste un error en la implementación de Chromium? ¿O la implementación es diferente de la especificación? Informa un error en new.crbug.com. Asegúrate de incluir tantos detalles como puedas, además de instrucciones simples para reproducir el error, y, luego, ingresa Blink>MediaStream en el cuadro Componentes. Glitch funciona muy bien para compartir repros rápidos y fáciles.

Muestra compatibilidad con la API

¿Planeas usar transmisiones insertables para MediaStreamTrack? Tu asistencia pública ayuda al equipo de Chromium a priorizar funciones y les muestra a otros proveedores de navegadores la importancia de admitirlas.

Envía un tweet a @ChromiumDev con el hashtag #InsertableStreams y cuéntanos dónde y cómo lo usas.

Agradecimientos

Harald Alvestrand y Guido Urdaneta escribieron las transmisiones insertables para la especificación de MediaStreamTrack. Este artículo fue revisado por Harald Alvestrand, Joe Medley, Ben Wagner, Huib Kleinhout y François Beaufort. Hero image de Chris Montgomery en Unsplash.