Spaces:
No application file
No application file
Download server.py from workitoscinco/cosoese: direct link, hf CLI and curl.
- Browser
- Download file 2.65 kB
-
https://huggingface.co/spaces/workitoscinco/cosoese/resolve/main/server.py
- Command line
-
hf download hf://spaces/workitoscinco/cosoese/server.py
-
curl -L -o server.py https://huggingface.co/spaces/workitoscinco/cosoese/resolve/main/server.py
2.65 kB
| from fastapi import FastAPI, Response | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| from kokoro import KPipeline | |
| import soundfile as sf | |
| import numpy as np | |
| import io | |
| app = FastAPI() | |
| app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) | |
| pipe = KPipeline(lang_code='e') | |
| class Req(BaseModel): | |
| input: str | |
| voice: str = "ef_dora" | |
| speed: float = 1.0 | |
| INDEX_HTML = """<!DOCTYPE html><html><head><meta charset="utf-8"><title>Kokoro TTS</title></head> | |
| <body style="font-family:sans-serif;text-align:center"> | |
| <h1>Kokoro TTS (espanol)</h1> | |
| <textarea id="t" rows="3" style="width:min(600px,90vw)">Hola, soy una voz de Kokoro generada con IA abierta.</textarea><br><br> | |
| <select id="v"> | |
| <option value="ef_dora">Dora (femenina)</option> | |
| <option value="em_alex">Alex (masculina)</option> | |
| <option value="em_santa">Santa (masculina)</option> | |
| </select> | |
| <label>Velocidad <input id="s2" type="range" min="0.5" max="2" step="0.1" value="1"><span id="sv">1</span></label><br><br> | |
| <button id="b">Hablar</button> | |
| <p id="s">Listo.</p> | |
| <audio id="a" controls style="width:min(600px,90vw)"></audio><br> | |
| <a id="d" hidden>Descargar wav</a> | |
| <script> | |
| const s2=document.querySelector("#s2"); | |
| s2.oninput=()=>document.querySelector("#sv").textContent=s2.value; | |
| document.querySelector("#b").onclick=async()=>{ | |
| const s=document.querySelector("#s"); s.textContent="Generando..."; | |
| try{ | |
| const r=await fetch("/v1/audio/speech",{method:"POST",headers:{"Content-Type":"application/json"}, | |
| body:JSON.stringify({input:document.querySelector("#t").value.slice(0,1000), | |
| voice:document.querySelector("#v").value,speed:parseFloat(s2.value)})}); | |
| if(!r.ok) throw new Error("servidor "+r.status); | |
| const buf=await r.arrayBuffer(); | |
| const url=URL.createObjectURL(new Blob([buf],{type:"audio/wav"})); | |
| const au=document.querySelector("#a"); au.src=url; au.play(); | |
| const dl=document.querySelector("#d"); dl.href=url; dl.download="kokoro.wav"; dl.hidden=false; | |
| s.textContent="Listo ("+(buf.byteLength/1024).toFixed(1)+" KB)."; | |
| }catch(e){s.textContent="Error: "+e.message;} | |
| }; | |
| </script></body></html>""" | |
| def index(): | |
| from fastapi.responses import HTMLResponse | |
| return HTMLResponse(INDEX_HTML) | |
| def speech(r: Req): | |
| parts = [a for _, _, a in pipe(r.input[:1000], voice=r.voice, speed=r.speed)] | |
| wav = np.concatenate(parts) if len(parts) > 1 else parts[0] | |
| buf = io.BytesIO() | |
| sf.write(buf, wav, 24000, format="WAV") | |
| return Response(content=buf.getvalue(), media_type="audio/wav") | |