Enregistrement audio et capture d'écran

Ce guide explique différentes approches pour enregistrer du contenu audio et vidéo à partir d'un onglet, d'une fenêtre ou d'un écran à l'aide d'API telles que chrome.tabCapture ou getDisplayMedia().

Enregistrement de l'écran

Pour l'enregistrement d'écran, appelez getDisplayMedia(), ce qui déclenche la boîte de dialogue ci-dessous. Cela permet à l'utilisateur de sélectionner l'onglet, la fenêtre ou l'écran qu'il souhaite partager, et indique clairement qu'un enregistrement est en cours.

Boîte de dialogue de partage d'écran pour example.com
Boîte de dialogue de partage d'écran pour example.com

L'exemple suivant demande l'accès pour enregistrer des contenus audio et vidéo.

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

S'il est appelé dans un script de contenu, l'enregistrement se termine automatiquement lorsque l'utilisateur accède à une nouvelle page. Pour enregistrer en arrière-plan et lors de navigations, utilisez un document hors écran avec le motif DISPLAY_MEDIA.

Capture d'onglet basée sur le geste de l'utilisateur

L'appel de getDisplayMedia() entraîne l'affichage d'une boîte de dialogue dans le navigateur, qui demande à l'utilisateur ce qu'il souhaite partager. Toutefois, dans certains cas, l'utilisateur vient de cliquer sur le bouton d'action pour appeler l'extension dans un onglet spécifique. Vous pouvez alors commencer à capturer l'onglet immédiatement, sans cette invite.

Enregistrer des contenus audio et vidéo en arrière-plan

À partir de Chrome 116, vous pouvez appeler l'API chrome.tabCapture dans un service worker pour obtenir un ID de flux suivant le geste de l'utilisateur. Il peut ensuite être transmis à un document hors écran pour commencer l'enregistrement.

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

Ensuite, dans votre document hors écran:

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

Pour voir un exemple complet, consultez l'exemple Capture d'onglet – Enregistreur.

Enregistrer des contenus audio et vidéo dans un nouvel onglet

Avant Chrome 116, il n'était pas possible d'utiliser l'API chrome.tabCapture dans un service worker ni un ID de flux créé par cette API dans un document hors écran. Ces deux éléments sont obligatoires pour l'approche ci-dessus.

En revanche, vous pouvez ouvrir la page de l'extension dans un nouvel onglet ou une nouvelle fenêtre, et obtenir directement un flux. Définissez la propriété targetTabId pour capturer l'onglet approprié.

Commencez par ouvrir une page d'extension (peut-être dans une fenêtre pop-up ou dans un service worker):

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

Ensuite, sur la page des extensions:

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

Vous pouvez également envisager d'utiliser l'approche d'enregistrement d'écran, qui vous permet d'enregistrer en arrière-plan à l'aide d'un document hors écran, mais qui présente à l'utilisateur une boîte de dialogue permettant de sélectionner un onglet, une fenêtre ou un écran à partir duquel enregistrer.

Enregistrer du contenu audio dans un pop-up

Si vous avez uniquement besoin d'enregistrer du contenu audio, vous pouvez obtenir un flux directement dans le pop-up de l'extension à l'aide de chrome.tabCapture.capture. Lorsque le pop-up se ferme, l'enregistrement est arrêté.

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 vous avez besoin que l'enregistrement persiste entre les navigations, envisagez d'utiliser l'approche décrite dans la section précédente.

Autres points à prendre en compte

Pour en savoir plus sur l'enregistrement d'un flux, consultez l'API MediaRecorder.