当从 Blob 热加载带有 Wasm 模块的 Web 音频工作处理器时,DOMException?



我正在尝试使用 Emscripten 从C++代码中转译的 Wasm 模块导入加载动态 Web 音频工作。

我想在内存中操作worklet代码,使用Blob创建对象,将它们作为模块注入音频Worklet,然后热交换它们。

我遵循了网络音频示例解决方案中建议的设计模式来实现作为 Wasm 模块导入工作块的工作。当处理器代码位于文件中时,这似乎效果很好。

无需外部 Wasm模块导入即可从内存热加载和交换工作日志似乎也运行良好。

这就是我为 Blob 创建代码的方式。为了说明我使用的是simple-kernel.wasmmodule.js它是使用与web-audio-samples中的Wasm设计模式示例相同的Emscripten配置编译的。

const blobCode = () => {
return `
import Module from './simple-kernel.wasmmodule.js';
import { RENDER_QUANTUM_FRAMES, MAX_CHANNEL_COUNT, HeapAudioBuffer } from '../lib/wasm-audio-helper.js';
class WASMWorkletProcessor extends AudioWorkletProcessor {
constructor() {
super();
// Allocate the buffer for the heap access. Start with stereo, but it can
// be expanded up to 32 channels.
this._heapInputBuffer = new HeapAudioBuffer(Module, RENDER_QUANTUM_FRAMES,
2, MAX_CHANNEL_COUNT);
this._heapOutputBuffer = new HeapAudioBuffer(Module, RENDER_QUANTUM_FRAMES,
2, MAX_CHANNEL_COUNT);
this._kernel = new Module.SimpleKernel();
}
process(inputs, outputs, parameters) {
.
.
.
return true;
}
}
registerProcessor('wasm-worklet-processor', WASMWorkletProcessor);`;
}

这就是我将代码与 Blob 一起使用来创建对象并将其加载到 worklet 中的方式。

const workletHotLoading = async (context) => {
const blob = new Blob([ blobCode() ], { type: "application/javascript; charset=utf-8" });
const workletUrl = window.URL.createObjectURL(blob);
await context.audioWorklet.addModule(workletUrl);
const oscillator = new OscillatorNode(context);
const wasmBlobWorkletNode = new AudioWorkletNode(context, 'wasm-worklet-processor');
wasmBlobWorkletNode.onprocessorerror = (event) => {
console.log(`An error from WASMWorkletProcessor.constructor() was detected.`);
};
oscillator.connect(wasmBlobWorkletNode).connect(context.destination);
oscillator.start();
};

我希望它能像没有 Wasm 导入的处理器一样工作,或者当我从文件中加载它们时。如果在 worklet 构造函数和流程方法中注释模块导入和模块代码,它将起作用。

但是,使用 Wasm 导入热加载工作包似乎不起作用......当我尝试这样做时,我得到"加载工作时出错:DOMException">并且没有其他线索。

我怀疑这可能有点幼稚,它可能需要更复杂的东西,例如动态导入......

我创建了一个网络音频样本解决方案的分支,其中我添加了一个小样本项目(wasm热加载),该项目创造了说明问题的条件。

可在此处获得: https://github.com/mimic-sussex/web-audio-samples/tree/master/audio-worklet/design-pattern/wasm-hot-loading

任何人都可以帮助阐明问题可能是什么以及这是否可行吗?

谢谢

问题是您的 Worklet 处理器的来源是不透明的。 这意味着无法从此脚本内部解析相对导入。

若要避免此问题,需要使用绝对 URI。

因此,您必须重写代码才能将正确的 baseURI 添加到导入语句中。由于此代码是从主 js 页面调用的,因此可以使用正确的格式构建此 blob 内容,例如使用 URL 构造函数及其第二个参数

const blobCode = () => {
return `
import Module from "${
// convert relative to absolute URL
new URL('./simple-kernel.wasmmodule.js', location.href)
}";
import { RENDER_QUANTUM_FRAMES, MAX_CHANNEL_COUNT, HeapAudioBuffer } from "${
new URL('../lib/wasm-audio-helper.js', location.href)
}";
class WASMWorkletProcessor extends AudioWorkletProcessor {
constructor() {
super();
[...]
`
};
console.log(blobCode());

我有一个类似的错误。仅当导入在工作包中时引发的 Dom 异常。 该问题是由于名为Web Audio Inspector的Chrome扩展程序引起的 此扩展肯定会在 worklet 周围添加一些包装函数,因为导入无权调用到函数中,因此 Worklet 导入会中断。 无论如何,卸载扩展程序并解决问题。

最新更新