Aussprache-Wörterbuch: eigenes Modul, Wortgrenzen, gepflegte Liste, Kandidaten-Suche
Englische Fachbegriffe und fremde Eigennamen wurden auf Deutsch falsch vorgelesen
("Repository", "Donald Trump"). Chatterbox hat keinen Lautschrift-Eingang, also bleibt
nur die Umschrift in deutscher Rechtschreibung — die gab es zwar schon, aber nur als
kleines Dict im CLI-Skript, das keine andere Anwendung sinnvoll erweitern konnte.
Empirisch geprüft, warum es keinen besseren Weg gibt:
- Der multilinguale Tokenizer heißt "grapheme_mtl_merged_expanded_v1" und enthält zwar
IPA-Zeichen und ein [ipa]-Sprachtoken. generate() lehnt language_id="ipa" ab; umgeht
man nur die Whitelist, kommt Unsinn heraus: "ɹɪˈpɑzɪˌtɔɹi" klingt wie "Ripacitari",
"dɪˈplɔɪmənt" wie "Deep Romant" (per Whisper zurücktranskribiert). IPA ist tot.
- Der vorhandene Sprachwechsel im Satz ([en]...[/en]) synthetisiert die Teile korrekt,
klebt sie aber ohne Überblendung zusammen: gemessen 4 Nahtpausen von 0,5-0,8 s, der
Satz wächst von 3,9 s auf 7,1 s. Für Fließtext unbrauchbar.
Neu:
- pronunciation.py — eigenständiges Modul, reine Standardbibliothek (kein torch), damit
CLI, HTTP-Service, MCP-Adapter und fremde Projekte (Open Notebook) dasselbe Wörterbuch
nutzen können, ohne das Modell zu laden. Namen werden aus chatterbox_cli_v4
re-exportiert, bestehende Importe bleiben gültig.
- Ladereihenfolge mit Vorrang: eingebaut -> pronunciation/<lang>.json (mitgeliefert) ->
~/.config/chatterbox/pronunciation/<lang>.json -> $CHATTERBOX_PRONUNCIATION_DICT ->
explizit übergebenes Dict. Kaputte JSON-Dateien werden gemeldet, nicht fatal.
- pronunciation/de.json — kuratierte Einträge (Tech, KI, Firmen, Personen, Medien).
- pronunciation_candidates.py — findet in einem Text alles, was hunspell (de) nicht kennt
und noch nicht im Wörterbuch steht. An einem echten Podcast-Transkript getestet: 61
Kandidaten, darunter Voicebox, Scrapling, Scraping.
Fehlerbehebung: Ersetzt wird jetzt an Wortgrenzen und in einem einzigen Durchgang. Das
alte str.replace() machte aus "UNESCO" ein "Uh EnnESCO" und aus "UNIX" ein "Uh EnnIX",
weil der Eintrag "UN" auch mitten im Wort traf.
Verifiziert: 199 Einträge laden in 44 ms ohne torch; UNESCO/UNIX/Xiaomi bleiben intakt;
Open Notebooks TTS-Server spricht die Umschrift ohne eine einzige Codeänderung dort; der
MCP-Service auf :9999 läuft unverändert weiter.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
1ce6540711
commit
cd9383ff88
6 changed files with 570 additions and 50 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import argparse
|
||||
import importlib.util
|
||||
import json
|
||||
import queue
|
||||
import re
|
||||
import sys
|
||||
|
|
@ -187,47 +188,15 @@ UNIT_REPLACEMENTS = {
|
|||
"%": "Prozent",
|
||||
}
|
||||
|
||||
# Eingebaute phonetische Annäherungen für häufige Fremdnamen und Anglizismen (Deutsch).
|
||||
# Nur Begriffe aufnehmen, bei denen das deutsche TTS eine falsche Aussprache produziert.
|
||||
# Anglizismen wie "Cloud", "Update", "Meeting" klingen auf Deutsch akzeptabel → kein Eintrag.
|
||||
DEFAULT_PRONUNCIATION_DE: dict[str, str] = {
|
||||
# Chinesische Eigennamen
|
||||
"Xi Jinping": "Schi Jinping",
|
||||
"Xi": "Schi",
|
||||
"Jinping": "Jinping",
|
||||
"Peking": "Peking",
|
||||
# Tech-Markennamen mit problematischer Aussprache
|
||||
"GitHub": "Git Hab",
|
||||
"LinkedIn": "Linked In",
|
||||
"YouTube": "Jutjub",
|
||||
"Wi-Fi": "Wai Fai",
|
||||
"iPhone": "Aiphone",
|
||||
"MacBook": "Mäk Buk",
|
||||
"ChatGPT": "Tschet Dschie Pie Tie",
|
||||
"OpenAI": "Open A I",
|
||||
"Anthropic": "Enthropik",
|
||||
"Claude": "Kloode",
|
||||
# KI-Begriffe
|
||||
"GPT": "Dschie Pie Tie",
|
||||
"LLM": "El El Em",
|
||||
# Sonstige
|
||||
"UN": "Uh En",
|
||||
"ARD": "Ah Er Dee",
|
||||
"ZDF": "Tset De Eff",
|
||||
"RTL": "Er Te El",
|
||||
"AFD": "Ah Eff Dee",
|
||||
"AfD": "Ah Eff Dee",
|
||||
"CDU": "Tse De Uh",
|
||||
"SPD": "Es Pe Dee",
|
||||
"FDP": "Eff De Pee",
|
||||
"BSW": "Be Es Wee",
|
||||
}
|
||||
|
||||
|
||||
def apply_pronunciation_dict(text: str, pron_dict: dict[str, str]) -> str:
|
||||
for phrase, replacement in sorted(pron_dict.items(), key=lambda x: len(x[0]), reverse=True):
|
||||
text = text.replace(phrase, replacement)
|
||||
return text
|
||||
# Aussprache-Wörterbuch: liegt in pronunciation.py (ohne torch-Abhängigkeit, damit
|
||||
# es auch schlanke Werkzeuge und fremde Anwendungen nutzen können). Die Namen werden
|
||||
# hier re-exportiert, damit bestehende Importe von chatterbox_cli_v4 weiter greifen.
|
||||
from pronunciation import ( # noqa: E402
|
||||
DEFAULT_PRONUNCIATION_DE,
|
||||
PRONUNCIATION_ENV,
|
||||
apply_pronunciation_dict,
|
||||
load_pronunciation_dict,
|
||||
)
|
||||
|
||||
|
||||
import unicodedata as _unicodedata
|
||||
|
|
@ -591,11 +560,12 @@ def preprocess_tts_text(
|
|||
if acronym_mode is None:
|
||||
acronym_mode = "german" if lang == "de" else "period_space"
|
||||
|
||||
# 1. Aussprache-Wörterbuch zuerst (vor Akronym-Expansion, damit Eigennamen greifen)
|
||||
if lang == "de":
|
||||
text = apply_pronunciation_dict(text, DEFAULT_PRONUNCIATION_DE)
|
||||
if pronunciation_dict:
|
||||
text = apply_pronunciation_dict(text, pronunciation_dict)
|
||||
# 1. Aussprache-Wörterbuch zuerst (vor Akronym-Expansion, damit Eigennamen greifen).
|
||||
# load_pronunciation_dict() fuegt eingebaute, mitgelieferte, benutzereigene und
|
||||
# per Umgebungsvariable gesetzte Eintraege zusammen; `pronunciation_dict` (vom
|
||||
# Aufrufer) hat Vorrang. In EINEM Durchgang ersetzen, damit eine Ersetzung nicht
|
||||
# erneut von einem anderen Eintrag getroffen wird.
|
||||
text = apply_pronunciation_dict(text, load_pronunciation_dict(lang, pronunciation_dict))
|
||||
|
||||
if normalize_units_values:
|
||||
text = normalize_units(text, lang)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue