Attribute quotes from a following "X's Stimme" narration (v1.20.25)
"Darrags Stimme klang tonlos." after a quote names who just spoke, but the voice-announcement rule only looked at the narration before a line, so this mirror image stayed Unknown. Verified on the book (-> Darrag). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d3b162f81f
commit
4d6eb7bd78
@ -22,6 +22,11 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
||||
- **Emotion instructions are now always written in English**, even for non-English voices (the spoken text and the native-accent clause stay in the book's own language). Confirmed by controlled A/B testing — same line, same voice, only the instruct language varying — that Qwen3-TTS follows English emotion instructions far more reliably: German instructs produced barely-differentiated output, while English instructs yield a clean, correctly-ordered prosodic gradient (whisper 128 Hz → sad 142 → neutral 179 → scared 203 → happy 225 → angry 269 Hz), with sensible duration changes too (sad slowest, scared fastest).
|
||||
- **Fish-Speech generation parameters (`temperature` / `top_p` / `repetition_penalty`) were never forwarded.** Every Fish-Speech line synthesized at the server's fixed defaults, ignoring the app's per-backend stability settings — the only backend not routed through the shared `_apply_tts_extra_params` helper.
|
||||
|
||||
## [1.20.25] — 2026-08-12
|
||||
|
||||
### Fixed
|
||||
- **A genitive name attached to "Stimme" after a quote now names the speaker** ("Darrags Stimme klang tonlos." → Darrag). The existing voice-announcement rule only inspected the narration *before* a line, so this common mirror image was left Unknown.
|
||||
|
||||
## [1.20.24] — 2026-08-12
|
||||
|
||||
### Fixed
|
||||
|
||||
2
static/dist/main.min.js
vendored
2
static/dist/main.min.js
vendored
File diff suppressed because one or more lines are too long
@ -10,7 +10,7 @@
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="theme-color" content="#2563EB">
|
||||
<meta name="app-version" content="1.20.24">
|
||||
<meta name="app-version" content="1.20.25">
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/static/icon.svg">
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
||||
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.20.24">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.20.25">
|
||||
|
||||
|
||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||
@ -378,7 +378,7 @@ window.toggleNavTree = function(treeId, chevronId) {
|
||||
</script>
|
||||
|
||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||
<script src="/static/loader.js?v=1.20.24"></script>
|
||||
<script src="/static/loader.js?v=1.20.25"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -818,6 +818,16 @@ function audiobookResolveUnknowns(segs, prevTail, roster) {
|
||||
const byPronoun = lastNameIn(String(prev.text || ''));
|
||||
if (byPronoun) who = byPronoun;
|
||||
}
|
||||
// "Darrags Stimme klang tonlos." / "Marcians Stimme war heiser." — a
|
||||
// genitive name attached to Stimme in the narration right AFTER a quote
|
||||
// names who just spoke. The existing voice-announcement rule only looked
|
||||
// at the narration BEFORE the line, so this mirror image stayed Unknown.
|
||||
if (!who) {
|
||||
for (const n of names) {
|
||||
const esc = n.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
if (new RegExp('^\\W{0,3}' + esc + "(?:s|'s)?\\s+Stimme\\b", 'i').test(nt)) { who = n; break; }
|
||||
}
|
||||
}
|
||||
let m = who ? null : nt.match(new RegExp('^\\W{0,3}(?:' + AB_SPEECH_VERBS + ')\\s+(?:(?:der|die|das|den|dem)\\s+)?(?:[a-zäöüß]+e[nrms]?\\s+){0,2}' + _AB_NAME));
|
||||
if (!m) m = nt.match(new RegExp('^(?:Der|Die)\\s+' + _AB_NAME + ',\\s+(?:der|die)\\s+gesprochen hatte'));
|
||||
// "ertönte es plötzlich über ihm. Karyla hatte …" — impersonal formula,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user