Audio- und Bildschirmaufnahme

In dieser Anleitung werden verschiedene Ansätze zum Aufzeichnen von Audio und Video aus einem Tab, Fenster oder Bildschirm mit APIs wie chrome.tabCapture oder getDisplayMedia() erläutert.

Bildschirmaufzeichnung

Rufen Sie für die Bildschirmaufzeichnung getDisplayMedia() auf. Dadurch wird das unten abgebildete Dialogfeld ausgelöst. So kann der Nutzer auswählen, welchen Tab, welches Fenster oder welchen Bildschirm er teilen möchte, und gibt einen klaren Hinweis darauf, dass eine Aufnahme stattfindet.

Dialogfeld zur Bildschirmfreigabe für example.com
Dialogfeld zur Bildschirmfreigabe für beispiel.de

Im folgenden Beispiel wird der Zugriff für die Aufzeichnung von Audio und Video angefordert.

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

Wenn der Aufruf in einem Inhaltsskript erfolgt, endet die Aufzeichnung automatisch, sobald der Nutzer eine neue Seite aufruft. Wenn du im Hintergrund und in verschiedenen Navigationsbereichen Aufnahmen machen möchtest, verwende ein Dokument außerhalb des Bildschirms und gib den Grund DISPLAY_MEDIA an.

Tabaufnahme basierend auf Nutzergeste

Wenn getDisplayMedia() aufgerufen wird, wird im Browser ein Dialogfeld angezeigt, in dem der Nutzer gefragt wird, was er freigeben möchte. In einigen Fällen hat der Nutzer jedoch gerade auf die Aktionsschaltfläche geklickt, um Ihre Erweiterung für einen bestimmten Tab aufzurufen, und Sie möchten die Aufnahme des Tabs sofort ohne diese Eingabeaufforderung starten.

Audio und Video im Hintergrund aufnehmen

Ab Chrome 116 können Sie die chrome.tabCapture API in einem Service Worker aufrufen, um nach der Nutzergeste eine Stream-ID zu erhalten. Diese kann dann an ein nicht sichtbares Dokument übergeben werden, um mit der Aufzeichnung zu beginnen.

Führen Sie im Service Worker folgende Schritte aus:

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

Gehen Sie dann in Ihrem nicht sichtbaren Dokument so vor:

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

Ein vollständiges Beispiel finden Sie im Beispiel Tab Capture – Rekorder.

Audio und Video in einem neuen Tab aufnehmen

Vor Chrome 116 war es nicht möglich, die chrome.tabCapture API in einem Service Worker zu verwenden oder eine von dieser API erstellte Stream-ID in einem nicht sichtbaren Dokument zu nutzen. Beide sind Voraussetzungen für den obigen Ansatz.

Stattdessen können Sie die Seite mit den Erweiterungen in einem neuen Tab oder Fenster öffnen und direkt einen Stream abrufen. Legen Sie die Eigenschaft targetTabId so fest, dass der richtige Tab erfasst wird.

Öffnen Sie zuerst eine Erweiterungsseite (beispielsweise in Ihrem Pop-up oder Service Worker):

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

Gehen Sie dann auf der Seite mit den Erweiterungen so vor:

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

Alternativ können Sie die Bildschirmaufzeichnung verwenden. Dabei können Sie im Hintergrund ein nicht sichtbares Dokument verwenden, dem Nutzer aber ein Dialogfeld zur Auswahl eines Tabs, Fensters oder Bildschirms für die Aufnahme angezeigt wird.

Audio in einem Pop-up aufnehmen

Wenn Sie nur Audioaufnahmen machen müssen, können Sie mit chrome.tabCapture.capture direkt einen Stream im Pop-up der Erweiterung abrufen. Wenn das Pop-up-Fenster geschlossen wird, wird die Aufzeichnung beendet.

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

Wenn die Aufzeichnung navigationsübergreifend bestehen bleiben soll, sollten Sie den im vorherigen Abschnitt beschriebenen Ansatz verwenden.

Weitere Aspekte

Weitere Informationen zum Aufzeichnen eines Streams findest du im Artikel zur MediaRecorder.