Streams inseríveis para MediaStreamTrack

O conteúdo de um MediaStreamTrack é exposto como um stream que pode ser manipulado ou usado para gerar novo conteúdo.

Contexto

No contexto da API Media Capture and Streams, a interface MediaStreamTrack representa uma única faixa de mídia em um stream. Normalmente, são faixas de áudio ou vídeo, mas outros tipos de faixa podem existir. Os objetos MediaStream consistem em zero ou mais objetos MediaStreamTrack, que representam várias faixas de áudio ou vídeo. Cada MediaStreamTrack pode ter um ou mais canais. O canal representa a menor unidade de um fluxo de mídia, como um sinal de áudio associado a um determinado alto-falante, como esquerda ou direita em uma faixa de áudio estéreo.

O que são transmissões inseríveis para MediaStreamTrack?

A ideia principal por trás dos streams inseríveis para MediaStreamTrack é expor o conteúdo de um MediaStreamTrack como uma coleção de streams, conforme definido pela API WhatWGs. Essas transmissões podem ser manipuladas para introduzir novos componentes.

Ao conceder acesso direto ao stream de vídeo (ou áudio), os desenvolvedores podem aplicar modificações diretamente ao stream. Por outro lado, para realizar a mesma tarefa de manipulação de vídeo com métodos tradicionais, os desenvolvedores precisam usar intermediários, como elementos <canvas>. Para mais detalhes sobre esse tipo de processo, consulte, por exemplo, vídeo + tela = magia.

Suporte ao navegador

Os fluxos inseríveis para MediaStreamTrack têm suporte no Chrome 94.

Casos de uso

Os casos de uso para streams inseríveis para MediaStreamTrack incluem, entre outros:

  • gadgets de videoconferência, como "chapéus engraçados" ou planos de fundo virtuais.
  • Processamento de voz, como vocoders de software.

Como usar fluxos inseríveis para MediaStreamTrack

Detecção de recursos

É possível detectar streams inseríveis com suporte a MediaStreamTrack da seguinte maneira:

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

Principais conceitos

Os streams inseríveis para MediaStreamTrack se baseiam em conceitos previamente propostos por WebCodecs e dividem conceitualmente o MediaStreamTrack em dois componentes:

  • O MediaStreamTrackProcessor, que consome a origem de um objeto MediaStreamTrack e gera um stream de frames de mídia, especificamente objetos VideoFrame ou AudioFrame). Pense nisso como um coletor de faixa que pode expor os frames não codificados da faixa como um ReadableStream.
  • O MediaStreamTrackGenerator, que consome um stream de frames de mídia e expõe uma interface MediaStreamTrack. Ele pode ser fornecido para qualquer sink, assim como uma faixa de getUserMedia(). Ele usa frames de mídia como entrada.

O MediaStreamTrackProcessor

Um objeto MediaStreamTrackProcessor expõe uma propriedade, readable. Ele permite a leitura dos frames do MediaStreamTrack. Se a faixa for uma faixa de vídeo, os blocos lidos de readable serão objetos VideoFrame. Se for uma faixa de áudio, os blocos lidos de readable serão objetos AudioFrame.

O MediaStreamTrackGenerator

Um objeto MediaStreamTrackGenerator também expõe uma propriedade, writable, que é um WritableStream que permite gravar frames de mídia no MediaStreamTrackGenerator, que é um MediaStreamTrack. Se o atributo kind for "audio", a transmissão vai aceitar objetos AudioFrame e falhar com qualquer outro tipo. Se o tipo for "video", a transmissão vai aceitar objetos VideoFrame e falhar com qualquer outro tipo. Quando um frame é gravado em writable, o método close() do frame é invocado automaticamente para que os recursos de mídia não sejam mais acessíveis pelo JavaScript.

Uma MediaStreamTrackGenerator é uma faixa em que uma fonte personalizada pode ser implementada gravando frames de mídia no campo writable.

Resumo geral

A ideia principal é criar uma cadeia de processamento da seguinte maneira:

Plataforma Track → Processador → Transformação → Gerador → Sinks de plataforma

O exemplo abaixo ilustra essa cadeia para um aplicativo de leitor de código de barras que destaca o código detectado em uma transmissão de vídeo ao 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;

Demonstração

Veja a demonstração do leitor de QR code da seção acima em ação em um navegador para computadores ou dispositivos móveis. Segure um código QR na frente da câmera. O app vai detectá-lo e destacá-lo. Confira o código-fonte do aplicativo no Glitch.

Leitor de código QR em execução na guia do navegador da área de trabalho mostrando um código QR detectado e destacado no smartphone que o usuário segura na frente da câmera do laptop.

Considerações de segurança e privacidade

A segurança dessa API depende dos mecanismos existentes na plataforma Web. Como os dados são expostos usando as interfaces VideoFrame e AudioFrame, as regras dessas interfaces para lidar com dados corrompidos pela origem são aplicadas. Por exemplo, os dados de recursos de origem cruzada não podem ser acessados devido a restrições existentes no acesso a esses recursos (por exemplo, não é possível acessar os pixels de um elemento de imagem ou vídeo de origem cruzada). Além disso, o acesso a dados de mídia de câmeras, microfones ou telas está sujeito à autorização do usuário. Os dados de mídia expostos por essa API já estão disponíveis em outras APIs.

Feedback

A equipe do Chromium quer saber sobre suas experiências com streams inseríveis para MediaStreamTrack.

Fale sobre o design da API

Há algo na API que não funciona como esperado? Ou faltam métodos ou propriedades que você precisa para implementar sua ideia? Você tem alguma dúvida ou comentário sobre o modelo de segurança? Envie um problema de especificação no repositório do GitHub correspondente ou adicione seus comentários a um problema existente.

Informar um problema com a implementação

Você encontrou um bug na implementação do Chromium? Ou a implementação é diferente das especificações? Registre um bug em new.crbug.com. Inclua o máximo de detalhes possível, instruções simples para reprodução e digite Blink>MediaStream na caixa Components. O Glitch é ótimo para compartilhar reprosagens rápidas e fáceis.

Mostrar suporte à API

Você planeja usar transmissões inseríveis para MediaStreamTrack? Seu apoio público ajuda a equipe do Chromium a priorizar recursos e mostra a outros fornecedores de navegadores a importância de oferecer suporte a eles.

Envie um tweet para @ChromiumDev usando a hashtag #InsertableStreams e informe onde e como você está usando.

Agradecimentos

Os streams inseríveis para a especificação MediaStreamTrack foram escritos por Harald Alvestrand e Guido Urdaneta. Este artigo foi revisado por Harald Alvestrand, Joe Medley, Ben Wagner, Huib Kleinhout e François Beaufort. Imagem principal de Chris Montgomery no Unsplash.