fix: explain why designed-voice benchmarks fail and stop batches on an unreachable service
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
f1b12993a1
commit
4d7434f9af
@ -6,6 +6,8 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
|||||||
---
|
---
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Fixed
|
||||||
|
- **Voice benchmark failures now say why.** Designed voices are benchmarked through the Voice Design engine; when that service is down the row showed a bare "-" and the raw "Max retries exceeded" text. The error now names the service and the container to start, the Factor and WPM columns show `ERR` beside the time column, and a batch stops after three identical "unreachable" failures instead of retrying every remaining voice.
|
||||||
### Added
|
### Added
|
||||||
- `scripts/compare_magazines.py`: read-only comparison of two magazine folders (words, boxes, reading order, articles, quality numbers) for re-import checks.
|
- `scripts/compare_magazines.py`: read-only comparison of two magazine folders (words, boxes, reading order, articles, quality numbers) for re-import checks.
|
||||||
|
|
||||||
|
|||||||
@ -310,7 +310,14 @@ def _voice_design_voice_request_audio(
|
|||||||
# randomness. See the config-side comment for the full story.
|
# randomness. See the config-side comment for the full story.
|
||||||
_apply_tts_extra_params(payload, settings, "voice_design_playback")
|
_apply_tts_extra_params(payload, settings, "voice_design_playback")
|
||||||
_apply_voice_pinned_seed(payload, voice, settings)
|
_apply_voice_pinned_seed(payload, voice, settings)
|
||||||
resp = _post_tts_with_fallback(f"{vd_url}/v1/audio/speech", payload, vd_hdrs, timeout=180)
|
try:
|
||||||
|
resp = _post_tts_with_fallback(f"{vd_url}/v1/audio/speech", payload, vd_hdrs, timeout=180)
|
||||||
|
except (requests.ConnectionError, requests.Timeout) as e:
|
||||||
|
# The raw "Max retries exceeded with url ..." text told the user nothing about what to do.
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Voice Design service unreachable at {vd_url} — start the "
|
||||||
|
f"'tts-faster-qwen3-tts-voicedesign' container (Engines tab) and retry"
|
||||||
|
) from e
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
audio = resp.content
|
audio = resp.content
|
||||||
if not audio:
|
if not audio:
|
||||||
|
|||||||
@ -434,7 +434,9 @@ function voiceFactor(v) {
|
|||||||
|
|
||||||
function fmtFactor(v) {
|
function fmtFactor(v) {
|
||||||
const f = voiceFactor(v);
|
const f = voiceFactor(v);
|
||||||
return f != null ? f.toFixed(2) + 'x' : '-';
|
if (f != null) return f.toFixed(2) + 'x';
|
||||||
|
const b = voiceBenchmark(v);
|
||||||
|
return b && !b.ok ? 'ERR' : '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
function fmtElapsed(v) {
|
function fmtElapsed(v) {
|
||||||
@ -932,7 +934,8 @@ async function runVoiceBenchmarkBatch() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setBenchmarkProgress(0, total, 'Starting benchmark...', stats);
|
setBenchmarkProgress(0, total, 'Starting benchmark...', stats);
|
||||||
for (let i = 0; i < voices.length; i++) {
|
let lastFailure = '', sameFailure = 0, aborted = false;
|
||||||
|
for (let i = 0; i < voices.length && !aborted; i++) {
|
||||||
const voice = voices[i];
|
const voice = voices[i];
|
||||||
const row = document.querySelector(`.vl-row[data-id="${CSS.escape(voice.id)}"]`);
|
const row = document.querySelector(`.vl-row[data-id="${CSS.escape(voice.id)}"]`);
|
||||||
if (row) {
|
if (row) {
|
||||||
@ -971,6 +974,14 @@ async function runVoiceBenchmarkBatch() {
|
|||||||
} else {
|
} else {
|
||||||
stats.errors++;
|
stats.errors++;
|
||||||
stats.last = `${voice.id}: failed${b && b.error ? ' · ' + b.error : ''}`;
|
stats.last = `${voice.id}: failed${b && b.error ? ' · ' + b.error : ''}`;
|
||||||
|
// The same unreachable service failing repeatedly means the rest will fail too.
|
||||||
|
const reason = b && b.error ? String(b.error) : '';
|
||||||
|
sameFailure = reason && reason === lastFailure ? sameFailure + 1 : 1;
|
||||||
|
lastFailure = reason;
|
||||||
|
if (/unreachable/i.test(reason) && sameFailure >= 3) {
|
||||||
|
toast(reason, 'error');
|
||||||
|
aborted = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|||||||
34
tests/test_benchmark_errors.py
Normal file
34
tests/test_benchmark_errors.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
"""A designed voice's benchmark must explain an unreachable Voice Design service."""
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
os.environ.setdefault("CONFIG_DIR", tempfile.mkdtemp(prefix="ttvc-test-config-"))
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from core import tts_helpers
|
||||||
|
|
||||||
|
|
||||||
|
class VoiceDesignUnreachableTest(unittest.TestCase):
|
||||||
|
def test_connection_error_becomes_actionable_message(self):
|
||||||
|
with mock.patch.object(tts_helpers, "_post_tts_with_fallback",
|
||||||
|
side_effect=requests.ConnectionError("Max retries exceeded")):
|
||||||
|
with self.assertRaises(RuntimeError) as ctx:
|
||||||
|
tts_helpers._voice_design_voice_request_audio(
|
||||||
|
"DE_F_Test", "Hallo", {"voice_design_url": "http://127.0.0.1:9"})
|
||||||
|
self.assertIn("Voice Design service unreachable", str(ctx.exception))
|
||||||
|
self.assertIn("tts-faster-qwen3-tts-voicedesign", str(ctx.exception))
|
||||||
|
|
||||||
|
def test_http_errors_are_not_masked(self):
|
||||||
|
resp = mock.Mock(status_code=500)
|
||||||
|
resp.raise_for_status.side_effect = requests.HTTPError("500")
|
||||||
|
with mock.patch.object(tts_helpers, "_post_tts_with_fallback", return_value=resp):
|
||||||
|
with self.assertRaises(requests.HTTPError):
|
||||||
|
tts_helpers._voice_design_voice_request_audio(
|
||||||
|
"DE_F_Test", "Hallo", {"voice_design_url": "http://127.0.0.1:9"})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Loading…
Reference in New Issue
Block a user