Smooth Hermes TTS sentence transitions
This commit is contained in:
1 parent
cbc312257c
commit
5f3d064bb4
3 files changed
+110
-13
No files matched your search
@@ -132,6 +132,21 @@ class LanguageSegmentationTests(unittest.TestCase):
|
||||
self.assertIn("5 bis 6 Uhr", spoken)
|
||||
self.assertIn("Wind maximal 16 Kilometer pro Stunde", spoken)
|
||||
|
||||
def test_qwen_speaks_strict_date_ranges_as_calendar_dates(self):
|
||||
spoken = gateway.prepare_for_qwen_speech(
|
||||
"Neuigkeiten vom 04.–05.09. und Vergleich 04.09.–06.10.2026."
|
||||
)
|
||||
self.assertIn("4. bis 5. September", spoken)
|
||||
self.assertIn("4. September bis 6. Oktober 2026", spoken)
|
||||
|
||||
def test_qwen_does_not_treat_plain_number_ranges_as_dates(self):
|
||||
spoken = gateway.prepare_for_qwen_speech(
|
||||
"Version 3.8, Werte 11,3 bis 29,0 und Kontext 80–160K."
|
||||
)
|
||||
self.assertIn("Version 3.8", spoken)
|
||||
self.assertIn("11,3 bis 29,0", spoken)
|
||||
self.assertIn("80–160K", spoken)
|
||||
|
||||
def test_qwen_keeps_prosody_punctuation(self):
|
||||
spoken = gateway.prepare_for_qwen_speech(
|
||||
"Ist das gut? Ja! SarahTV: erreichbar."
|
||||
|
||||
@@ -224,6 +224,40 @@ def _spoken_date(match: re.Match) -> str:
|
||||
return result
|
||||
|
||||
|
||||
def _spoken_short_date_range(match: re.Match) -> str:
|
||||
first_day = int(match.group(1))
|
||||
last_day = int(match.group(2))
|
||||
month = int(match.group(3))
|
||||
year = match.group(4)
|
||||
month_name = GERMAN_MONTHS.get(month)
|
||||
if not month_name or not 1 <= first_day <= 31 or not 1 <= last_day <= 31:
|
||||
return match.group(0)
|
||||
result = f"{first_day}. bis {last_day}. {month_name}"
|
||||
if year:
|
||||
result += f" {year}"
|
||||
return result
|
||||
|
||||
|
||||
def _spoken_full_date_range(match: re.Match) -> str:
|
||||
first_day = int(match.group(1))
|
||||
first_month = int(match.group(2))
|
||||
last_day = int(match.group(3))
|
||||
last_month = int(match.group(4))
|
||||
year = match.group(5)
|
||||
first_name = GERMAN_MONTHS.get(first_month)
|
||||
last_name = GERMAN_MONTHS.get(last_month)
|
||||
if (not first_name or not last_name
|
||||
or not 1 <= first_day <= 31 or not 1 <= last_day <= 31):
|
||||
return match.group(0)
|
||||
if first_month == last_month:
|
||||
result = f"{first_day}. bis {last_day}. {last_name}"
|
||||
else:
|
||||
result = f"{first_day}. {first_name} bis {last_day}. {last_name}"
|
||||
if year:
|
||||
result += f" {year}"
|
||||
return result
|
||||
|
||||
|
||||
def _spell_digits(value: str) -> str:
|
||||
return " ".join(GERMAN_DIGITS[digit] for digit in value)
|
||||
|
||||
@@ -277,6 +311,20 @@ def normalize_for_german_speech(text: str) -> str:
|
||||
text,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
# Date ranges are deliberately strict: both variants require dotted
|
||||
# calendar notation, so ordinary numeric ranges remain untouched.
|
||||
text = re.sub(
|
||||
r"\b([0-3]?\d)\.([01]?\d)\.\s*[-‐‑‒–—−]\s*"
|
||||
r"([0-3]?\d)\.([01]?\d)\.(?:(\d{4})\b)?",
|
||||
_spoken_full_date_range,
|
||||
text,
|
||||
)
|
||||
text = re.sub(
|
||||
r"\b([0-3]?\d)\.\s*[-‐‑‒–—−]\s*"
|
||||
r"([0-3]?\d)\.([01]?\d)\.(?:(\d{4})\b)?",
|
||||
_spoken_short_date_range,
|
||||
text,
|
||||
)
|
||||
text = re.sub(
|
||||
r"\b([0-3]?\d)\.([01]?\d)\.(?:(\d{4})\b)?",
|
||||
_spoken_date,
|
||||
|
||||
Reference in new issue
Block a user