17

I've successfully instantiated a simple AudioWorklet in React and wish to start a simple oscillator like in Google's example. In order to test run it, I am rendering a button whose onClick event calls the following:

src/App.jsx:

userGesture(){
  //create a new AudioContext
  this.context = new AudioContext();

  //Add our Processor module to the AudioWorklet
  this.context.audioWorklet.addModule('worklet/processor.js').then(() => {

  //Create an oscillator and run it through the processor
  let oscillator = new OscillatorNode(this.context);
  let bypasser = new MyWorkletNode(this.context, 'my-worklet-processor');

  //Connect to the context's destination and start
  oscillator.connect(bypasser).connect(this.context.destination);
  oscillator.start();
  })
  .catch((e => console.log(e)))
}

The problem is, on every click, addModule method is returning the following error:

DOMException: The user aborted a request.

I am running Chrome v66 on Ubuntu v16.0.4.

src/worklet/worklet-node.js:

 export default class MyWorkletNode extends window.AudioWorkletNode {
        constructor(context) {
          super(context, 'my-worklet-processor');
        }
      }

src/worklet/processor.js

class MyWorkletProcessor extends AudioWorkletProcessor {
    constructor() {
      super();
    }

    process(inputs, outputs) {
      let input = inputs[0];
      let output = outputs[0];
      for (let channel = 0; channel < output.length; ++channel) {
        output[channel].set(input[channel]);
      }


      return true;
    }
  }

  registerProcessor('my-worklet-processor', MyWorkletProcessor);
spidercatnat
  • 439
  • 1
  • 5
  • 15
  • If each user click calls `userGesture`, then you are constantly registering the same processor again and again with the same name. That's not allowed. Don't understand the error message though. – Raymond Toy Apr 25 '18 at 15:10
  • 2
    I've just had the same exception and the reason turned out to be a syntax error in the processor file. I've checked yours and I don't see any errors. So I don't know what exactly caused it in your case, but I'll leave this comment here in case anyone else will stumble upon the same exception. – filipovskii_off May 13 '18 at 13:53
  • I'm running into the exact same issue with newer CSS Paint worklets. If I pull their example from the github site, it works fine. If I host it locally, it gives this error. Very confusing. – Dr_Derp Jul 10 '18 at 19:05
  • It throws that when the module file path is wrong. – Константин Ван Apr 27 '20 at 23:15

7 Answers7

13

My code is straight JavaScript, not React, but I got the same error because the path provided to addModule was incorrect. In my case, both the script that calls addModule and the script provided as the argument to addModule reside in the same directory ("js"). In spite of that, I still had to include this directory in the path to eliminate the error:

...addModule('js/StreamTransmitter.js')...

I hope this helps. Good luck!

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
StephenL
  • 181
  • 1
  • 4
  • Thanks! I found the answer in the context of React was to server AudioWorkletProcessors from the public directory. Shameless plug, I wrote an entire Medium article on it ;-) – spidercatnat Feb 21 '19 at 19:07
4

For anyone else getting this mysterious error, swallow your pride and check the following:

  • The processor doesn't have any errors.
  • The processor is calling external modules with proper path to the external file(s).
  • The external modules don't have any errors.

The promise will abort when external modules that are loaded via "import" have errors, or the paths to the modules can't be resolved (e.g. the path's to the modules are wrong and don't point to existing files).

bob
  • 7,539
  • 2
  • 46
  • 42
  • Out of all the answers, this is the one I found helpful :) I got the error from having an improper path. I forgot to change it while moving files around because I'm used to VSCode automatically updating ES module imports for me. – Ronald C Jan 12 '21 at 03:08
3

This seems to be a bug in the Chromium module loader, it parses the worklet/processor.js file by removing whitespace, which in turn causes it to have JavaScript syntax errors everywhere, which then finally causes this generic non-explanatory error message to show up.

The solution is to serve your worklet-processors (e.g. worklet/processor.js in your case) with:

Content-Type: application/javascript

or

Content-Type: text/javascript
John Weisz
  • 30,137
  • 13
  • 89
  • 132
3

This worked for me: serve your worklet files from public folder instead of src. The addModule(url) function points there by default, so addModule('worklets/foo.js') references file public\worklets\foo.js

Source: https://hackernoon.com/implementing-audioworklets-with-react-8a80a470474

Adam D.
  • 29
  • 5
  • 1
    Ah, you found my article that this thread culminated in :) HackerNoon lost all the gists, sadly. Check out the same article on Medium: https://medium.com/hackernoon/implementing-audioworklets-with-react-8a80a470474 – spidercatnat Jan 26 '21 at 19:32
2

I also experienced this error but due to a Webpack issue.

Turns out webpack doesn't support worklets like it supports web workers (see this issue).

I would recommend using worker-url with webpack.

  1. Install worker-url
npm i --save-dev worker-url
  1. Update your webpack config to include the WorkerUrl plugin.
const WorkerUrlPlugin = require('worker-url/plugin');

module.exports = {
  // ...
  plugins: [new WorkerUrlPlugin()],
  // ...
};

  1. Use WorkerUrl like so:
import { WorkerUrl } from 'worker-url';

const workletUrl = new WorkerUrl(
  new URL('./random-noise-processor', import.meta.url),
  { name: 'worklet' },
);

await context.audioWorklet.addModule(workletUrl);
Rico Kahler
  • 17,616
  • 11
  • 59
  • 85
1

The Error "DOMException: The user aborted a request." happens when the AudioWorklet.addModule() function cannot load the file from the path or URL you provided. Refer to this MDN page

The api AudioWorklet.addModule() expects a String containing the URL of a JavaScript file with the module to add.

It can be an internal URL that points to your public folder where the browser loads your static files in this case -> 'worklet/processor.js if the worklet folder is inside the public directory of your React app. You can modify your code as below.

this.context.audioWorklet.addModule('worklet/processor.js')

In this case the audioWorklet.addModule() method expects the path to point to your public folder. It can also be an external URL for example a link to Github repository that loads the JS file.

Hamza Kyamanywa
  • 417
  • 3
  • 8
-1

Changing:

this.context.audioWorklet.addModule('worklet/processor.js') 

with

this.context.audioWorklet.addModule('../worklet/processor.js') 

worked for me.

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61