This guide explains different approaches for recording audio and video from a tab, window, or
screen using APIs such as chrome.tabCapture
or
getDisplayMedia()
.
Screen recording
For screen recording, call getDisplayMedia()
, which triggers the dialog box
shown below. This provides the user with the ability to select which tab, window or screen they wish
to share and provides a clear indication that recording is taking place.
The following example requests access to record both audio and video.
const stream = await navigator.mediaDevices.getDisplayMedia({ audio: true, video: true });
If called within a content script, recording will automatically end when the user navigates to a new
page. To record in the background and across navigations, use an
offscreen document with the DISPLAY_MEDIA
reason.
Tab capture based on user gesture
Calling getDisplayMedia()
results in the browser showing a dialog which asks
the user what they would like to share. However, in some cases the user has just clicked on the
action button to invoke your extension for a specific tab, and you would like to
immediately start capturing the tab without this prompt.
Record audio and video in the background
Starting in Chrome 116, you can call the chrome.tabCapture
API in a service worker
to obtain a stream ID following user gesture. This can then be passed to an offscreen document to
start recording.
In your 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
});
});
Then, in your offscreen document:
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.
}
});
For a full example, see the Tab Capture - Recorder sample.
Record audio and video in a new tab
Prior to Chrome 116, it was not possible to use the chrome.tabCapture
API in a
service worker or to consume a stream ID created by that API in an offscreen document. Both of these
are requirements for the approach above.
Instead, you can open an extension page in a new tab or window, and directly obtain a stream. Set
the targetTabId
property to capture the correct tab.
Start by opening an extension page (perhaps in your popup or service worker):
chrome.windows.create({ url: chrome.runtime.getURL("recorder.html") });
Then, in your extension page:
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);
});
Alternatively, consider using the screen recording approach which allows you to record in the background using an offscreen document, but shows the user a dialog to select a tab, window or screen to record from.
Record audio in a popup
If you only need to record audio, you can directly obtain a stream in the extension popup using chrome.tabCapture.capture. When the popup closes, recording will be stopped.
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)
});
If you need the recording to persist across navigations, consider using the approach described in the previous section.
Other considerations
For more information on how to record a stream, see the MediaRecorder API.