feat: use Edge TTS (Korean Hyunsu voice @ +45%) as the default voice
Some checks failed
Release / semantic-release (push) Successful in 31s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / build-linux (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
tests / Unit tests (Linux, Python 3.11) (push) Has been cancelled
Some checks failed
Release / semantic-release (push) Successful in 31s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / build-linux (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
tests / Unit tests (Linux, Python 3.11) (push) Has been cancelled
The user chose Microsoft Edge TTS, voice ko-KR-HyunsuMultilingualNeural at rate +45% (~1.45x), as the natural Korean voice. Wire it into the bridge and make it the default engine. - bridge/server.py: _edge_synthesize() calls edge-tts and transcodes the MP3 to PCM16 mono WAV with the system ffmpeg (temp file for a correct header); TTS_ENGINE default -> edge; EDGE_TTS_VOICE / EDGE_TTS_RATE env-driven - requirements-bridge.txt: add edge-tts (lightweight; httpx) - compose/.env.example/README: TTS_ENGINE=edge + EDGE_TTS_* knobs; note the online/privacy trade-off (reply text is sent to Microsoft, needs internet) - drop the now-unused MeloTTS build layer (Dockerfile) and melo-worker (supervisord) — edge synthesises in-process, no model/worker baked, slimmer and faster image; settings UI engine list -> edge/piper, restart only bridge Verified on host: edge-tts -> ffmpeg yields a valid 16-bit mono 24kHz WAV; envsubst renders tts_engine=edge; docker build --check + 26 tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -22,8 +22,7 @@ from typing import Any, Dict
|
||||
FIELDS = [
|
||||
("ollama_chat_model", "LLM 모델", "model"),
|
||||
("whisper_model", "STT(Whisper) 모델", "select:tiny,base,small,medium,large,large-v3"),
|
||||
("tts_engine", "TTS 엔진", "select:melo,piper"),
|
||||
("melo_speed", "TTS 속도 (MeloTTS)", "number:0.5:2.5:0.1"),
|
||||
("tts_engine", "TTS 엔진", "select:edge,piper"),
|
||||
("output_language", "출력 언어 (비우면 사용자 언어)", "text"),
|
||||
("llm_thinking_enabled", "LLM 사고(thinking) 모드", "bool"),
|
||||
("agentic_max_turns", "에이전트 최대 반복", "number:1:12:1"),
|
||||
@@ -54,9 +53,7 @@ def _current() -> Dict[str, Any]:
|
||||
cfg = _read_config()
|
||||
out: Dict[str, Any] = {}
|
||||
for k in _KEYS:
|
||||
if k == "melo_speed":
|
||||
out[k] = cfg.get("melo_speed", os.environ.get("MELO_SPEED", "1.5"))
|
||||
elif k == "output_language":
|
||||
if k == "output_language":
|
||||
out[k] = cfg.get("output_language", os.environ.get("OUTPUT_LANGUAGE", ""))
|
||||
else:
|
||||
out[k] = cfg.get(k, "")
|
||||
@@ -78,12 +75,7 @@ def _coerce(updates: Dict[str, Any]) -> Dict[str, Any]:
|
||||
for k, v in updates.items():
|
||||
if k not in _KEYS:
|
||||
continue
|
||||
if k == "melo_speed":
|
||||
try:
|
||||
v = float(v)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
elif k == "agentic_max_turns":
|
||||
if k == "agentic_max_turns":
|
||||
try:
|
||||
v = int(v)
|
||||
except (TypeError, ValueError):
|
||||
@@ -114,15 +106,15 @@ def _save(updates: Dict[str, Any]) -> None:
|
||||
|
||||
|
||||
def _apply() -> str:
|
||||
# Restart melo + bridge AFTER this response is sent. Detached (new session)
|
||||
# so the bridge being killed mid-restart doesn't drop the restart itself,
|
||||
# and the HTTP client still receives this response.
|
||||
# Restart the bridge AFTER this response is sent. Detached (new session) so
|
||||
# the bridge being killed mid-restart doesn't drop the restart itself, and
|
||||
# the HTTP client still receives this response. (Edge TTS has no worker.)
|
||||
try:
|
||||
subprocess.Popen(
|
||||
["sh", "-c", "sleep 1; supervisorctl restart melo-worker bridge"],
|
||||
["sh", "-c", "sleep 1; supervisorctl restart bridge"],
|
||||
start_new_session=True,
|
||||
)
|
||||
return "1초 후 브리지/TTS 워커가 재시작되어 반영됩니다."
|
||||
return "1초 후 브리지가 재시작되어 반영됩니다."
|
||||
except Exception as e: # pragma: no cover
|
||||
return str(e)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user