File size: 2,860 Bytes
1b41e6d
 
 
 
 
490c04c
 
 
 
1b41e6d
490c04c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1b41e6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490c04c
 
1b41e6d
 
 
490c04c
 
 
 
 
 
1b41e6d
 
490c04c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import gradio as gr
import edge_tts
import asyncio
import tempfile
import os
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import FileResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import uvicorn

# --- FastAPI часть для API ---
app = FastAPI()

# Разрешаем CORS для всех доменов (можно ограничить только вашим сайтом)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["POST", "GET"],
    allow_headers=["*"],
)

@app.post("/api/tts")
async def api_tts(request: Request):
    try:
        data = await request.json()
        text = data.get("text", "").strip()
        voice = data.get("voice", "en-US-GuyNeural")
        rate = data.get("rate", 0)
        pitch = data.get("pitch", 0)

        if not text:
            raise HTTPException(status_code=400, detail="Text is required")

        rate_str = f"{rate:+d}%"
        pitch_str = f"{pitch:+d}Hz"
        
        communicate = edge_tts.Communicate(text, voice, rate=rate_str, pitch=pitch_str)
        output_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
        await communicate.save(output_file)

        return FileResponse(output_file, media_type="audio/mpeg")

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# --- Gradio часть для интерфейса Spaces ---
async def get_voices():
    voices = await edge_tts.list_voices()
    return {f"{v['ShortName']} - {v['Locale']} ({v['Gender']})": v['ShortName'] for v in voices}

async def text_to_speech(text, voice, rate, pitch):
    if not text.strip():
        return None, "Please enter text to convert."
    if not voice:
        return None, "Please select a voice."
    
    voice_short_name = voice.split(" - ")[0]
    rate_str = f"{rate:+d}%"
    pitch_str = f"{pitch:+d}Hz"
    communicate = edge_tts.Communicate(text, voice_short_name, rate=rate_str, pitch=pitch_str)
    
    with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
        tmp_path = tmp_file.name
        await communicate.save(tmp_path)
    
    return tmp_path, None

async def create_demo():
    voices = await get_voices()
    
    with gr.Blocks(analytics_enabled=False) as demo:
        # ... (ваш текущий интерфейс Gradio без изменений) ...
        # (оставьте всю разметку и логику как есть)
    
    return demo

# Запуск и совмещение FastAPI + Gradio
gradio_app = gr.mount_gradio_app(app, await create_demo(), path="/")

@gradio_app.get("/")
async def root():
    return {"message": "Edge TTS API is running. Use /api/tts for API or / for Gradio UI."}

if __name__ == "__main__":
    uvicorn.run(gradio_app, host="0.0.0.0", port=7860)