|
@@ -10,12 +10,12 @@ from fastapi import (
|
|
|
File,
|
|
|
Form,
|
|
|
)
|
|
|
-
|
|
|
from fastapi.responses import StreamingResponse, JSONResponse, FileResponse
|
|
|
|
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
+from typing import List
|
|
|
import uuid
|
|
|
import requests
|
|
|
import hashlib
|
|
@@ -31,6 +31,7 @@ from utils.utils import (
|
|
|
)
|
|
|
from utils.misc import calculate_sha256
|
|
|
|
|
|
+
|
|
|
from config import (
|
|
|
SRC_LOG_LEVELS,
|
|
|
CACHE_DIR,
|
|
@@ -252,15 +253,15 @@ async def speech(request: Request, user=Depends(get_verified_user)):
|
|
|
)
|
|
|
|
|
|
elif app.state.config.TTS_ENGINE == "elevenlabs":
|
|
|
-
|
|
|
payload = None
|
|
|
try:
|
|
|
payload = json.loads(body.decode("utf-8"))
|
|
|
except Exception as e:
|
|
|
log.exception(e)
|
|
|
- pass
|
|
|
+ raise HTTPException(status_code=400, detail="Invalid JSON payload")
|
|
|
|
|
|
- url = f"https://api.elevenlabs.io/v1/text-to-speech/{payload['voice']}"
|
|
|
+ voice_id = payload.get("voice", "")
|
|
|
+ url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
|
|
|
|
|
|
headers = {
|
|
|
"Accept": "audio/mpeg",
|
|
@@ -435,3 +436,69 @@ def transcribe(
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
detail=ERROR_MESSAGES.DEFAULT(e),
|
|
|
)
|
|
|
+
|
|
|
+
|
|
|
+def get_available_models() -> List[dict]:
|
|
|
+ if app.state.config.TTS_ENGINE == "openai":
|
|
|
+ return [{"id": "tts-1"}, {"id": "tts-1-hd"}]
|
|
|
+ elif app.state.config.TTS_ENGINE == "elevenlabs":
|
|
|
+ headers = {
|
|
|
+ "xi-api-key": app.state.config.TTS_API_KEY,
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ }
|
|
|
+
|
|
|
+ try:
|
|
|
+ response = requests.get(
|
|
|
+ "https://api.elevenlabs.io/v1/models", headers=headers
|
|
|
+ )
|
|
|
+ response.raise_for_status()
|
|
|
+ models = response.json()
|
|
|
+ return [
|
|
|
+ {"name": model["name"], "id": model["model_id"]} for model in models
|
|
|
+ ]
|
|
|
+ except requests.RequestException as e:
|
|
|
+ log.error(f"Error fetching voices: {str(e)}")
|
|
|
+ return []
|
|
|
+
|
|
|
+
|
|
|
+@app.get("/models")
|
|
|
+async def get_models(user=Depends(get_verified_user)):
|
|
|
+ return {"models": get_available_models()}
|
|
|
+
|
|
|
+
|
|
|
+def get_available_voices() -> List[dict]:
|
|
|
+ if app.state.config.TTS_ENGINE == "openai":
|
|
|
+ return [
|
|
|
+ {"name": "alloy", "id": "alloy"},
|
|
|
+ {"name": "echo", "id": "echo"},
|
|
|
+ {"name": "fable", "id": "fable"},
|
|
|
+ {"name": "onyx", "id": "onyx"},
|
|
|
+ {"name": "nova", "id": "nova"},
|
|
|
+ {"name": "shimmer", "id": "shimmer"},
|
|
|
+ ]
|
|
|
+ elif app.state.config.TTS_ENGINE == "elevenlabs":
|
|
|
+ headers = {
|
|
|
+ "xi-api-key": app.state.config.TTS_API_KEY,
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ }
|
|
|
+
|
|
|
+ try:
|
|
|
+ response = requests.get(
|
|
|
+ "https://api.elevenlabs.io/v1/voices", headers=headers
|
|
|
+ )
|
|
|
+ response.raise_for_status()
|
|
|
+ voices_data = response.json()
|
|
|
+
|
|
|
+ voices = []
|
|
|
+ for voice in voices_data.get("voices", []):
|
|
|
+ voices.append({"name": voice["name"], "id": voice["voice_id"]})
|
|
|
+ return voices
|
|
|
+ except requests.RequestException as e:
|
|
|
+ log.error(f"Error fetching voices: {str(e)}")
|
|
|
+
|
|
|
+ return []
|
|
|
+
|
|
|
+
|
|
|
+@app.get("/voices")
|
|
|
+async def get_voices(user=Depends(get_verified_user)):
|
|
|
+ return {"voices": get_available_voices()}
|