Do not auto-attribute segments that fuse several speakers' turns (v1.20.26)
A trailing inquit names only the last speaker, so applying it to a block holding multiple turns silently mis-credited the earlier one — a wrong attribution is invisible where an Unknown is not. Such blocks are now skipped by the grammar rules and left for the LLM pass or a manual split. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4d6eb7bd78
commit
14ed0c89e7
@ -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).
|
- **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.
|
- **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.26] — 2026-08-12
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Segments fusing two speakers' turns are no longer auto-attributed to one of them.** A trailing inquit only names the *last* speaker, so applying it to a block containing several turns ("…ausliefern und …" + "Er hat es nicht so gemeint" + ", unterbrach die blonde Perdia Lysandra.") silently mis-credited the earlier turn — worse than leaving it Unknown, because a wrong attribution is invisible while an Unknown is not. Blocks holding multiple turns are now skipped by the grammar rules and left for the LLM pass or manual splitting.
|
||||||
|
|
||||||
## [1.20.25] — 2026-08-12
|
## [1.20.25] — 2026-08-12
|
||||||
|
|
||||||
### Fixed
|
### 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="format-detection" content="telephone=no">
|
||||||
<meta name="color-scheme" content="light dark">
|
<meta name="color-scheme" content="light dark">
|
||||||
<meta name="theme-color" content="#2563EB">
|
<meta name="theme-color" content="#2563EB">
|
||||||
<meta name="app-version" content="1.20.25">
|
<meta name="app-version" content="1.20.26">
|
||||||
<link rel="manifest" href="/manifest.webmanifest">
|
<link rel="manifest" href="/manifest.webmanifest">
|
||||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||||
<link rel="apple-touch-icon" href="/static/icon.svg">
|
<link rel="apple-touch-icon" href="/static/icon.svg">
|
||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
||||||
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
||||||
<link rel="stylesheet" href="/static/style.css?v=1.20.25">
|
<link rel="stylesheet" href="/static/style.css?v=1.20.26">
|
||||||
|
|
||||||
|
|
||||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||||
@ -378,7 +378,7 @@ window.toggleNavTree = function(treeId, chevronId) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||||
<script src="/static/loader.js?v=1.20.25"></script>
|
<script src="/static/loader.js?v=1.20.26"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -804,8 +804,15 @@ function audiobookResolveUnknowns(segs, prevTail, roster) {
|
|||||||
// mistyped it as dialogue — confirmed live: the quote before such a segment
|
// mistyped it as dialogue — confirmed live: the quote before such a segment
|
||||||
// stayed Unknown purely because the inquit carried the wrong type. Accept
|
// stayed Unknown purely because the inquit carried the wrong type. Accept
|
||||||
// either type here and repair the type while we are at it.
|
// either type here and repair the type while we are at it.
|
||||||
const _nextIsInquitText = next && new RegExp('^\\W{0,3}(?:' + AB_SPEECH_VERBS + ')\\b').test(String(next.text || '').trim());
|
// A segment holding several turns separated by a blank line is TWO speakers
|
||||||
if (!who && (next?.type === 'narration' || _nextIsInquitText)) {
|
// fused into one ("...ausliefern und ...\n\nEr hat es nicht so gemeint" —
|
||||||
|
// Lysandra, then Perdia interrupting). A trailing inquit only names the LAST
|
||||||
|
// speaker, so applying it to the whole block silently mis-credits the earlier
|
||||||
|
// turn. Leaving it Unknown is the honest outcome: visibly unresolved beats
|
||||||
|
// confidently wrong, and the split can then be made by hand or by the LLM pass.
|
||||||
|
const _isFusedTurns = /\n\s*\n/.test(String(s.text || '').trim());
|
||||||
|
const _nextIsInquitText = !_isFusedTurns && next && new RegExp('^\\W{0,3}(?:' + AB_SPEECH_VERBS + ')\\b').test(String(next.text || '').trim());
|
||||||
|
if (!who && !_isFusedTurns && (next?.type === 'narration' || _nextIsInquitText)) {
|
||||||
const nt = String(next.text || '').trim();
|
const nt = String(next.text || '').trim();
|
||||||
// Split quote whose inquit uses a PRONOUN rather than a name:
|
// Split quote whose inquit uses a PRONOUN rather than a name:
|
||||||
// "»Ja, ungewöhnlich«" + ", antwortete er knapp." The rules below all
|
// "»Ja, ungewöhnlich«" + ", antwortete er knapp." The rules below all
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user