|
@@ -283,6 +283,34 @@ def _download_voice_file(voice_path: Path) -> Path:
|
|
|
return voice_path
|
|
return voice_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def resolve_voices_path() -> str:
|
|
|
|
|
+ voices_dir = Path(VOICES_DIR)
|
|
|
|
|
+ if voices_dir.is_dir():
|
|
|
|
|
+ voice_files = sorted(voices_dir.glob("*.bin"))
|
|
|
|
|
+ if not voice_files:
|
|
|
|
|
+ raise FileNotFoundError(f"voices 目录中没有可用的 .bin 音色文件: {voices_dir}")
|
|
|
|
|
+
|
|
|
|
|
+ packed_path = voices_dir / "_voices.generated.npz"
|
|
|
|
|
+ needs_rebuild = not packed_path.exists()
|
|
|
|
|
+ if not needs_rebuild:
|
|
|
|
|
+ packed_mtime = packed_path.stat().st_mtime
|
|
|
|
|
+ needs_rebuild = any(f.stat().st_mtime > packed_mtime for f in voice_files)
|
|
|
|
|
+
|
|
|
|
|
+ if needs_rebuild:
|
|
|
|
|
+ voice_map = {}
|
|
|
|
|
+ for voice_file in voice_files:
|
|
|
|
|
+ raw = np.fromfile(voice_file, dtype=np.float32)
|
|
|
|
|
+ if raw.size != 510 * 1 * 256:
|
|
|
|
|
+ raise ValueError(f"音色文件格式不正确: {voice_file}")
|
|
|
|
|
+ voice_map[voice_file.stem] = raw.reshape(510, 1, 256)
|
|
|
|
|
+ np.savez(packed_path, **voice_map)
|
|
|
|
|
+ return str(packed_path)
|
|
|
|
|
+
|
|
|
|
|
+ if Path(VOICES_V1_PATH).exists():
|
|
|
|
|
+ return VOICES_V1_PATH
|
|
|
|
|
+ raise FileNotFoundError(f"找不到 voices 目录或 voices-v1.0.bin: {voices_dir}, {VOICES_V1_PATH}")
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def load_onnx_session(name: str):
|
|
def load_onnx_session(name: str):
|
|
|
try:
|
|
try:
|
|
|
import onnxruntime as ort # type: ignore
|
|
import onnxruntime as ort # type: ignore
|
|
@@ -305,7 +333,11 @@ def load_kokoro_engine(name: str):
|
|
|
raise RuntimeError("无法导入 kokoro_onnx。请在部署环境中安装 kokoro-onnx。") from e
|
|
raise RuntimeError("无法导入 kokoro_onnx。请在部署环境中安装 kokoro-onnx。") from e
|
|
|
|
|
|
|
|
model_path = resolve_model_path(name)
|
|
model_path = resolve_model_path(name)
|
|
|
- return Kokoro(model_path=model_path, voices_path=VOICES_V1_PATH, vocab_config=CONFIG_PATH if Path(CONFIG_PATH).exists() else None)
|
|
|
|
|
|
|
+ return Kokoro(
|
|
|
|
|
+ model_path=model_path,
|
|
|
|
|
+ voices_path=resolve_voices_path(),
|
|
|
|
|
+ vocab_config=CONFIG_PATH if Path(CONFIG_PATH).exists() else None,
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_model(force_reload: bool = False, name: Optional[str] = None):
|
|
def load_model(force_reload: bool = False, name: Optional[str] = None):
|