GoogleChromeLabs / web-audio-samples

Web Audio API samples by Chrome Web Audio Team
https://bit.ly/web-audio-samples
Apache License 2.0
687 stars 197 forks source link

audioWorklet.addModule doesn't load scipt inside of Chrome Extensions #192

Closed Yuribtr closed 4 years ago

Yuribtr commented 4 years ago

I'm writing extension for Chrome, which works with SpeechRecognition engine via microphone. Also I'm trying to make simple volume voice (or gain) indicator, as this is crucial for recognition quality. For this I tried to use AudioWorkletProcessor. I made separate JS file 'vmeter.js' with class VMonitorProcessor that extends AudioWorkletProcessor and some test messages inside. Than I put vmeter.js in root folder of my extension, together with content.js and background.js. Following lines of code in content.js gives me an error:

const context = new AudioContext();
const processorURL = 'vmeter.js';
context.audioWorklet.addModule(processorURL).then(() => {
            consoleLog('Module added');
            let vMeterWorkletNode = new VMeterWorkletNode(context);
            vMeterWorkletNode.connect(context.destination);
});

Uncaught (in promise) DOMException: The user aborted a request.

I tried almost everything, any combinations of absolute and relative URL doesn't help (also due to CORS policies). By the way, above error also fired if I pass empty file name to addModule, which confirms that addModule doesn't look JS file in extension folder.

But I found a temporary solution, which looks as dirty hack:

const context = new AudioContext();
const processorSource = atob('.......');//base64 encoded script vmeter.js goes here
const processorBlob = new Blob([processorSource.toString()], {type: 'text/javascript'});
const processorURL = URL.createObjectURL(processorBlob);
context.audioWorklet.addModule(processorURL).then(() => {
            consoleLog('Module added');
            let vMeterWorkletNode = new VMeterWorkletNode(context);
            vMeterWorkletNode.connect(context.destination);
});

This works fine. But of course this must not be used in production release.

Maybe addModule needs some correction to account the context of it's execution? Sorry, if I mistakenly put this issue here, I don't know where such issue can be reported.

Yuribtr commented 4 years ago

Seems that, problem solved by adding in manifest following statement:

  "web_accessible_resources": [
    "vmeter.js"
  ],

and code for execution like this:

const processorURL = chrome.runtime.getURL('vmeter.js');
 context.audioWorklet.addModule(processorURL).then(() => {
            console.Log('VMeter module added');
            let vMeterWorkletNode = new VMeterWorkletNode(context);
            vMeterWorkletNode.connect(context.destination);
    });

So this issue was NOT connected with addModule behavior.