한국어 우선 MeloTTS 웹 서비스 추가 (GPU, 속도/피치, 로그인 없음)

- FastAPI 백엔드: /api/voices, /api/tts, /api/health
- 한국어 메인 + 영어(5종 악센트), 중국어/일본어 UI 제거
- 언어별 목소리 모델 선택, 속도(0.5~2.0x)/피치(±12반음) 조절
- 로그인/사용제한/과금 유도 없음 (무제한 테스트)
- NVIDIA GPU 자동 사용 (torch cu128, Blackwell sm_120)
- 유저 친화 한국어 UI (frontend)
- Docker/compose (GPU 예약), 8788 포트
- MeloTTS(순수 파이썬) 벤더링 + 검증된 버전 고정(constraints)
This commit is contained in:
claude
2026-08-23 21:57:48 +09:00
parent a6f3bac584
commit f197177ae1
77 changed files with 11621 additions and 1 deletions

View File

@@ -0,0 +1,122 @@
"""Set of default text cleaners"""
# TODO: pick the cleaner for languages dynamically
import re
from .french_abbreviations import abbreviations_fr
# Regular expression matching whitespace:
_whitespace_re = re.compile(r"\s+")
rep_map = {
":": ",",
";": ",",
",": ",",
"。": ".",
"!": "!",
"?": "?",
"\n": ".",
"·": ",",
"、": ",",
"...": ".",
"…": ".",
"$": ".",
"“": "",
"”": "",
"‘": "",
"’": "",
"(": "",
")": "",
"(": "",
")": "",
"《": "",
"》": "",
"【": "",
"】": "",
"[": "",
"]": "",
"—": "",
"~": "-",
"~": "-",
"「": "",
"」": "",
"¿" : "",
"¡" : ""
}
def replace_punctuation(text):
pattern = re.compile("|".join(re.escape(p) for p in rep_map.keys()))
replaced_text = pattern.sub(lambda x: rep_map[x.group()], text)
return replaced_text
def expand_abbreviations(text, lang="fr"):
if lang == "fr":
_abbreviations = abbreviations_fr
for regex, replacement in _abbreviations:
text = re.sub(regex, replacement, text)
return text
def lowercase(text):
return text.lower()
def collapse_whitespace(text):
return re.sub(_whitespace_re, " ", text).strip()
def remove_punctuation_at_begin(text):
return re.sub(r'^[,.!?]+', '', text)
def remove_aux_symbols(text):
text = re.sub(r"[\<\>\(\)\[\]\"\«\»]+", "", text)
return text
def replace_symbols(text, lang="en"):
"""Replace symbols based on the lenguage tag.
Args:
text:
Input text.
lang:
Lenguage identifier. ex: "en", "fr", "pt", "ca".
Returns:
The modified text
example:
input args:
text: "si l'avi cau, diguem-ho"
lang: "ca"
Output:
text: "si lavi cau, diguemho"
"""
text = text.replace(";", ",")
text = text.replace("-", " ") if lang != "ca" else text.replace("-", "")
text = text.replace(":", ",")
if lang == "en":
text = text.replace("&", " and ")
elif lang == "fr":
text = text.replace("&", " et ")
elif lang == "pt":
text = text.replace("&", " e ")
elif lang == "ca":
text = text.replace("&", " i ")
text = text.replace("'", "")
elif lang== "es":
text=text.replace("&","y")
text = text.replace("'", "")
return text
def french_cleaners(text):
"""Pipeline for French text. There is no need to expand numbers, phonemizer already does that"""
text = expand_abbreviations(text, lang="fr")
# text = lowercase(text) # as we use the cased bert
text = replace_punctuation(text)
text = replace_symbols(text, lang="fr")
text = remove_aux_symbols(text)
text = remove_punctuation_at_begin(text)
text = collapse_whitespace(text)
text = re.sub(r'([^\.,!\?\-…])$', r'\1.', text)
return text