feat: play cached TTS audio immediately on auto-start if already generated
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled

This commit is contained in:
Admin
2026-03-03 13:46:37 +05:00
parent f28de2195d
commit 09e90d2ab0
2 changed files with 69 additions and 12 deletions

View File

@@ -2922,21 +2922,43 @@ const chapterTmpl = `
navigator.mediaSession.setActionHandler('seekto', function(d) { if (isFinite(d.seekTime)) { audio.currentTime = d.seekTime; updateSeek(); } });
}
function loadAndPlay(url) {
// Always set autoplay=true before load(): the browser needs this hint set
// synchronously before load() regardless of whether we got here via a user
// gesture or a programmatic trigger (e.g. chapter transition). The canplay
// handler will call play() as well, but autoplay on the element is the only
// reliable path after an async fetch where the gesture stack is gone.
audio.autoplay = true;
audio.src = url; audio.load();
audio.playbackRate = getSpeed();
registerMediaSession();
}
function startAudio(autoplay) {
setGenerating();
highlightPara(0);
generateAudio(CHAPTER_N, function (url) {
if (stale()) return;
// Always set autoplay=true before load(): the browser needs this hint set
// synchronously before load() regardless of whether we got here via a user
// gesture or a programmatic trigger (e.g. chapter transition). The canplay
// handler will call play() as well, but autoplay on the element is the only
// reliable path after an async fetch where the gesture stack is gone.
audio.autoplay = true;
audio.src = url; audio.load();
audio.playbackRate = getSpeed();
registerMediaSession();
});
// Check if audio was already generated for this chapter this session.
// If so, play it directly without re-generating.
fetch('/ui/audio/' + SLUG + '/' + CHAPTER_N + '?voice=' + encodeURIComponent(voiceSel.value) + '&speed=1')
.then(function(res) {
if (stale()) return;
if (res.ok) {
return res.json().then(function(data) {
if (stale()) return;
if (data && data.url) { loadAndPlay(data.url); return; }
throw new Error('no url in response');
});
}
// Not cached yet — fall through to generation.
generateAudio(CHAPTER_N, function(url) {
if (stale()) return;
loadAndPlay(url);
});
})
.catch(function(e) {
if (stale()) return;
setError(e.message);
});
}
window.ttsToggle = function () {