2026-09-03 00:10:18 +04:00

40 lines
1.2 KiB
Python

"""Text helpers shared by the adapters."""
from __future__ import annotations
import re
_WHITESPACE = re.compile(r"\s+")
def normalise(text: str) -> str:
"""Collapse whitespace and trim. Keeps the robot from reading stray newlines."""
return _WHITESPACE.sub(" ", text or "").strip()
def is_cjk(char: str) -> bool:
code = ord(char)
return (
0x4E00 <= code <= 0x9FFF # CJK unified ideographs
or 0x3400 <= code <= 0x4DBF # extension A
or 0x3040 <= code <= 0x30FF # kana
or 0xAC00 <= code <= 0xD7AF # hangul
)
def estimate_speech_seconds(text: str, words_per_minute: int = 150) -> float:
"""Rough spoken duration.
Used only when the robot does not report utterance completion itself, so the
dashboard can still return to "Ready" at a believable moment instead of
hanging on "Speaking..." forever.
"""
cleaned = normalise(text)
if not cleaned:
return 0.0
cjk_chars = sum(1 for ch in cleaned if is_cjk(ch))
latin_words = len([w for w in cleaned.split() if any(not is_cjk(c) for c in w)])
# ~2.5 CJK characters per second is a typical TTS cadence.
seconds = (latin_words / max(60, words_per_minute)) * 60.0 + (cjk_chars / 2.5)
return max(0.8, seconds)