fix: OOV english words now transcribed via phonemize G2P + IPA
- Add phonemize (MIT) rule-based G2P as second fallback tier - IPA phoneme -> katakana CV-syllable transcription table - proposal -> プラポーザル, bilibili -> バイリーバイリー (no more letter-spelling) - Letter spelling kept as last resort only - Bridge logs SYNTH IN/OUT to stderr; tts.py drains stderr to Python logs so conversion results are visible in the server log - Rebuild portable zip (83.8 MB)
This commit is contained in:
@@ -45,6 +45,7 @@ class TTSBridge:
|
||||
self._process: asyncio.subprocess.Process | None = None
|
||||
self._bridge_script = bridge_script or _resolve_path("tts_bridge.js")
|
||||
self._node_exe = _get_node_exe()
|
||||
self._stderr_task: asyncio.Task | None = None
|
||||
|
||||
async def start(self) -> None:
|
||||
if not pathlib.Path(self._bridge_script).exists():
|
||||
@@ -61,6 +62,7 @@ class TTSBridge:
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
self._stderr_task = asyncio.create_task(self._drain_stderr())
|
||||
|
||||
line = await asyncio.wait_for(self._process.stdout.readline(), timeout=60)
|
||||
line_str = line.decode("utf-8").strip()
|
||||
@@ -73,6 +75,23 @@ class TTSBridge:
|
||||
|
||||
logger.info("Node.js TTS bridge ready.")
|
||||
|
||||
async def _drain_stderr(self) -> None:
|
||||
"""Continuously read bridge stderr and forward to Python logs."""
|
||||
if self._process is None or self._process.stderr is None:
|
||||
return
|
||||
try:
|
||||
while True:
|
||||
raw = await self._process.stderr.readline()
|
||||
if not raw:
|
||||
break
|
||||
line = raw.decode("utf-8", errors="replace").rstrip()
|
||||
if line:
|
||||
logger.info("[bridge] %s", line)
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
except Exception:
|
||||
logger.debug("Bridge stderr drain stopped", exc_info=True)
|
||||
|
||||
async def synthesize(self, kana_text: str) -> bytes:
|
||||
if self._process is None or self._process.stdin is None:
|
||||
raise RuntimeError("Bridge not started. Call start() first.")
|
||||
@@ -114,6 +133,13 @@ class TTSBridge:
|
||||
async def stop(self) -> None:
|
||||
if self._process is not None:
|
||||
logger.info("Stopping TTS bridge...")
|
||||
if self._stderr_task is not None:
|
||||
self._stderr_task.cancel()
|
||||
try:
|
||||
await self._stderr_task
|
||||
except (asyncio.CancelledError, Exception):
|
||||
pass
|
||||
self._stderr_task = None
|
||||
try:
|
||||
if self._process.stdin is not None:
|
||||
self._process.stdin.close()
|
||||
|
||||
Reference in New Issue
Block a user