MarneMorgan commited on
Commit
c5ceb20
·
verified ·
1 Parent(s): bf97b2b

Create voices.py

Browse files
Files changed (1) hide show
  1. voices.py +66 -0
voices.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import requests
4
+ from pathlib import Path
5
+
6
+ HF_VOICES_JSON_URL = os.getenv("HF_VOICES_JSON_URL", "")
7
+ HF_VOICES_BASE_URL = os.getenv("HF_VOICES_BASE_URL", "")
8
+ LOCAL_VOICES_DIR = Path(os.getenv("LOCAL_VOICES_DIR", "/tmp/voices"))
9
+
10
+ LOCAL_VOICES_DIR.mkdir(parents=True, exist_ok=True)
11
+
12
+ class VoiceRegistry:
13
+ def __init__(self):
14
+ self._voices = None
15
+
16
+ def load(self):
17
+ if self._voices is not None:
18
+ return self._voices
19
+ if not HF_VOICES_JSON_URL:
20
+ raise RuntimeError("HF_VOICES_JSON_URL is not set")
21
+
22
+ r = requests.get(HF_VOICES_JSON_URL, timeout=60)
23
+ r.raise_for_status()
24
+ self._voices = r.json()
25
+ return self._voices
26
+
27
+ def list_voice_ids(self):
28
+ v = self.load()
29
+ return sorted(list(v.keys()))
30
+
31
+ def ensure_voice(self, voice_id: str) -> dict:
32
+ voices = self.load()
33
+ if voice_id not in voices:
34
+ raise KeyError(f"Unknown voiceId: {voice_id}")
35
+
36
+ meta = voices[voice_id]
37
+ rel_model = meta["model"] # e.g. "voices/en_US-amy.onnx"
38
+ rel_json = meta.get("config") # optional: "voices/en_US-amy.onnx.json"
39
+
40
+ model_path = LOCAL_VOICES_DIR / Path(rel_model).name
41
+ if not model_path.exists():
42
+ if not HF_VOICES_BASE_URL:
43
+ raise RuntimeError("HF_VOICES_BASE_URL is not set")
44
+ url = f"{HF_VOICES_BASE_URL.rstrip('/')}/{rel_model}"
45
+ self._download(url, model_path)
46
+
47
+ config_path = None
48
+ if rel_json:
49
+ config_path = LOCAL_VOICES_DIR / Path(rel_json).name
50
+ if not config_path.exists():
51
+ url = f"{HF_VOICES_BASE_URL.rstrip('/')}/{rel_json}"
52
+ self._download(url, config_path)
53
+
54
+ return {
55
+ "voiceId": voice_id,
56
+ "modelPath": str(model_path),
57
+ "configPath": str(config_path) if config_path else None,
58
+ **meta,
59
+ }
60
+
61
+ def _download(self, url: str, dst: Path):
62
+ r = requests.get(url, timeout=120)
63
+ r.raise_for_status()
64
+ dst.write_bytes(r.content)
65
+
66
+ registry = VoiceRegistry()