[Goal]: To record the sound of a tab and at the same time hear the sound while it's being recorded
[Means]: To use chrome.tabCapture because it's less invasive than chrome.desktopCapture or navigator.mediaDevices.getDisplayMedia. The former provides a better user experience as opposed to the latter which asks for tab selection every time and then intrusively shows the blue rectangle with a status bar and the Stop Sharing button
[Issue]: Tab sound is muted after getting the stream (recording not necessary, only calling getUserMedia) and can not be unmuted
[Technicals]:
1. Obtain the stream id in a foreground page (popup, options, or iframe pointing to an extension page, injected in the current DOM by a content script) because that's the only place where tabCapture is available
const tabId = ...get current tab id...
chrome.tabCapture.getMediaStreamId({ consumerTabId: tabId }, function(streamId) {
// send the streamId to the content script
})
2. Receive the streamId then use it to start the capture
const options = {
audio: {
mandatory: {
chromeMediaSource: 'tab',
chromeMediaSourceId: streamId
}
}
}
navigator.mediaDevices.getUserMedia(options).then((tabStream) => {
// at this point the sound of the tab becomes muted with no way to unmute it
});
3. Just invoking tabCapture will mute the tab. AudioContext source connecting to the default destination doesn't do anything for this stream and no error is thrown. If the callback promise from getUserMedia is empty, the sound of the tab comes back on its own in about 20 seconds or so. If MediaRecorder actually uses the stream to record the sound, the sound doesn't come back until recording is stopped. The sound of the tab *is present in the recording*, just muted while recording.
[Comparison 1]: Obtaining a MediaStream directly with chrome.tabCapture.capture instead of the above mechanism works as intended. The tab sound is muted, but can be reconnected to the speakers using AudioContext. The issue with this approach is that chrome.tabCapture.capture can't be started successfully in an injected iframe (always fails with the cryptic "Error starting tab capture"), so there's no way to capture the sound. It does work in a popup though, but not really an option given its volatile nature.
[Comparison 2]: chrome.desktopCapture works the opposite way. The sound is always present in the tab while recording and can not be muted, not that this poses a problem.
[Bug report]: Also filed a bug report
here.