DOMException при горячей загрузке процессора веб-аудио рабочего места с модулями WASM из BLOB-объекта?
Я пытаюсь загрузить динамические рабочие листы Web Audio с импортом модуля WASM, перенесенного из кода C++, используя EMSCRIPTEN.
Я хочу манипулировать кодом рабочих листов в памяти, используя Blob для создания объектов, вставляя их в виде модулей в рабочий аудио-файл и заменяя их в горячем режиме.
Я следовал шаблону проектирования, предложенному в решении web-audio-samples, чтобы реализовать рабочие листы, которые импортируются как модуль WASM в рабочий лист. Кажется, это хорошо работает, когда код процессора находится в файле.
Горячая загрузка и замена рабочих листов из памяти без импорта внешних модулей WASM также, кажется, работают хорошо.
Вот как я создаю код для Blob. Для иллюстрации я использую файл simple-kernel.wasmmodule.js, скомпилированный с той же конфигурацией EMSCRIPTEN, что и пример шаблона проектирования WASM в примерах web-audio.
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 для создания объекта и загрузки его в рабочий лист.
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 или когда я загружаю их из файла. Если комментарий импортирует модуль и код модуля в конструкторе рабочего процесса и методе обработки, это работает.
Тем не менее, горячая загрузка рабочего листа с импортом WASM, похоже, не работает... Когда я пытаюсь это сделать, я получаю "Ошибка при загрузке рабочего стола: DOMException" и никакой другой подсказки.
Я подозреваю, что это может быть немного наивно, и что это может потребовать более сложной, такой как динамический импорт...
Я создал ветвь решения web-audio-samples, в которую добавил небольшой пример проекта (wasm-hot-loading), который создает условия для иллюстрации проблемы.
Это доступно здесь: https://github.com/mimic-sussex/web-audio-samples/tree/master/audio-worklet/design-pattern/wasm-hot-loading
Кто-нибудь может помочь пролить некоторый свет на то, что проблема может быть и возможно ли это?
Спасибо
Fo
1 ответ
Проблема в том, что источник вашего Worklet Processor непрозрачен. Это означает, что ваш относительный импорт не может быть разрешен изнутри этого скрипта.
Чтобы обойти это, вам нужно использовать абсолютные 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 Exception генерируется только при импорте в рабочем наборе. проблема была связана с расширением Chrome, называемым веб-аудиоинспектором, это расширение, безусловно, добавляет некоторую функцию обертывания вокруг рабочеголета, поскольку импорт не разрешен для вызова в функцию, импорт рабочеголета прерывается. В любом случае, удалили расширение, и проблема решена.