Compartilhamento de guias aprimorado com a captura de região

François Beaufort
François Beaufort

A plataforma da Web já permite que um app da Web capture uma faixa de vídeo da guia atual. Agora ele vem com a captura de região, um mecanismo para cortar essas faixas de vídeo. O aplicativo da web designa uma parte da guia atual como sua área de interesse, e o navegador recorta todos os pixels fora dessa área.

Antes, os apps da Web podiam cortar as faixas de vídeo "manualmente". Ou seja, os aplicativos da web podem manipular cada frame diretamente. Essa solução não foi robusta nem eficiente. A captura de região resolve essas deficiências. O app da Web agora pode instruir o navegador a fazer o trabalho por ele.

Sobre a captura de região

Você criou um site com Dynamic ContentTM. É o melhor aplicativo da web de todos os tempos, e as pessoas não conseguem parar de usá-lo, muitas vezes de forma colaborativa. Uma próxima etapa possível é incorporar recursos de conferência virtual. Você decide fazer isso. Você se junta a um provedor de serviços de videoconferência e incorpora o app da Web dele como um iframe de origem cruzada. O app da Web de videoconferência captura a guia atual como uma faixa de vídeo e a transmite para os participantes remotos.

Captura de tela de uma janela do navegador com um app da Web destacando a área de conteúdo principal e o iframe de origem cruzada.
A área de conteúdo principal está em azul, e o iframe de origem cruzada está em vermelho.

Não tão rápido... Agora, você realmente não quer transmitir os vídeos das pessoas de volta para elas, certo? Melhor cortar essa parte. Mas como? O iframe incorporado não sabe qual conteúdo você expõe e onde. Por isso, não é possível cortar sem ajuda. Em teoria, você poderia passar as coordenadas pretendidas. Mas o que acontece se o usuário redimensionar a janela? Rola a janela de visualização? Aumenta ou diminui o zoom? Interage com a página de uma forma que produz uma mudança de layout? Mesmo que você envie as novas coordenadas para o iframe de captura, problemas de sincronização ainda podem gerar alguns frames cortados com erros.

Então, vamos usar a captura de região. Há um Element na sua página, talvez um <div>, com o conteúdo principal. Vamos chamá-lo de mainContentArea. Você quer que o app da Web de videoconferência capture e compartilhe remotamente a área definida pela caixa delimitadora desse elemento. Então, você deriva um CropTarget de mainContentArea. Você transmite este CropTarget para o app da Web de videoconferência. Depois de cortar a faixa de vídeo usando este CropTarget, os frames nessa faixa agora consistem apenas nos pixels que se enquadram na caixa delimitadora de mainContentArea. Se mainContentArea mudar de tamanho, forma ou localização, a faixa de vídeo vai acompanhar, sem exigir nenhuma outra entrada de nenhum app da Web.

Vamos repetir essas etapas:

Defina um CropTarget no seu app da Web chamando CropTarget.fromElement() com o elemento que você quiser como entrada.

// In the main web app, associate mainContentArea with a new CropTarget
const mainContentArea = document.querySelector("#mainContentArea");
const cropTarget = await CropTarget.fromElement(mainContentArea);

Você transmite o CropTarget para o app da Web de videoconferência.

// Send the CropTarget to the video conferencing web app.
const iframe = document.querySelector("#videoConferenceIframe");
iframe.contentWindow.postMessage(cropTarget);

O app da Web de videoconferência pede ao navegador para cortar a faixa na área definida pelo CropTarget chamando cropTo() na faixa de vídeo de autocaptura com o alvo do corte recebido do app da Web principal.

// In the embedded video conferencing web app, ask the user for permission
// to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
  preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();

// Start cropping the self-capture video track using the CropTarget
// received over window.onmessage.
await track.cropTo(cropTarget);

// Enjoy! Transmit remotely the cropped video track with RTCPeerConnection.

Et voilà! Tudo pronto.

Análise detalhada

Detecção de recursos

Para verificar se CropTarget.fromElement() é compatível, use:

if ("CropTarget" in self && "fromElement" in CropTarget) {
  // Deriving a target is supported.
}

Como derivar um CropTarget

Vamos nos concentrar no elemento chamado mainContentArea. Para derivar um CropTarget com base nele, chame CropTarget.fromElement(mainContentArea). A promessa retornada será resolvida com um novo objeto CropTarget se for bem-sucedida. Caso contrário, ela será rejeitada se você tiver criado um número desnecessário de objetos CropTarget.

const mainContentArea = document.querySelector("#mainContentArea");
const cropTarget = await CropTarget.fromElement(mainContentArea);

Ao contrário de um Element, um objeto CropTarget é serializável. Ele pode ser transmitido para outro documento usando Window.postMessage(), por exemplo.

Corte

Ao capturar a guia, a faixa de vídeo é instanciada como uma BrowserCaptureMediaStreamTrack, que é uma subclasse de MediaStreamTrack. Essa subclasse expõe cropTo(). Chame track.cropTo(cropTarget) para começar a cortar os contornos de mainContentArea (o elemento do qual cropTarget foi derivado).

Se for bem-sucedida, a promessa será resolvida quando for possível garantir que todos os frames de vídeo subsequentes consistam nos pixels que se enquadram na caixa delimitadora da mainContentArea.

Se falhar, a promessa vai ser rejeitada. Isso acontecerá se:

  • A CropTarget foi criada em outra guia. Por enquanto, fique atento.
  • O CropTarget foi derivado de um elemento que não existe mais.
  • A música tem clonagens. Consulte o problema 1509418 (link em inglês).
  • A faixa atual não é uma faixa de vídeo de captura automática. veja abaixo.

O método cropTo() é exposto em qualquer faixa de vídeo de captura de guia, e não apenas na autocaptura. Portanto, é aconselhável verificar se o usuário selecionou a guia atual antes de tentar cortar a faixa. Para isso, use o Capture Handle. Também é possível pedir ao navegador para orientar o usuário a fazer a autocaptura usando o preferCurrentTab.

// Start cropping the self-capture video track using the CropTarget.
await track.cropTo(cropTarget);

Para reverter para o estado sem corte, chame cropTo() com null.

// Stop cropping.
await track.cropTo(null);

Conteúdo obstrutivo e escondido

Para a captura de região, somente a posição e o tamanho do destino são importantes, e não o z-index. Os pixels que ocultam o alvo serão capturados. As partes obstruídas do alvo não serão capturadas.

Isso é resultado da captura de região, que é basicamente corte. Uma alternativa, que será a própria API futura, é a captura no nível do elemento. Ou seja, capture somente pixels associados ao alvo, independentemente das oclusões. Essa API tem um conjunto de requisitos de segurança e privacidade diferente do simples recorte.

Imagem de diferentes resultados para a API Region Capture e o Element-level Capture.
Comportamento da captura de região com conteúdo de obstrução.

Segurança e privacidade

A captura de região permite que um app da Web que já esteja observando todos os pixels na guia remova alguns desses pixels voluntariamente. Ele é altamente seguro, porque nenhuma informação nova pode ser obtida.

A captura de região pode ser usada para limitar quais informações são enviadas aos participantes remotos. Por exemplo, talvez você queira compartilhar alguns slides, mas não suas anotações do apresentador.

Captura de tela de uma janela do navegador com slides e anotações do apresentador.
Um app da Web com slides e anotações do apresentador.
Compartilhar as anotações remotamente é altamente indesejável. Sinalize captura de região.

No local, a captura de região não adiciona nenhuma garantia de segurança. Ao transferir uma faixa para outro documento, o documento de destino ainda pode desfazer o corte e ter acesso a todos os pixels da guia capturada.

O Chrome desenha uma borda azul ao redor das bordas das guias capturadas. Ao cortar, o Chrome geralmente desenha a borda azul ao redor do alvo recortado.

Demonstração

Você pode testar a captura de região executando a demonstração no Glitch. Tenha confira o código-fonte.

Suporte ao navegador

Compatibilidade com navegadores

  • Chrome: 104
  • Borda: 104.
  • Firefox: incompatível.
  • Safari: incompatível.

A captura de região está disponível no Chrome 104 apenas em computadores.

A seguir

Veja uma prévia do que vai melhorar o compartilhamento de tela na Web em um futuro próximo:

  • A captura de região é compatível com capturas de outras guias.
  • O Foco condicional permite que o app da Web de captura instrua o navegador a mudar o foco para a superfície de exibição capturada ou evitar essa mudança.
  • Uma API Capture no nível do elemento pode ser fornecida.

Feedback

A equipe do Chrome e a comunidade de padrões da Web querem saber sobre suas experiências com a captura de região.

Conte-nos sobre o design

Alguma coisa na captura de região não funciona como você esperava? Ou faltam métodos ou propriedades que você precisa para implementar sua ideia? Tem uma pergunta ou comentário sobre o modelo de segurança?

  • Registre um problema de especificação no repositório do GitHub (link em inglês) ou adicione sua opinião a um problema.

Problemas com a implementação?

Você encontrou um bug na implementação do Chrome? Ou a implementação é diferente das especificações?

  • Registre um bug em https://new.crbug.com. Certifique-se de incluir o máximo de detalhes possível e instruções simples para reproduzi-los. O Glitch é ótimo para compartilhar repetições rápidas e fáceis.

Mostrar apoio

Você planeja usar a captura por região? Seu apoio público ajuda a equipe do Chrome a priorizar recursos e mostra a outros fornecedores de navegadores como é essencial oferecer suporte a eles.

Envie um tweet para @ChromiumDev e informe onde e como você o está usando.

Agradecimentos

Agradecemos a João Medley por revisar este artigo.