AthanasiusRG commited on
Commit
a10e4f8
Β·
verified Β·
1 Parent(s): f4f68ae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -65
app.py CHANGED
@@ -4,11 +4,18 @@ import shutil
4
  import tempfile
5
  from fastapi import FastAPI, UploadFile, File, Form, HTTPException
6
  from fastapi.responses import FileResponse
7
- from core.cloner import KokoClone
8
 
9
- # ── Chargement unique des modΓ¨les ─────────────────────────────────────────────
10
- print("Loading KokoClone models...")
11
- cloner = KokoClone()
 
 
 
 
 
 
 
 
12
 
13
 
14
  # ── Handlers Gradio ───────────────────────────────────────────────────────────
@@ -18,7 +25,7 @@ def gradio_speak(text, lang, speed):
18
  raise gr.Error("Veuillez entrer du texte.")
19
  output_file = "/tmp/gradio_speak_output.wav"
20
  try:
21
- cloner.speak(text=text, lang=lang, output_path=output_file, speed=float(speed))
22
  return output_file
23
  except Exception as e:
24
  raise gr.Error(f"Erreur : {str(e)}")
@@ -31,7 +38,7 @@ def gradio_clone(text, lang, ref_audio_path):
31
  raise gr.Error("Please upload or record a reference audio file.")
32
  output_file = "/tmp/gradio_clone_output.wav"
33
  try:
34
- cloner.generate(text=text, lang=lang, reference_audio=ref_audio_path, output_path=output_file)
35
  return output_file
36
  except Exception as e:
37
  raise gr.Error(f"An error occurred: {str(e)}")
@@ -44,15 +51,15 @@ def gradio_convert(source_audio_path, ref_audio_path):
44
  raise gr.Error("Please upload a reference audio file.")
45
  output_file = "/tmp/gradio_convert_output.wav"
46
  try:
47
- cloner.convert(source_audio=source_audio_path, reference_audio=ref_audio_path, output_path=output_file)
48
  return output_file
49
  except Exception as e:
50
  raise gr.Error(f"An error occurred: {str(e)}")
51
 
52
 
53
- # ── Interface Gradio (Gradio 6 compatible) ────────────────────────────────────
54
 
55
- with gr.Blocks() as demo: # theme retirΓ© ici β†’ va dans launch()
56
  gr.Markdown(
57
  """
58
  <div style="text-align: center;">
@@ -64,11 +71,8 @@ with gr.Blocks() as demo: # theme retirΓ© ici β†’ va dans launch()
64
 
65
  with gr.Tabs():
66
 
67
- # ── Onglet 1 : TTS Simple ─────────────────────────────────────────────
68
  with gr.Tab("πŸ—£οΈ Simple TTS"):
69
- gr.Markdown(
70
- "Génère la parole avec une voix Kokoro — **aucun audio de référence requis**."
71
- )
72
  with gr.Row():
73
  with gr.Column(scale=1):
74
  speak_text = gr.Textbox(
@@ -96,13 +100,8 @@ with gr.Blocks() as demo: # theme retirΓ© ici β†’ va dans launch()
96
  step=0.1
97
  )
98
  speak_btn = gr.Button("πŸ—£οΈ GΓ©nΓ©rer l'audio", variant="primary")
99
-
100
  with gr.Column(scale=1):
101
- speak_out = gr.Audio(
102
- label="Audio gΓ©nΓ©rΓ©",
103
- interactive=False,
104
- autoplay=True
105
- )
106
  gr.Markdown(
107
  """
108
  **Voix disponibles**
@@ -115,49 +114,30 @@ with gr.Blocks() as demo: # theme retirΓ© ici β†’ va dans launch()
115
  > Vitesse **0.7–0.8** recommandΓ©e pour les apprenants dΓ©butants.
116
  """
117
  )
118
-
119
  speak_btn.click(
120
  fn=gradio_speak,
121
  inputs=[speak_text, speak_lang, speak_speed],
122
  outputs=speak_out
123
  )
124
 
125
- # ── Onglet 2 : Text β†’ Clone ───────────────────────────────────────────
126
  with gr.Tab("🎀 Text β†’ Clone"):
127
  gr.Markdown("SynthΓ©tise le texte puis applique la voix d'un audio de rΓ©fΓ©rence.")
128
  with gr.Row():
129
  with gr.Column(scale=1):
130
- clone_text = gr.Textbox(
131
- label="1. Texte Γ  synthΓ©tiser",
132
- lines=4,
133
- placeholder="Enter the text you want spoken..."
134
- )
135
  clone_lang = gr.Dropdown(
136
  label="2. Langue",
137
  choices=[
138
- ("English", "en"),
139
- ("FranΓ§ais", "fr"),
140
- ("Hindi", "hi"),
141
- ("Japanese", "ja"),
142
- ("Chinese", "zh"),
143
- ("EspaΓ±ol", "es"),
144
- ("Italiano", "it"),
145
- ("PortuguΓͺs", "pt"),
146
  ],
147
  value="en"
148
  )
149
- clone_ref = gr.Audio(
150
- label="3. Audio de rΓ©fΓ©rence",
151
- type="filepath"
152
- )
153
  clone_btn = gr.Button("πŸš€ GΓ©nΓ©rer avec clonage", variant="primary")
154
-
155
  with gr.Column(scale=1):
156
- clone_out = gr.Audio(
157
- label="Audio clonΓ©",
158
- interactive=False,
159
- autoplay=False
160
- )
161
  gr.Markdown(
162
  """
163
  **Conseils**
@@ -166,34 +146,21 @@ with gr.Blocks() as demo: # theme retirΓ© ici β†’ va dans launch()
166
  - La langue doit correspondre au texte
167
  """
168
  )
169
-
170
  clone_btn.click(
171
  fn=gradio_clone,
172
  inputs=[clone_text, clone_lang, clone_ref],
173
  outputs=clone_out
174
  )
175
 
176
- # ── Onglet 3 : Audio β†’ Clone ──────────────────────────────────────────
177
  with gr.Tab("πŸ” Audio β†’ Clone"):
178
  gr.Markdown("Re-voice un audio existant pour qu'il sonne comme la voix de rΓ©fΓ©rence.")
179
  with gr.Row():
180
  with gr.Column(scale=1):
181
- convert_src = gr.Audio(
182
- label="1. Audio source",
183
- type="filepath"
184
- )
185
- convert_ref = gr.Audio(
186
- label="2. Voix de rΓ©fΓ©rence",
187
- type="filepath"
188
- )
189
  convert_btn = gr.Button("πŸ” Convertir la voix", variant="primary")
190
-
191
  with gr.Column(scale=1):
192
- convert_out = gr.Audio(
193
- label="Audio converti",
194
- interactive=False,
195
- autoplay=False
196
- )
197
  gr.Markdown(
198
  """
199
  **Comment Γ§a marche**
@@ -203,7 +170,6 @@ with gr.Blocks() as demo: # theme retirΓ© ici β†’ va dans launch()
203
  - Aucune transcription nΓ©cessaire
204
  """
205
  )
206
-
207
  convert_btn.click(
208
  fn=gradio_convert,
209
  inputs=[convert_src, convert_ref],
@@ -211,7 +177,7 @@ with gr.Blocks() as demo: # theme retirΓ© ici β†’ va dans launch()
211
  )
212
 
213
 
214
- # ── FastAPI montΓ©e sur Gradio ─────────────────────────────────────────────────
215
 
216
  app = gr.mount_gradio_app(FastAPI(), demo, path="/")
217
 
@@ -238,7 +204,7 @@ async def api_speak(
238
  ):
239
  out_path = tempfile.mktemp(suffix=".wav")
240
  try:
241
- cloner.speak(text=text, lang=lang, output_path=out_path, speed=speed)
242
  return FileResponse(out_path, media_type="audio/wav", filename="speech.wav")
243
  except ValueError as e:
244
  raise HTTPException(status_code=400, detail=str(e))
@@ -257,7 +223,7 @@ async def api_clone(
257
  ref_path = ref_tmp.name
258
  out_path = ref_path.replace(".wav", "_out.wav")
259
  try:
260
- cloner.generate(text=text, lang=lang, reference_audio=ref_path, output_path=out_path)
261
  return FileResponse(out_path, media_type="audio/wav", filename="cloned.wav")
262
  except Exception as e:
263
  raise HTTPException(status_code=500, detail=str(e))
@@ -279,7 +245,7 @@ async def api_convert(
279
  ref_path = ref_tmp.name
280
  out_path = src_path.replace(".wav", "_converted.wav")
281
  try:
282
- cloner.convert(source_audio=src_path, reference_audio=ref_path, output_path=out_path)
283
  return FileResponse(out_path, media_type="audio/wav", filename="converted.wav")
284
  except Exception as e:
285
  raise HTTPException(status_code=500, detail=str(e))
 
4
  import tempfile
5
  from fastapi import FastAPI, UploadFile, File, Form, HTTPException
6
  from fastapi.responses import FileResponse
 
7
 
8
+ # ── Singleton : Γ©vite le double chargement ────────────────────────────────────
9
+ _cloner = None
10
+
11
+ def get_cloner():
12
+ global _cloner
13
+ if _cloner is None:
14
+ from core.cloner import KokoClone
15
+ print("Loading KokoClone models (once)...")
16
+ _cloner = KokoClone()
17
+ print("KokoClone ready.")
18
+ return _cloner
19
 
20
 
21
  # ── Handlers Gradio ───────────────────────────────────────────────────────────
 
25
  raise gr.Error("Veuillez entrer du texte.")
26
  output_file = "/tmp/gradio_speak_output.wav"
27
  try:
28
+ get_cloner().speak(text=text, lang=lang, output_path=output_file, speed=float(speed))
29
  return output_file
30
  except Exception as e:
31
  raise gr.Error(f"Erreur : {str(e)}")
 
38
  raise gr.Error("Please upload or record a reference audio file.")
39
  output_file = "/tmp/gradio_clone_output.wav"
40
  try:
41
+ get_cloner().generate(text=text, lang=lang, reference_audio=ref_audio_path, output_path=output_file)
42
  return output_file
43
  except Exception as e:
44
  raise gr.Error(f"An error occurred: {str(e)}")
 
51
  raise gr.Error("Please upload a reference audio file.")
52
  output_file = "/tmp/gradio_convert_output.wav"
53
  try:
54
+ get_cloner().convert(source_audio=source_audio_path, reference_audio=ref_audio_path, output_path=output_file)
55
  return output_file
56
  except Exception as e:
57
  raise gr.Error(f"An error occurred: {str(e)}")
58
 
59
 
60
+ # ── Interface Gradio ──────────────────────────────────────────────────────────
61
 
62
+ with gr.Blocks() as demo:
63
  gr.Markdown(
64
  """
65
  <div style="text-align: center;">
 
71
 
72
  with gr.Tabs():
73
 
 
74
  with gr.Tab("πŸ—£οΈ Simple TTS"):
75
+ gr.Markdown("Génère la parole avec une voix Kokoro — **aucun audio de référence requis**.")
 
 
76
  with gr.Row():
77
  with gr.Column(scale=1):
78
  speak_text = gr.Textbox(
 
100
  step=0.1
101
  )
102
  speak_btn = gr.Button("πŸ—£οΈ GΓ©nΓ©rer l'audio", variant="primary")
 
103
  with gr.Column(scale=1):
104
+ speak_out = gr.Audio(label="Audio gΓ©nΓ©rΓ©", interactive=False, autoplay=True)
 
 
 
 
105
  gr.Markdown(
106
  """
107
  **Voix disponibles**
 
114
  > Vitesse **0.7–0.8** recommandΓ©e pour les apprenants dΓ©butants.
115
  """
116
  )
 
117
  speak_btn.click(
118
  fn=gradio_speak,
119
  inputs=[speak_text, speak_lang, speak_speed],
120
  outputs=speak_out
121
  )
122
 
 
123
  with gr.Tab("🎀 Text β†’ Clone"):
124
  gr.Markdown("SynthΓ©tise le texte puis applique la voix d'un audio de rΓ©fΓ©rence.")
125
  with gr.Row():
126
  with gr.Column(scale=1):
127
+ clone_text = gr.Textbox(label="1. Texte Γ  synthΓ©tiser", lines=4)
 
 
 
 
128
  clone_lang = gr.Dropdown(
129
  label="2. Langue",
130
  choices=[
131
+ ("English", "en"), ("FranΓ§ais", "fr"), ("Hindi", "hi"),
132
+ ("Japanese", "ja"), ("Chinese", "zh"), ("EspaΓ±ol", "es"),
133
+ ("Italiano", "it"), ("PortuguΓͺs", "pt"),
 
 
 
 
 
134
  ],
135
  value="en"
136
  )
137
+ clone_ref = gr.Audio(label="3. Audio de rΓ©fΓ©rence", type="filepath")
 
 
 
138
  clone_btn = gr.Button("πŸš€ GΓ©nΓ©rer avec clonage", variant="primary")
 
139
  with gr.Column(scale=1):
140
+ clone_out = gr.Audio(label="Audio clonΓ©", interactive=False, autoplay=False)
 
 
 
 
141
  gr.Markdown(
142
  """
143
  **Conseils**
 
146
  - La langue doit correspondre au texte
147
  """
148
  )
 
149
  clone_btn.click(
150
  fn=gradio_clone,
151
  inputs=[clone_text, clone_lang, clone_ref],
152
  outputs=clone_out
153
  )
154
 
 
155
  with gr.Tab("πŸ” Audio β†’ Clone"):
156
  gr.Markdown("Re-voice un audio existant pour qu'il sonne comme la voix de rΓ©fΓ©rence.")
157
  with gr.Row():
158
  with gr.Column(scale=1):
159
+ convert_src = gr.Audio(label="1. Audio source", type="filepath")
160
+ convert_ref = gr.Audio(label="2. Voix de rΓ©fΓ©rence", type="filepath")
 
 
 
 
 
 
161
  convert_btn = gr.Button("πŸ” Convertir la voix", variant="primary")
 
162
  with gr.Column(scale=1):
163
+ convert_out = gr.Audio(label="Audio converti", interactive=False, autoplay=False)
 
 
 
 
164
  gr.Markdown(
165
  """
166
  **Comment Γ§a marche**
 
170
  - Aucune transcription nΓ©cessaire
171
  """
172
  )
 
173
  convert_btn.click(
174
  fn=gradio_convert,
175
  inputs=[convert_src, convert_ref],
 
177
  )
178
 
179
 
180
+ # ── FastAPI + Gradio ──────────────────────────────────────────────────────────
181
 
182
  app = gr.mount_gradio_app(FastAPI(), demo, path="/")
183
 
 
204
  ):
205
  out_path = tempfile.mktemp(suffix=".wav")
206
  try:
207
+ get_cloner().speak(text=text, lang=lang, output_path=out_path, speed=speed)
208
  return FileResponse(out_path, media_type="audio/wav", filename="speech.wav")
209
  except ValueError as e:
210
  raise HTTPException(status_code=400, detail=str(e))
 
223
  ref_path = ref_tmp.name
224
  out_path = ref_path.replace(".wav", "_out.wav")
225
  try:
226
+ get_cloner().generate(text=text, lang=lang, reference_audio=ref_path, output_path=out_path)
227
  return FileResponse(out_path, media_type="audio/wav", filename="cloned.wav")
228
  except Exception as e:
229
  raise HTTPException(status_code=500, detail=str(e))
 
245
  ref_path = ref_tmp.name
246
  out_path = src_path.replace(".wav", "_converted.wav")
247
  try:
248
+ get_cloner().convert(source_audio=src_path, reference_audio=ref_path, output_path=out_path)
249
  return FileResponse(out_path, media_type="audio/wav", filename="converted.wav")
250
  except Exception as e:
251
  raise HTTPException(status_code=500, detail=str(e))