moss / app.py
Webber1979's picture
Update app.py
4250c19 verified
import os
import sys
import subprocess
import tempfile
import soundfile as sf
import librosa
from fastapi import FastAPI, File, Form, UploadFile
from fastapi.responses import FileResponse
from fastapi.middleware.cors import CORSMiddleware
# 1. АВТОМАТИЧЕСКОЕ СКАЧИВАНИЕ ОРИГИНАЛЬНОГО РЕПОЗИТОРИЯ
REPO_DIR = "MOSS-TTS-Nano"
if not os.path.exists(REPO_DIR):
print("Клонируем оригинальный репозиторий MOSS-TTS-Nano...")
subprocess.run(["git", "clone", "https://github.com/OpenMOSS/MOSS-TTS-Nano.git"])
# Добавляем скачанную папку в пути Python, чтобы импорты работали
sys.path.append(REPO_DIR)
# 2. ИМПОРТИРУЕМ ОРИГИНАЛЬНЫЙ ДВИЖОК
from moss_tts_nano_runtime import NanoTTSService
app = FastAPI()
# Разрешаем CORS для твоего React-интерфейса
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 3. ИНИЦИАЛИЗАЦИЯ МОДЕЛИ (скачает веса при первом запуске)
print("Загрузка весов MOSS-TTS-Nano (это может занять пару минут)...")
tts_service = NanoTTSService(
checkpoint_path="OpenMOSS-Team/MOSS-TTS-Nano",
audio_tokenizer_path="OpenMOSS-Team/MOSS-Audio-Tokenizer-Nano",
device="auto" # Автоматически включит GPU, если он есть
)
print("Модель успешно загружена и готова к работе!")
@app.get("/")
async def root():
return {"message": "Бэкенд MOSS-TTS-Nano работает! Жду запросов от React UI на /api/predict"}
@app.post("/api/predict")
async def predict(
text: str = Form(...),
speed: float = Form(1.0),
mode: str = Form("standard"),
speaker: str = Form("default"),
reference_audio: UploadFile = File(None)
):
prompt_audio_path = None
try:
# Если загружен файл для клонирования голоса
if mode == "clone" and reference_audio is not None:
temp_audio = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
content = await reference_audio.read()
temp_audio.write(content)
temp_audio.close()
prompt_audio_path = temp_audio.name
# Выбор стандартного голоса
voice_preset = "Junhao" # Дефолтный голос в MOSS
# 4. ЗАПУСК ОРИГИНАЛЬНОГО СИНТЕЗА
result = tts_service.synthesize(
text=text,
voice=voice_preset if not prompt_audio_path else None,
prompt_audio_path=prompt_audio_path,
mode="voice_clone", # В MOSS это универсальный режим
)
audio_data = result['audio']
sample_rate = result['sample_rate']
# 5. ОБРАБОТКА СКОРОСТИ (если ползунок скорости изменен)
if speed != 1.0:
audio_data = librosa.effects.time_stretch(audio_data, rate=speed)
# 6. СОХРАНЕНИЕ И ОТПРАВКА РЕЗУЛЬТАТА
output_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
sf.write(output_file.name, audio_data, sample_rate)
return FileResponse(
output_file.name,
media_type="audio/wav",
filename="output.wav"
)
except Exception as e:
import traceback
traceback.print_exc()
return {"error": str(e)}
finally:
# Убираем за собой временные файлы
if prompt_audio_path and os.path.exists(prompt_audio_path):
os.remove(prompt_audio_path)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)