Nagrywanie dźwięku i przechwytywanie ekranu

W tym przewodniku omawiamy różne metody nagrywania dźwięku i obrazu z poziomu karty, okna lub ekranu za pomocą interfejsów API takich jak chrome.tabCapture czy getDisplayMedia().

Nagrywanie ekranu

W przypadku nagrywania ekranu wywołaj getDisplayMedia(), co spowoduje wyświetlenie okna widocznego poniżej. Dzięki temu użytkownik może wybrać kartę, okno lub ekran do udostępnienia, a jednocześnie wyraźnie wskazuje, że trwa nagrywanie.

Okno udostępniania ekranu w przypadku domeny example.com
Okno udostępniania ekranu w domenie example.com.

Poniższy przykład zawiera prośbę o dostęp do nagrywania zarówno dźwięku, jak i obrazu.

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

Jeśli jest wywoływany w skrypcie treści, nagrywanie zakończy się automatycznie, gdy użytkownik przejdzie na nową stronę. Aby nagrywać w tle i w trakcie nawigacji, użyj dokumentu poza ekranem i podaj powód DISPLAY_MEDIA.

Przechwytywanie kart na podstawie gestu użytkownika

Wywołanie getDisplayMedia() powoduje, że w przeglądarce wyświetla się okno z pytaniem użytkownika, co chcesz udostępnić. Jednak w niektórych przypadkach użytkownik właśnie kliknął przycisk czynności, aby wywołać rozszerzenie na konkretnej karcie. Chcesz natychmiast rozpocząć przechwytywanie karty, nie używając tego monitu.

Nagrywaj dźwięk i obraz w tle

Od wersji Chrome 116 możesz wywoływać interfejs API chrome.tabCapture w skrypcie service worker, aby uzyskać identyfikator strumienia za pomocą gestu użytkownika. Można je potem przekazać do dokumentu poza ekranem, aby rozpocząć nagrywanie.

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

Następnie w dokumencie poza ekranem:

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

Pełny przykład znajdziesz w przykładzie Tab Capture – Dyktafon.

Nagrywanie dźwięku i obrazu w nowej karcie

Przed Chrome 116 nie można było używać interfejsu chrome.tabCapture API w skryptach service worker ani używać identyfikatora strumienia utworzonego przez ten interfejs API w dokumencie niewyświetlanym na ekranie. W przypadku powyższego podejścia oba te warunki są wymagane.

Zamiast tego możesz otworzyć stronę rozszerzenia w nowej karcie lub nowym oknie i bezpośrednio uzyskać strumień. Ustaw właściwość targetTabId tak, aby przechwytywała właściwą kartę.

Otwórz stronę rozszerzenia (prawdopodobnie w wyskakującym okienku lub w mechanizmie service worker):

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

Następnie na stronie rozszerzenia:

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

Możesz też skorzystać z metody nagrywania ekranu – umożliwia ona nagrywanie w tle za pomocą dokumentu spoza ekranu, ale także wyświetlanie użytkownikowi okna, w którym można wybrać kartę, okno lub ekran.

Nagraj dźwięk w wyskakującym okienku

Jeśli chcesz tylko nagrać dźwięk, strumień możesz uzyskać bezpośrednio w wyskakującym okienku rozszerzenia, korzystając z chrome.tabCapture.capture. Po zamknięciu wyskakującego okienka nagrywanie zostanie zatrzymane.

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

Jeśli chcesz, aby nagranie było spójne we wszystkich nawigacjach, rozważ metodę opisaną w poprzedniej sekcji.

Inne uwagi

Więcej informacji o nagrywaniu strumienia znajdziesz w artykule o interfejsie MediaRecorder API.