Can Chrome content and background scripts share access to blob: URLs?

I’m creating a getUserMedia stream in a Chrome extension content script, and I’d like to pass it to the background script.

You can’t pass non-JSON’able data between them, so my strategy is to pass instead the generated blob URL to the stream.

Content script:

function get_stream() {
    navigator.mediaDevices.getUserMedia({video: 1}).then(stream => {
        chrome.runtime.sendMessage({action: 'got_stream', params: {stream_url: URL.createObjectURL(stream)}});

Background script:

chrome.runtime.onMessage.addListener(function(data) {
    switch (data.action) {
        case 'got_stream': got_stream(data.params); break;

function got_stream(params) {
    let vid = document.createElement('video');
    alert(params.stream_url); //blob:http://...
    vid.src = params.stream_url; //error - file not found

This is fine… until I try to apply it to a generated element, at which point the console says the file is not found.

I assume it’s because the background and content scripts are in sandboxed environments.

Is there any way around this without having to do something nuclear like transfer the stream literally via WebRTC or something?

chrome.desktopCapture – can’t record both system audio and microphone?

I’ve built a Chrome extension that captures screen activity and microphone input and outputs a video file. Since chrome.desktopCapture can’t record audio input alongside screen capture, I’m getting the mic in its own, separate stream. So:

//get screen stream
chrome.desktopCapture.chooseDesktopMedia(['screen'], null, (stream_id, opts) => {
    let constraints = {video: mandatory: {
        chromeMediaSource: 'desktop',
        chromeMediaSourceId: stream_id
    navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
        video_stream = stream;

//get mic stream
navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {
    audio_stream = stream;

Then, later, when I’ve got both streams, before I start recording I merge them by creating a master stream and add the respective tracks from the separate video and audio streams to it.

let master_stream = new MediaStream(video_stream);

And ultimately, when I end up with a video file, this works GREAT. I get screen and mic.

Question: Why does this technique NOT work if I ask Chrome to ALSO record system sound?

So if I change ['screen'] to ['screen', 'audio'], with everything else the same, I end up with no mic in the resultant video.

If I output getTracks() on master_stream, here’s what I get:

    0: MediaStreamTrack {kind: "audio", id: "9ee3ee33-73ee-41e4-957c-d6fd3aaada43", label: "System Audio", enabled: true, muted: false, …}
    1: MediaStreamTrack {kind: "audio", id: "ab2429a1-7f75-48f2-9ee1-6a4bfd7ca942", label: "Default - Microphone (Samson Meteor Mic) (17a0:0310)", enabled: true, muted: false, …}
    2: MediaStreamTrack {kind: "video", id: "4ecb1929-31d0-4a79-8cbc-1a8759323c3b", label: "screen:0:0", enabled: true, muted: false, …}

I can’t see an obvious cause as to why adding system audio kills mic audio in the resultant output. Anyone any ideas?

Chrome Extension – getUserMedia throws “NotAllowedError: Failed due to shutdown”

I have a suite which records the user’s webcam and mic. It works great on a webpage, but in a Chrome Extension the line:

navigator.mediaDevices.getUserMedia({video: true, audio: true})

is throwing

NotAllowedError: Failed due to shutdown

I’ve searched and found almost nothing that might explain this. Has anyone else come across this or know what I can do about it?

how to get microphone permission when button is clicked in extension popup

                                audio: {
                                    echoCancellation: !0,
                                    channelCount: 1,
                                    sampleRate: {
                                        ideal: e
                                    sampleSize: i

it return promise value Rejected and promise status DOM:Shutdown

Record current tab in chrome using chrome extension and getUserMedia()

I am trying to make a Chrome extension to record user activity in the current tab.

I found out that I can use getUserMedia() on the front, and chrome.desktopCapture in my background script.

However, when I try to use chrome.desktopCapture.chooseDesktopMedia([‘tab’], onApproved), I get prompted for the tab I want to share. However, I would like to skip this step and share my current tab without the prompt.

I know that this can be done, because in the Screencastify Chrome extension, you can do that. The first option is to record the current tab and no popups are displayed.

What is the correct way to handle native cancelling of getUserMedia screenshare?

I am using screenshare with getUserMedia for a web application I am developing.

I am currently using Chrome with a Chrome extension using the API below to achieve the functionality, but the functionality is also possible in Firefox and may become natively available(I believe it was possible in the past) via getDisplayMedia or other means in the future.

During screenshare, a native dialog is shown at the bottom of the browser to stop the screenshare. I would like for a way to handle this event, but I am unaware of a common, standard way to achieve this. Is there an appropriate way to do this(preferably in all APIs), or should I achieve this by track events?

Video capture only selected area via Chrome Extension

I’m trying to write an Chrome Extension which allows user to select an area on screen and then captures video of that area only.
I read everything about chrome.desktopCapture API and about getUserMedia(), but I can’t find an option for it, it seems like it allows only capturing of whole screen.
Is there any alternate way to do this via Chrome Extension?
Basically, input from user is coordinates of top left angle and the dimension of area will always be the same.