feat: 优化 AudioWorklet 加载逻辑,增加 Blob URL 兼容性和多基址回退方案
This commit is contained in:
@@ -478,11 +478,11 @@ export class S2sWsRealtimeClient extends EventTarget {
|
||||
}
|
||||
}
|
||||
|
||||
// The worklets live at the repo root, one level up from this module.
|
||||
// ?v=2 busts the browser cache so the fixed (unmuted) playback worklet
|
||||
// always loads instead of a stale muted copy.
|
||||
// 多基址回退:打包环境优先后端 http(tauri.localhost 无法加载 worklet 模块),
|
||||
// 浏览器开发回退页面源 / 相对路径。
|
||||
// AudioWorklet 加载(WebView2/打包兼容):
|
||||
// 1) 先直接 addModule(http 地址) —— 浏览器/常规环境快路径
|
||||
// 2) 失败则 fetch 源码 → Blob URL → addModule —— 打包 WebView2 下
|
||||
// tauri.localhost 自定义协议与跨域均受限,Blob 同源最稳
|
||||
// 3) 多个候选基址(后端 http / 页面源 / 相对路径)
|
||||
const candidates = [
|
||||
window.VOICE_WORKLETS_BASE,
|
||||
`${window.location.origin}/voice-worklets/`,
|
||||
@@ -490,6 +490,27 @@ export class S2sWsRealtimeClient extends EventTarget {
|
||||
].filter(Boolean);
|
||||
let workletErr = null;
|
||||
let workletOk = false;
|
||||
|
||||
const addViaBlob = async (name) => {
|
||||
for (const base of candidates) {
|
||||
try {
|
||||
const res = await fetch(base + name, { cache: "no-store" });
|
||||
if (!res.ok) continue;
|
||||
const src = await res.text();
|
||||
const url = URL.createObjectURL(new Blob([src], { type: "application/javascript" }));
|
||||
try {
|
||||
await ctx.audioWorklet.addModule(url);
|
||||
return true;
|
||||
} finally {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
} catch (err) {
|
||||
workletErr = err;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
for (const base of candidates) {
|
||||
try {
|
||||
await ctx.audioWorklet.addModule(base + "mic-capture.js?v=3");
|
||||
@@ -498,9 +519,16 @@ export class S2sWsRealtimeClient extends EventTarget {
|
||||
break;
|
||||
} catch (err) {
|
||||
workletErr = err;
|
||||
console.warn("[ws] worklet 加载失败,尝试备用地址:", base, err);
|
||||
console.warn("[ws] worklet 直接加载失败,改走 Blob 方案:", base, err);
|
||||
}
|
||||
}
|
||||
if (!workletOk) {
|
||||
// 回退:fetch → Blob → addModule(WebView2 打包环境最稳)
|
||||
const micOk = await addViaBlob("mic-capture.js?v=3");
|
||||
const playOk = await addViaBlob("audio-playback.js?v=3");
|
||||
workletOk = micOk && playOk;
|
||||
if (workletOk) console.info("[ws] AudioWorklet 已通过 Blob URL 加载(WebView2 兼容模式)");
|
||||
}
|
||||
if (!workletOk) throw workletErr || new Error("AudioWorklet 模块加载失败");
|
||||
|
||||
const captureNode = new AudioWorkletNode(ctx, "mic-capture", {
|
||||
|
||||
Reference in New Issue
Block a user