Spaces:
Sleeping
Sleeping
File size: 3,162 Bytes
9c3aa3c 72a07cd c43dd80 72a07cd 9c3aa3c 72a07cd 9c3aa3c 72a07cd 9c3aa3c 72a07cd 9c3aa3c 72a07cd 9c3aa3c 72a07cd 9c3aa3c 72a07cd 9c3aa3c c43dd80 72a07cd 9c3aa3c 72a07cd 9c3aa3c c43dd80 72a07cd 9c3aa3c c43dd80 72a07cd c43dd80 72a07cd c43dd80 72a07cd c43dd80 9c3aa3c c43dd80 72a07cd 9c3aa3c c43dd80 72a07cd c43dd80 72a07cd 9c3aa3c 72a07cd 9c3aa3c 72a07cd | 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 86 87 88 89 90 | import os
import io
import traceback
import numpy as np
import scipy.io.wavfile as wavfile # Используем scipy вместо soundfile
from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
from pydantic import BaseModel
from supertonic import TTS
import uvicorn
app = FastAPI(title="Supertonic TTS API")
class TTSRequest(BaseModel):
text: str
lang: str = "ru"
voice: str = "M2"
print("Загрузка модели Supertonic TTS...")
tts = TTS(auto_download=True)
default_style = tts.get_voice_style(voice_name="M2")
print("Модель успешно загружена и готова к работе!")
@app.get("/")
async def root():
return {
"status": "ok",
"message": "Supertonic TTS API is running",
"docs": "/docs",
"usage": "POST /api/tts с JSON: {'text': 'ваш текст', 'lang': 'ru', 'voice': 'M2'}"
}
@app.post("/api/tts")
async def synthesize(request: TTSRequest):
try:
# 1. Получаем стиль голоса
if request.voice == "M2":
style = default_style
else:
style = tts.get_voice_style(voice_name=request.voice)
# 2. Синтез
wav, duration = tts.synthesize(request.text, voice_style=style, lang=request.lang)
# 3. Конвертация в numpy (если модель вернула тензор PyTorch)
if hasattr(wav, 'cpu'):
wav = wav.cpu().numpy()
elif hasattr(wav, 'numpy'):
wav = wav.numpy()
wav = np.asarray(wav)
# 4. Убираем лишние измерения (например, если форма (1, 48000) -> (48000,))
wav = wav.squeeze()
# 5. Нормализация и конвертация в int16 (стандарт для WAV)
# Сначала приводим к float32 для безопасной нормализации
wav = wav.astype(np.float32)
max_val = np.max(np.abs(wav))
if max_val > 1.0:
wav = wav / max_val
# Конвертируем в int16 (от -32768 до 32767)
wav_int16 = (wav * 32767).astype(np.int16)
# 6. Получаем sample rate
sample_rate = getattr(tts, 'sample_rate', 24000)
# 7. Записываем в память через scipy (работает безотказно)
out = io.BytesIO()
wavfile.write(out, sample_rate, wav_int16)
audio_bytes = out.getvalue()
# 8. Возвращаем аудио
return Response(
content=audio_bytes,
media_type='audio/wav',
headers={
"Content-Disposition": "attachment; filename=speech.wav",
"X-Audio-Duration": str(round(duration, 2))
}
)
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail=f"Ошибка генерации: {str(e)}")
if __name__ == '__main__':
port = int(os.environ.get('PORT', 7860))
uvicorn.run(app, host='0.0.0.0', port=port) |