diff --git a/index.html b/index.html index aecff6b..76a3db5 100644 --- a/index.html +++ b/index.html @@ -170,7 +170,8 @@ const value = document.querySelector('#speech-progress-value'); const preparing = message.startsWith('Förbereder svensk uppläsning.'); const match = message.match(/^Hämtar svensk röstmodell till enheten: (\d+) procent\.$/); - if (!preparing && !match) { + const bytesMatch = message.match(/^Hämtar svensk röstmodell till enheten: ([\d.,]+) MB hämtade\.$/); + if (!preparing && !match && !bytesMatch) { container.hidden = true; progress.removeAttribute('value'); value.textContent = 'Väntar på nedladdning'; @@ -183,6 +184,11 @@ value.textContent = `${percent}%`; return true; } + if (bytesMatch) { + progress.removeAttribute('value'); + value.textContent = `${bytesMatch[1]} MB hämtade`; + return true; + } progress.removeAttribute('value'); value.textContent = 'Förbereder…'; return true; diff --git a/scripts/check-frontend.sh b/scripts/check-frontend.sh index 691084d..1d0071f 100755 --- a/scripts/check-frontend.sh +++ b/scripts/check-frontend.sh @@ -31,6 +31,7 @@ grep -q 'id="microphone" aria-pressed="false"' index.html grep -q 'id="voice-status" role="status" aria-live="polite"' index.html grep -q 'id="speech-progress" aria-label="Nedladdning av svensk röstmodell"' index.html grep -q 'id="speech-progress-value"' index.html +grep -q 'MB hämtade' index.html grep -q "window.GameVoice.createVoiceController" index.html grep -q "addVoiceButton(item, 'Testa ljudet'" index.html grep -q 'Jag förstår – starta mikrofonen' index.html diff --git a/tests/voice.test.cjs b/tests/voice.test.cjs index ae1e345..095cc6f 100644 --- a/tests/voice.test.cjs +++ b/tests/voice.test.cjs @@ -264,6 +264,8 @@ test('Piper model download progress is reported as a bounded percentage', async assert.match(h.states.at(-1).message, /50 procent/); h.piperProgressCallbacks[0]({loaded: 90_000_000, total: 63_000_000}); assert.match(h.states.at(-1).message, /100 procent/); + h.piperProgressCallbacks[0]({loaded: 10 * 1024 * 1024, total: 0}); + assert.match(h.states.at(-1).message, /10 MB hämtade/); }); test('Piper output keeps per-character pitch and rate stable', async () => { diff --git a/voice.js b/voice.js index 4545a43..3ea624a 100644 --- a/voice.js +++ b/voice.js @@ -250,13 +250,21 @@ setState('IDLE', 'Piper tog för lång tid på sig. Dialogen finns kvar som text. Tryck på Läs senaste repliken för att försöka igen.'); }, 180000); - let lastProgress = -1; + let lastProgressPercent = -1; + let lastProgressMegabytes = -1; const progress = event => { - if (token !== generation || !Number.isFinite(event?.loaded) || !Number.isFinite(event?.total) || event.total <= 0) return; - const percent = Math.max(0, Math.min(100, Math.floor((event.loaded / event.total) * 100))); - if (percent === lastProgress) return; - lastProgress = percent; - setState('PROCESSING', `Hämtar svensk röstmodell till enheten: ${percent} procent.`); + if (token !== generation || !Number.isFinite(event?.loaded) || event.loaded < 0) return; + if (Number.isFinite(event.total) && event.total > 0) { + const percent = Math.max(0, Math.min(100, Math.floor((event.loaded / event.total) * 100))); + if (percent === lastProgressPercent) return; + lastProgressPercent = percent; + setState('PROCESSING', `Hämtar svensk röstmodell till enheten: ${percent} procent.`); + return; + } + const megabytes = Math.floor((event.loaded / (1024 * 1024)) * 10) / 10; + if (megabytes === lastProgressMegabytes) return; + lastProgressMegabytes = megabytes; + setState('PROCESSING', `Hämtar svensk röstmodell till enheten: ${megabytes.toLocaleString('sv-SE')} MB hämtade.`); }; Promise.resolve()