diff --git a/static/index.html b/static/index.html index 75b4270..c796516 100644 --- a/static/index.html +++ b/static/index.html @@ -275,7 +275,7 @@ - + diff --git a/static/js/audiobook.js b/static/js/audiobook.js index 76eb04d..96453c8 100644 --- a/static/js/audiobook.js +++ b/static/js/audiobook.js @@ -164,7 +164,15 @@ function audiobookCastView(total) { if (ic) ic.className = 'mdi ' + (min ? 'mdi-window-maximize' : 'mdi-window-minimize'); }; ov.querySelector('#ab-cv-min').addEventListener('click', () => setMin(!ov.classList.contains('minimized'))); - ov.querySelector('#ab-cv-x').addEventListener('click', () => { if (_audiobook.running) _audiobook.cancel = true; else ov.remove(); }); + ov.querySelector('#ab-cv-x').addEventListener('click', () => { + if (_audiobook.running) { + _audiobook.cancel = true; + if (typeof _audiobook.abort === 'function') _audiobook.abort(); + ov.remove(); + } else { + ov.remove(); + } + }); ov.querySelector('#ab-cv-head').addEventListener('click', e => { if (ov.classList.contains('minimized') && !e.target.closest('button')) setMin(false); }); const fill = ov.querySelector('#ab-cv-fill'), count = ov.querySelector('#ab-cv-count'); const feed = ov.querySelector('#ab-cv-feed'), chars = ov.querySelector('#ab-cv-chars'); @@ -230,6 +238,9 @@ async function audiobookCast() { : [text]; _audiobook.running = true; _audiobook.cancel = false; + const ac = new AbortController(); + _audiobook.abort = () => ac.abort(); + const view = audiobookCastView(chunks.length); const llm_url = audiobookLlmUrl(), model = audiobookLlmModel(), language = audiobookLang(); @@ -254,11 +265,15 @@ async function audiobookCast() { try { const r = await fetch('/api/attribute-dialogue', { method: 'POST', headers: { 'Content-Type': 'application/json' }, + signal: ac.signal, body: JSON.stringify({ text: chunks[i], known_characters: roster.slice(-40), recent, language, llm_url, model }), }); if (!r.ok) { const e = await r.json().catch(() => ({})); throw new Error(e.detail || r.statusText); } data = await r.json(); - } catch (_) { data = null; } + } catch (err) { + if (err.name === 'AbortError') break; + data = null; + } let segs = data && Array.isArray(data.segments) ? data.segments : []; if (!segs.length) {