Gravação de áudio e captura de tela

Este guia explica diferentes abordagens para gravar áudio e vídeo de uma guia, janela ou tela usando APIs como chrome.tabCapture ou getDisplayMedia()

Gravação de tela

Para gravação de tela, chame getDisplayMedia(), que aciona a caixa de diálogo. mostradas abaixo. Isso fornece ao usuário a capacidade de selecionar qual guia, janela ou tela quer compartilhar e indicar claramente que a gravação está ocorrendo.

Caixa de diálogo de compartilhamento de tela de example.com
Caixa de diálogo de compartilhamento de tela de example.com.

O exemplo a seguir solicita acesso para gravar áudio e vídeo.

const stream = await navigator.mediaDevices.getDisplayMedia({ audio: true, video: true });

Se chamado dentro de um script de conteúdo, a gravação será encerrada automaticamente quando o usuário navegar para um novo página. Para gravar em segundo plano e em diferentes navegações, use uma documento fora da tela pelo motivo DISPLAY_MEDIA.

Captura de guia com base no gesto do usuário

Chamar getDisplayMedia() faz com que o navegador mostre uma caixa de diálogo que solicita ao usuário o que ele gostaria de compartilhar. No entanto, em alguns casos, o usuário apenas clica no botão botão de ação para invocar sua extensão para uma guia específica e você quiser começar imediatamente a capturar a guia sem esse comando.

Grave áudio e vídeo em segundo plano

A partir do Chrome 116, é possível chamar a API chrome.tabCapture em um service worker para receber um ID de stream após o gesto do usuário. Isso pode ser transmitido para um documento fora da tela para iniciar a gravação.

No seu service worker:

chrome.action.onClicked.addListener(async (tab) => {
  const existingContexts = await chrome.runtime.getContexts({});

  const offscreenDocument = existingContexts.find(
    (c) => c.contextType === 'OFFSCREEN_DOCUMENT'
  );

  // If an offscreen document is not already open, create one.
  if (!offscreenDocument) {
    // Create an offscreen document.
    await chrome.offscreen.createDocument({
      url: 'offscreen.html',
      reasons: ['USER_MEDIA'],
      justification: 'Recording from chrome.tabCapture API',
    });
  }

  // Get a MediaStream for the active tab.
  const streamId = await chrome.tabCapture.getMediaStreamId({
    targetTabId: tab.id
  });

  // Send the stream ID to the offscreen document to start recording.
  chrome.runtime.sendMessage({
    type: 'start-recording',
    target: 'offscreen',
    data: streamId
  });
});

Em seguida, no documento fora da tela:

chrome.runtime.onMessage.addListener(async (message) => {
  if (message.target !== 'offscreen') return;
  
  if (message.type === 'start-recording') {
    const media = await navigator.mediaDevices.getUserMedia({
      audio: {
        mandatory: {
          chromeMediaSource: "tab",
          chromeMediaSourceId: message.data,
        },
      },
      video: {
        mandatory: {
          chromeMediaSource: "tab",
          chromeMediaSourceId: message.data,
        },
      },
    });

    // Continue to play the captured audio to the user.
    const output = new AudioContext();
    const source = output.createMediaStreamSource(media);
    source.connect(output.destination);

    // TODO: Do something to recording the MediaStream.
  }
});

Para conferir um exemplo completo, consulte Captura de guia - Gravador.

Gravar áudio e vídeo em uma nova guia

Antes do Chrome 116, não era possível usar a API chrome.tabCapture em uma service worker ou consumir um ID de stream criado por essa API em um documento fora da tela. Ambas as opções são requisitos para a abordagem acima.

Em vez disso, você pode abrir uma página de extensão em uma nova guia ou janela e acessar um stream diretamente. Definir a propriedade targetTabId para capturar a guia correta.

Comece abrindo uma página de extensão (talvez em seu pop-up ou service worker):

chrome.windows.create({ url: chrome.runtime.getURL("recorder.html") });

Em seguida, na página da sua extensão:

chrome.tabCapture.getMediaStreamId({ targetTabId: tabId }, async (id) => {
  const media = await navigator.mediaDevices.getUserMedia({
    audio: {
      mandatory: {
        chromeMediaSource: "tab",
        chromeMediaSourceId: id,
      },
    },
    video: {
      mandatory: {
        chromeMediaSource: "tab",
        chromeMediaSourceId: id,
      },
    },
  });

  // Continue to play the captured audio to the user.
  const output = new AudioContext();
  const source = output.createMediaStreamSource(media);
  source.connect(output.destination);
});

Como alternativa, considere usar a abordagem de gravação de tela, que permite gravar em segundo plano usando um documento fora da tela, mas mostrar ao usuário uma caixa de diálogo para selecionar uma guia janela ou tela de onde gravar.

Gravar áudio em um pop-up

Se você só precisa gravar áudio, receba um stream diretamente no pop-up da extensão usando chrome.tabCapture.capture. Quando o pop-up fechar, a gravação será interrompida.

chrome.tabCapture.capture({ audio: true }, (stream) => {
  // Continue to play the captured audio to the user.
  const output = new AudioContext();
  const source = output.createMediaStreamSource(stream);
  source.connect(output.destination);

  // TODO: Do something with the stream (e.g record it)
});

Se você precisar que a gravação persista entre as navegações, considere usar a abordagem descrita na seção anterior.

Outras considerações

Para saber mais sobre como gravar uma transmissão, consulte a API MediaRecorder.