Grabación de audio y captura de pantalla

En esta guía, se explican los diferentes enfoques para grabar audio y video desde una pestaña, ventana o pantalla con APIs como chrome.tabCapture o getDisplayMedia().

Grabación de pantalla

Para la grabación de pantalla, llama a getDisplayMedia(), que activa el cuadro de diálogo que se muestra a continuación. Esto le proporciona al usuario la capacidad de seleccionar qué pestaña, ventana o pantalla desea compartir y le indica con claridad que se está grabando.

Diálogo de uso compartido de pantalla para example.com
Diálogo de uso compartido de pantalla para example.com.

En el siguiente ejemplo, se solicita acceso para grabar audio y video.

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

Si se llama dentro de una secuencia de comandos de contenido, la grabación finalizará automáticamente cuando el usuario navegue a una página nueva. Para grabar en segundo plano y entre navegaciones, usa un documento fuera de pantalla con el motivo DISPLAY_MEDIA.

Captura de pestañas basada en gestos del usuario

Si llamas a getDisplayMedia(), el navegador mostrará un diálogo en el que se le preguntará al usuario qué desea compartir. Sin embargo, en algunos casos, el usuario acaba de hacer clic en el botón de acción para invocar tu extensión para una pestaña específica, y tú quieres comenzar a capturar la pestaña de inmediato sin este mensaje.

Graba audio y video en segundo plano

A partir de Chrome 116, puedes llamar a la API de chrome.tabCapture en un service worker para obtener un ID de transmisión después del gesto del usuario. Luego, se puede pasar a un documento fuera de pantalla para comenzar a grabar.

En tu 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
  });
});

Luego, en el documento fuera de pantalla, haz lo siguiente:

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 ver un ejemplo completo, consulta el ejemplo Captura de pestaña: Grabadora.

Cómo grabar audio y video en una pestaña nueva

Antes de Chrome 116, no era posible usar la API de chrome.tabCapture en un service worker ni consumir un ID de transmisión creado por esa API en un documento fuera de pantalla. Ambos son requisitos para el enfoque anterior.

En su lugar, puedes abrir la página de una extensión en una pestaña o ventana nueva para obtener una transmisión directamente. Configura la propiedad targetTabId para capturar la pestaña correcta.

Para comenzar, abre una página de la extensión (quizá en tu ventana emergente o service worker):

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

Luego, sigue estos pasos en la página de extensiones:

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, considera usar el enfoque de grabación de pantalla, que te permite grabar en segundo plano con un documento fuera de pantalla, pero le muestra al usuario un diálogo para seleccionar una pestaña, ventana o pantalla desde la que grabar.

Cómo grabar audio en una ventana emergente

Si solo necesitas grabar audio, puedes obtener una transmisión directamente en la ventana emergente de la extensión con chrome.tabCapture.capture. Cuando se cierre la ventana emergente, se detendrá la grabación.

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)
});

Si necesitas que el registro se conserve en todas las navegaciones, considera usar el enfoque descrito en la sección anterior.

Otras consideraciones

Para obtener más información sobre cómo grabar una transmisión, consulta la API de MediaRecorder.