Files
unios-tts/app/segmentation.py
Shaman 82c306ff69 init
2026-10-01 07:38:01 +03:00

61 lines
2.0 KiB
Python

import re
from dataclasses import dataclass
from razdel import sentenize
from app.normalize import normalize_common, normalize_language
from app.ssml import DEFAULT_PAUSE_MS, explicit_pause_char
from app.translit import transliterate_latin
_CYRILIC_RE = re.compile(r'[\u0400-\u04FF]')
_PARAGRAPH_RE = re.compile(r"\n[ \t]*\n")
# Явная отметка паузы во входном тексте: `|||` (пауза по умолчанию) или
# `|||1500` (миллисекунды). Извлекается ДО нормализации, длительность
# ограничивается здесь, чтобы цифры не попадали в rutextnorm.
_EXPLICIT_PAUSE_RE = re.compile(r"\|\|\|(?:(\d+))?")
@dataclass
class Segment:
text: str
lang: str
para: int = 0
def split_sentences(text: str) -> list[str]:
return [s.text for s in sentenize(text)]
def split_paragraphs(text: str) -> list[str]:
return [p for p in (block.strip() for block in _PARAGRAPH_RE.split(text)) if p]
def extract_explicit_pauses(text: str) -> str:
def repl(m: re.Match) -> str:
ms = int(m.group(1)) if m.group(1) else DEFAULT_PAUSE_MS
return explicit_pause_char(ms)
return _EXPLICIT_PAUSE_RE.sub(repl, text)
def has_cyrillic(text: str) -> bool:
return bool(_CYRILIC_RE.search(text))
def detect_language(text: str) -> str:
return "ru" if has_cyrillic(text) else "en"
def prepare_segments(text: str) -> list[Segment]:
lang = detect_language(text)
text = extract_explicit_pauses(text)
text = normalize_common(text)
all_segments: list[Segment] = []
for para_idx, para in enumerate(split_paragraphs(text)):
for sent in split_sentences(para):
if lang == "ru":
sent = transliterate_latin(sent)
seg_text = normalize_language(sent, lang)
if seg_text.strip():
all_segments.append(Segment(text=seg_text, lang=lang, para=para_idx))
return all_segments