我正在尝试使用带有AudioWorklet的vue-cli创建一个WebApp,但是在尝试访问我的AudioWorkletNode的任何属性时遇到了一堆错误,比如port或channelCount等:
TypeError: Illegal invocation at MyWorkletNode.invokeGetter
经过几个小时的谷歌搜索和调试,我认为它与类有关,AudioWorklet似乎只适用于ES6类,但vue-cli / babel / webpack中的一个是神奇的(我不知道它在哪里和它做什么)和转换将类转到常规构造函数或其他东西。或者也许它是worklet-loader进行转换?我不知道,我完全在黑暗中,不知道在哪里看。
如果我在没有任何捆绑器的情况下编写代码,只需使用vanilla JS,它可以工作,我没有收到任何错误。但我需要在我的vue项目中使用AudioWorklets,那么我的选择是什么?什么比禁用类转换更好?如果没有,我在哪里以及如何禁用它?
// main.js
import worklet from 'worklet-loader!./processor.js'
class MyWorkletNode extends AudioWorkletNode {
constructor(context) {
super(context, 'my-worklet-processor');
// Throws TypeError: Illegal invocation
console.log(this.channelCount);
}
}
this.audioCtx.audioWorklet.addModule(worklet).then(() => {
let node = new MyWorkletNode(this.audioCtx);
console.log("Loaded!");
// Throws 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);
如果没有更多的代码,很难说这里有什么问题。工件部分看起来正确。
但是为了回答一般性问题(后代),处理器必须在一个单独的包中加载到它自己的上下文中。当您使用worklet-loader时,导入实际上只是一个URL。
import MyWorkletProceessor from 'worklet-loader!./path/MyWorkletProcessor'
console.log(MyWorkletProcessor)
>5b91ba45c32d94f52b3a.worklet.js
我不建议使用内联加载器,因为默认情况下它会将工件置于dist根目录,这可能会导致部署问题。
这是基本设置的演练。
// vue-config.js
configureWebpack: {
module: {
rules: [
{
test: /Worklet\.js$/, <---- change this to match your filename 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)
我还制作了一个相关的demo app,显示了运行在vue中的worklet。