Files
ai-spel-frontend/piper-runtime.js
T
Ein Anderssono 2acf1f2e82
Build and publish frontend / publish (push) Successful in 53s
Fix isolation headers for Piper worker
2026-10-16 06:59:37 +02:00

55 lines
1.8 KiB
JavaScript

const version = document.querySelector('#frontend-version')?.textContent || 'dev';
const workerUrl = `/tts/piper-wasm-v1/piper-worker.js?v=${encodeURIComponent(version)}`;
let worker;
let requestId = 0;
const pending = new Map();
function getWorker() {
if (worker) return worker;
worker = new Worker(workerUrl);
worker.onmessage = event => {
const message = event.data || {};
const request = pending.get(message.id);
if (!request) return;
if (message.type === 'progress') {
request.onProgress?.(message.progress);
} else {
pending.delete(message.id);
if (message.type === 'audio') request.resolve(new Blob([message.audio], {type: 'audio/x-wav'}));
else request.reject(new Error(message.error || 'Piper-arbetaren misslyckades.'));
}
};
worker.onerror = event => {
const details = [event.message, event.filename && `${event.filename}:${event.lineno || 0}:${event.colno || 0}`]
.filter(Boolean)
.join(' — ');
const error = new Error(details
? `Piper-arbetaren kunde inte startas: ${details}`
: 'Piper-arbetaren kunde inte startas.');
for (const request of pending.values()) request.reject(error);
pending.clear();
worker?.terminate();
worker = null;
};
worker.onmessageerror = () => {
const error = new Error('Piper-arbetaren skickade ett oläsbart svar.');
for (const request of pending.values()) request.reject(error);
pending.clear();
worker?.terminate();
worker = null;
};
return worker;
}
window.GamePiper = {
voiceId: 'sv_SE-nst-medium',
synthesize(text, onProgress) {
return new Promise((resolve, reject) => {
const id = ++requestId;
pending.set(id, {resolve, reject, onProgress});
try { getWorker().postMessage({id, text: String(text)}); }
catch (error) { pending.delete(id); reject(error); }
});
},
};