Tips for integrating AudioWorklets with vue-cli, webpack, and babel (resolved illegal invocation error)

I'm experiencing some challenges while attempting to develop a WebApp using vue-cli with AudioWorklets. Whenever I try to access properties of my AudioWorkletNode, such as port or channelCount, I encounter multiple errors:

TypeError: Illegal invocation at MyWorkletNode.invokeGetter

Despite extensive research and debugging, it seems that the issue is somehow linked to classes. AudioWorklet appears to only function properly with ES6 classes, but vue-cli/babel/webpack performs some mysterious magic (which I am not familiar with) and transpiles the classes into regular constructor functions or something similar. Or could it be worklet-loader that handles the transpilation? I am completely lost and unsure where to focus my efforts.

If I code without any bundlers, just pure vanilla JS, it works flawlessly without any errors. However, incorporating AudioWorklets in my vue project poses a challenge. Are there alternative solutions apart from disabling class transpilation? If not, how can I disable it effectively?

// main.js
import worklet from 'worklet-loader!./processor.js'

class MyWorkletNode extends AudioWorkletNode {
  constructor(context) {
    super(context, 'my-worklet-processor');
    // Triggers TypeError: Illegal invocation
    console.log(this.channelCount);
  }
}

this.audioCtx.audioWorklet.addModule(worklet).then(() => {
  let node = new MyWorkletNode(this.audioCtx);
  console.log("Loaded!");

  // Triggers TypeError: Illegal invocation
  node.port.onmessage = event => {
    console.log(event.data);
  };
}).catch(e => console.log(`${e.name}: ${e.message}`));


// processor.js
class MyWorkletProcessor extends AudioWorkletProcessor {
  constructor() {
    super();
    this.port.postMessage('hello!');
  }

  process(inputs, outputs, parameters) {
    // audio processing code here.
  }
}

registerProcessor('my-worklet-processor', MyWorkletProcessor);

Answer №1

Identifying the issue here can be challenging without more code for context. The components related to worklets appear to be correct.

To address the broader question (for future reference), the processor needs to be in a separate bundle loaded into its own context. When utilizing worklet-loader, the import essentially functions as a URL.

import MyWorkletProcessor from 'worklet-loader!./path/MyWorkletProcessor'

console.log(MyWorkletProcessor) 

>5b91ba45c32d94f52b3a.worklet.js

I advise against using the inline loader because it places the artifact at the dist root by default, potentially leading to deployment complications.

Below is a guide outlining the basic setup:

// vue-config.js
configureWebpack: {
  module: {
    rules: [
      {
        test: /Worklet\.js$/,  <---- modify this to match your file naming conventions
        loader: 'worklet-loader',
        options: {
          name: 'js/[hash].worklet.js'
        }
      }
    ]
  }
}

// somewhere in vue code
import MyWorkletProcessor from './path/MyWorkletProcessor'
import MyWorkletNode from './path/MyWorkletNode'
...

try {
  await context.audioWorklet.addModule(MyWorkletProcessor)
  myWorkletNode = new MyWorkletNode(context)
  // or if no custom node
  // myWorkletNode = new AudioWorkletNode(context, 'my-worklet-processor') 
} catch (error) {
  // ...
}
// connect the workletNode input to a source node
someSourceNode.connect(myWorkletNode )
// connect the worklet output to some other node or destination
myWorkletNode.connect(context.destination)

// MyWorkletNode.js
export default class MyWorkletNode extends AudioWorkletNode {
   constructor(context) {
    super(context, 'my-worklet-processor')
    console.log(this.channelCount)
  }
}

// MyWorkletProcessor.js
class MyWorkletProcessor extends AudioWorkletProcessor {
  constructor() {
    super()
    this.port.postMessage('hello!')
  }

  process(inputs, outputs, parameters) {
    // audio processing code here.
    return true
  }
}
registerProcessor('my-worklet-processor', MyWorkletProcessor)

I have also created a relevant demo app demonstrating worklets running within Vue.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Error encountered: Array is undefined when using the map and subscribe functions in Ionic

I have developed a service that is supposed to retrieve data from a JSON file and assign it to an array called 'countries', which will be used throughout the application on multiple pages. However, when I call the method getCountries, the countri ...

Leverage the power of EJS and Node JS by incorporating node modules into

I am having trouble importing my datetimepicker JavaScript and style sheet into my EJS file. Unfortunately, the CSS and JS files are not rendering properly when I run the code. Below is how my code is structured: In the EJS file: <html> <meta n ...

Is it possible to create an <h1> heading that can be clicked like a button and actually do something when clicked?

I am currently designing a web page that includes <div class="cane-wrap"> <h1 class="mc">christmas tic tac toe</h1> </div> https://i.sstatic.net/R3Yps.png located at the top center of the webpage, with ...

Using Mocha with the --watch flag enabled causes issues with ES6 modules and results in error messages

I've been attempting to configure Mocha to automatically monitor for changes in my files using the --watch flag. I have defined two scripts in package.json as follows: "test": "mocha", "test:watch": "mocha --watch ./test ./game_logic" When I run ...

Show various error messages depending on the type of error detected

When pulling data from an API, my goal is to handle errors appropriately by displaying custom error messages based on the type of error that occurs. If the response is not okay, I want to throw an error and show its message. However, if there is a network ...

Sending data to a React Dialog component using the OnClick event

I am a beginner learning React.js and currently experimenting with passing parameters to a dialog box using onclick events. <IconButton className={classes.approvebutton} onClick={() => handleDialogClick("approve",1)}> <ThumbU ...

Place the div directly beside the input field on the right side

I am attempting to align a div directly beside the text being entered in a text input field. It seems logical to me that this could be achieved by measuring the length of the input value and positioning the div accordingly. However, the issue I am facing i ...

The de-duplication feature in webpack is not functioning properly when the splitChunks cacheGroups commons option is activated

In my lerna project, I have two identical packages named p1 and p2. Both p1 and p2 utilize a 3rd party package - in this case, eosjs@beta, which is approximately 50KB in size. When I incorporate p1 into an example react project, the package size increase ...

Is your server failing to respond to requests once there are too many within a session?

A web application I developed uses frequent $.ajax() calls to send and receive data between a virtual machine host and client. However, I have encountered a recurring issue where the connection cuts out after a certain number of consecutive calls within a ...

Web2py exhibits varying behavior between local and online versions, where it executes server code but results in a 404 error

When I run the request on my local version of the application using the code below, it successfully executes on the server. $.ajax({ type: 'POST', url: "{{=URL('default', 'serverFunction.json')}}", data: {id: id} }); Howe ...

Unable to prepend '1' to the list

My goal is to display a list as '1 2 3...', but instead it is showing '0 1 2...' var totalLessons = $('.lesson-nav .mod.unit.less li').length; for (var i = 0; i < totalLessons; i++) { $('.lesson-nav .mod.unit.les ...

iOS users may find that when a web page loads, it is often already scrolled halfway down

Encountering a problem with a long-scroll website that I'm currently developing. Whenever I access the page on my iPhone, the initial scroll position is consistently halfway down or near the bottom of the page. I've attempted to troubleshoot by d ...

What could be causing the issue with my date input not recognizing the model value?

As someone with a background in server-side development, I've been delving into CSS, Javascript, jQuery, and more to broaden my skills. I recently created a test project that loads a model and presents its values in basic text boxes. It functions corr ...

Load next.js images before the page finishes loading

Despite the conventional wisdom against it, I am exploring ways to preload a group of images before a page transition or prior to rendering my page. My specific scenario involves the need to display many large image files simultaneously and animate them on ...

Conceal a div element dynamically when clicking on another div

<script type="text/javascript"> function displayBookInfo(str) { if (str == "") { document.getElementById("more-info").innerHTML=""; return; } if (window.XMLHttpRequest) { // code for m ...

Key to Perform Right Click

Hey, I could use a little advice window.addEventListener('keyup', function (event) { if (document.activeElement && document.activeElement.tagName === 'INPUT') { return; } switch (String.fromCharCode(event.keyCode ...

Transmit the Selected Options from the Checkbox Categories

Here's an intriguing situation for you. I've got a webpage that dynamically generates groups of checkboxes, and their names are unknown until they're created. These groups could be named anything from "type" to "profile", and there's a ...

After a full day has passed, remove nodes from the Firebase database

Upon initializing my server, I populate Firebase with seed data. In the 24 hours that follow, users contribute additional data, but after this time period elapses, I aim to purge all user data while retaining the original seed information. What is the opt ...

The Fixed Navbar is causing sections to be slightly off from their intended positions

Utilizing a bootstrap navigation menu on my website with a fixed position. When clicking a menu item, it takes me to the designated section but slightly above the desired position. How can I ensure that it goes to the exact position upon clicking the men ...

The functionality of Google's AdMob in the context of Meteor.js/Cordova is currently not defined

I have been working on developing a mobile app specifically for android platforms using Meteor.js As I am nearing completion, I decided to integrate Google AdMob into my application. Unfortunately, despite my efforts, I could not find any suitable package ...