Randriamiandry commited on
Commit
bdabebb
·
1 Parent(s): f7be0cf

Correction chargement Kokoro avec chemins explicites

Browse files
Files changed (1) hide show
  1. app.py +34 -22
app.py CHANGED
@@ -8,29 +8,47 @@ from fastapi.staticfiles import StaticFiles
8
  from pydantic import BaseModel
9
  import soundfile as sf
10
  import time
 
11
 
12
  print("🚀 Démarrage API Kokoro-82M (ONNX rapide)")
13
 
14
  # -------------------------------------------------------------
15
- # Chargement du modèle via from_pretrained (recommandé)
16
  # -------------------------------------------------------------
17
- from kokoro_onnx import Kokoro
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- # Modèle par défaut (sera téléchargé automatiquement depuis HF)
20
- MODEL_NAME = "onnx-community/Kokoro-82M-v1.0-ONNX"
 
 
21
 
22
- tts = Kokoro.from_pretrained(MODEL_NAME, device="cpu")
23
  print("✅ Modèle Kokoro chargé avec succès")
24
 
25
- # Dictionnaire pour les voix clonées (si supporté)
26
  cloned_voices = {}
27
 
28
  # -------------------------------------------------------------
29
  # Application FastAPI
30
  # -------------------------------------------------------------
31
- app = FastAPI(title="Kokoro TTS API", version="2.2")
32
-
33
- # Servir l'interface HTML (optionnel)
34
  app.mount("/static", StaticFiles(directory="static"), name="static")
35
 
36
  @app.get("/")
@@ -38,6 +56,7 @@ async def root():
38
  return {
39
  "status": "ok",
40
  "model": "Kokoro-82M (ONNX)",
 
41
  "endpoints": ["/tts", "/clone-voice", "/voices"]
42
  }
43
 
@@ -47,7 +66,7 @@ async def demo():
47
 
48
  class TTSRequest(BaseModel):
49
  text: str
50
- voice: str = "af_heart" # voix par défaut (anglais)
51
  speed: float = 1.0
52
  lang: str = "fr"
53
 
@@ -58,25 +77,22 @@ async def generate_speech(request: TTSRequest):
58
  if not text:
59
  raise HTTPException(400, "Texte vide")
60
 
61
- # Choix de la voix : clonée ou intégrée
62
  voice = request.voice
63
  if voice in cloned_voices:
64
- voice = cloned_voices[voice] # peut être un chemin ou un identifiant
65
 
66
  try:
67
- # Génération audio
68
  audio, sample_rate = tts.tts(
69
  text=text,
70
  voice=voice,
71
  speed=request.speed,
72
  lang=request.lang
73
  )
74
- # Sauvegarde en mémoire
75
  buffer = io.BytesIO()
76
  sf.write(buffer, audio, sample_rate, format='WAV')
77
  buffer.seek(0)
78
 
79
- print(f"✅ Généré en {time.time()-start:.2f}s | voix={voice} | langue={request.lang}")
80
  return Response(content=buffer.read(), media_type="audio/wav")
81
  except Exception as e:
82
  raise HTTPException(500, f"Erreur TTS: {str(e)}")
@@ -86,21 +102,18 @@ async def clone_voice(audio_file: UploadFile = File(...), voice_name: str = Form
86
  if voice_name in cloned_voices:
87
  raise HTTPException(400, f"La voix '{voice_name}' existe déjà")
88
 
89
- # Sauvegarde du fichier temporaire
90
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp:
91
  content = await audio_file.read()
92
  tmp.write(content)
93
  tmp_path = tmp.name
94
 
95
  try:
96
- # Certaines versions supportent clone_voice
97
  if hasattr(tts, 'clone_voice'):
98
  cloned_voice = tts.clone_voice(tmp_path)
 
 
99
  else:
100
- # Fallback : on stocke le chemin (fonctionne si l'API l'accepte)
101
- cloned_voice = tmp_path
102
- cloned_voices[voice_name] = cloned_voice
103
- return {"message": f"Voix '{voice_name}' clonée", "voice_name": voice_name, "total": len(cloned_voices)}
104
  except Exception as e:
105
  raise HTTPException(500, f"Erreur clonage: {str(e)}")
106
  finally:
@@ -109,7 +122,6 @@ async def clone_voice(audio_file: UploadFile = File(...), voice_name: str = Form
109
 
110
  @app.get("/voices")
111
  async def list_voices():
112
- # Les voix intégrées sont dans tts.voices (si dispo)
113
  builtin = list(tts.voices.keys()) if hasattr(tts, 'voices') else []
114
  return {"builtin": builtin, "cloned": list(cloned_voices.keys())}
115
 
 
8
  from pydantic import BaseModel
9
  import soundfile as sf
10
  import time
11
+ from huggingface_hub import hf_hub_download
12
 
13
  print("🚀 Démarrage API Kokoro-82M (ONNX rapide)")
14
 
15
  # -------------------------------------------------------------
16
+ # Téléchargement des fichiers du modèle et des voix
17
  # -------------------------------------------------------------
18
+ REPO_ID = "onnx-community/Kokoro-82M-v1.0-ONNX"
19
+
20
+ # Télécharger les deux fichiers nécessaires
21
+ try:
22
+ model_path = hf_hub_download(
23
+ repo_id=REPO_ID,
24
+ filename="model.onnx",
25
+ cache_dir="/app/cache"
26
+ )
27
+ voices_path = hf_hub_download(
28
+ repo_id=REPO_ID,
29
+ filename="voices.json",
30
+ cache_dir="/app/cache"
31
+ )
32
+ print(f"✅ Modèle téléchargé : {model_path}")
33
+ print(f"✅ Voices téléchargées : {voices_path}")
34
+ except Exception as e:
35
+ raise RuntimeError(f"Échec du téléchargement : {e}")
36
 
37
+ # -------------------------------------------------------------
38
+ # Chargement de Kokoro avec les chemins explicites
39
+ # -------------------------------------------------------------
40
+ from kokoro_onnx import Kokoro
41
 
42
+ tts = Kokoro(model_path=model_path, voices_path=voices_path)
43
  print("✅ Modèle Kokoro chargé avec succès")
44
 
45
+ # Dictionnaire pour les voix clonées (optionnel)
46
  cloned_voices = {}
47
 
48
  # -------------------------------------------------------------
49
  # Application FastAPI
50
  # -------------------------------------------------------------
51
+ app = FastAPI(title="Kokoro TTS API", version="2.3")
 
 
52
  app.mount("/static", StaticFiles(directory="static"), name="static")
53
 
54
  @app.get("/")
 
56
  return {
57
  "status": "ok",
58
  "model": "Kokoro-82M (ONNX)",
59
+ "voices_available": list(tts.voices.keys()) if hasattr(tts, 'voices') else [],
60
  "endpoints": ["/tts", "/clone-voice", "/voices"]
61
  }
62
 
 
66
 
67
  class TTSRequest(BaseModel):
68
  text: str
69
+ voice: str = "af_heart"
70
  speed: float = 1.0
71
  lang: str = "fr"
72
 
 
77
  if not text:
78
  raise HTTPException(400, "Texte vide")
79
 
 
80
  voice = request.voice
81
  if voice in cloned_voices:
82
+ voice = cloned_voices[voice]
83
 
84
  try:
 
85
  audio, sample_rate = tts.tts(
86
  text=text,
87
  voice=voice,
88
  speed=request.speed,
89
  lang=request.lang
90
  )
 
91
  buffer = io.BytesIO()
92
  sf.write(buffer, audio, sample_rate, format='WAV')
93
  buffer.seek(0)
94
 
95
+ print(f"✅ Généré en {time.time()-start:.2f}s | voix={voice}")
96
  return Response(content=buffer.read(), media_type="audio/wav")
97
  except Exception as e:
98
  raise HTTPException(500, f"Erreur TTS: {str(e)}")
 
102
  if voice_name in cloned_voices:
103
  raise HTTPException(400, f"La voix '{voice_name}' existe déjà")
104
 
 
105
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp:
106
  content = await audio_file.read()
107
  tmp.write(content)
108
  tmp_path = tmp.name
109
 
110
  try:
 
111
  if hasattr(tts, 'clone_voice'):
112
  cloned_voice = tts.clone_voice(tmp_path)
113
+ cloned_voices[voice_name] = cloned_voice
114
+ return {"message": f"Voix '{voice_name}' clonée", "voice_name": voice_name}
115
  else:
116
+ raise HTTPException(501, "Clonage non supporté par cette version de kokoro-onnx")
 
 
 
117
  except Exception as e:
118
  raise HTTPException(500, f"Erreur clonage: {str(e)}")
119
  finally:
 
122
 
123
  @app.get("/voices")
124
  async def list_voices():
 
125
  builtin = list(tts.voices.keys()) if hasattr(tts, 'voices') else []
126
  return {"builtin": builtin, "cloned": list(cloned_voices.keys())}
127