2026-08-20 11:39:21 +08:00
|
|
|
|
"""从 narration.md 解析 SEG 分段,逐段调用 TTS 生成 MP3。"""
|
2026-09-08 00:07:26 +08:00
|
|
|
|
import os
|
2026-08-20 11:39:21 +08:00
|
|
|
|
import re
|
|
|
|
|
|
import subprocess
|
|
|
|
|
|
import sys
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
2026-09-08 00:07:26 +08:00
|
|
|
|
WS = Path(__file__).resolve().parent
|
|
|
|
|
|
plugin_dir = (os.environ.get("APS_AUDIO_GENERATION_PLUGIN") or "").strip()
|
|
|
|
|
|
voice_id = (os.environ.get("APS_TTS_VOICE_ID") or "").strip()
|
|
|
|
|
|
if not plugin_dir or not voice_id:
|
|
|
|
|
|
raise SystemExit("请配置 APS_AUDIO_GENERATION_PLUGIN 和 APS_TTS_VOICE_ID 后再生成配音")
|
|
|
|
|
|
PLUGIN = Path(plugin_dir).expanduser().resolve()
|
|
|
|
|
|
VOICE = voice_id
|
2026-08-20 11:39:21 +08:00
|
|
|
|
|
|
|
|
|
|
text = (WS / "narration.md").read_text(encoding="utf-8")
|
|
|
|
|
|
segments = re.findall(r"SEG (\d+)([^)]*)\s*\n(.*?)(?=\n\nSEG |\Z)", text, re.S)
|
|
|
|
|
|
print(f"共解析 {len(segments)} 段")
|
|
|
|
|
|
|
|
|
|
|
|
for num, body in segments:
|
|
|
|
|
|
out = WS / "audio" / f"seg{num}.mp3"
|
|
|
|
|
|
if out.exists() and out.stat().st_size > 10_000:
|
|
|
|
|
|
print(f"seg{num} 已存在,跳过")
|
|
|
|
|
|
continue
|
|
|
|
|
|
body = " ".join(body.split())
|
|
|
|
|
|
result = subprocess.run(
|
|
|
|
|
|
[sys.executable, str(PLUGIN / "scripts" / "audio_generation_tool.py"), "speech",
|
|
|
|
|
|
"--text", body, "--voice-id", VOICE, "--output", str(out)],
|
|
|
|
|
|
cwd=PLUGIN, capture_output=True, text=True, timeout=600,
|
|
|
|
|
|
)
|
|
|
|
|
|
ok = out.exists() and out.stat().st_size > 10_000
|
|
|
|
|
|
print(f"seg{num}: {'OK' if ok else 'FAIL'} ({len(body)} 字)")
|
|
|
|
|
|
if not ok:
|
|
|
|
|
|
print(result.stdout[-500:], result.stderr[-500:])
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
print("全部配音生成完成")
|