88 lines
2.4 KiB
Python
88 lines
2.4 KiB
Python
from flask import Flask, request, send_file, jsonify
|
|
import ChatTTS
|
|
import tempfile
|
|
import numpy as np
|
|
import soundfile as sf
|
|
from flask_cors import CORS
|
|
import os
|
|
import pickle
|
|
import asyncio
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
import time
|
|
import hashlib
|
|
|
|
app = Flask(__name__)
|
|
CORS(app)
|
|
|
|
chat_tts = ChatTTS.Chat()
|
|
chat_tts.load(compile=False)
|
|
|
|
SAMPLE_RATE = 24000
|
|
|
|
SPEAKER_EMBEDDING_FILE = 'cutegirl_speaker_embedding.pkl'
|
|
AUDIO_DIR = '/www/wwwroot/chat.obscura.work/audio_files'
|
|
|
|
with open(SPEAKER_EMBEDDING_FILE, 'rb') as f:
|
|
FIXED_SPEAKER = pickle.load(f)
|
|
|
|
executor = ThreadPoolExecutor(max_workers=3)
|
|
|
|
def generate_audio(text):
|
|
params_infer_code = ChatTTS.Chat.InferCodeParams(
|
|
spk_emb=FIXED_SPEAKER,
|
|
temperature=0.3,
|
|
top_P=0.6,
|
|
top_K=20,
|
|
)
|
|
|
|
wavs = chat_tts.infer(text, params_infer_code=params_infer_code)
|
|
audio_data = wavs[0]
|
|
|
|
if not np.issubdtype(audio_data.dtype, np.floating):
|
|
audio_data = audio_data.astype(np.float32)
|
|
|
|
if np.max(np.abs(audio_data)) > 1:
|
|
audio_data = audio_data / np.max(np.abs(audio_data))
|
|
|
|
return audio_data
|
|
|
|
def get_audio_filename(text):
|
|
return hashlib.md5(text.encode()).hexdigest() + '.wav'
|
|
|
|
@app.route('/synthesize', methods=['POST', 'OPTIONS'])
|
|
async def synthesize():
|
|
if request.method == 'OPTIONS':
|
|
return '', 204
|
|
|
|
data = request.json
|
|
texts = data.get('texts')
|
|
if not texts:
|
|
return jsonify({"error": "No texts provided"}), 400
|
|
|
|
audio_urls = []
|
|
|
|
for text in texts:
|
|
filename = get_audio_filename(text)
|
|
filepath = os.path.join(AUDIO_DIR, filename)
|
|
|
|
if os.path.exists(filepath):
|
|
audio_urls.append(f"/audio_files/{filename}")
|
|
else:
|
|
loop = asyncio.get_event_loop()
|
|
audio_data = await loop.run_in_executor(executor, generate_audio, text)
|
|
sf.write(filepath, audio_data, SAMPLE_RATE)
|
|
audio_urls.append(f"/audio_files/{filename}")
|
|
|
|
return jsonify({"audio_urls": audio_urls})
|
|
|
|
@app.route('/audio_files/<filename>', methods=['GET', 'OPTIONS'])
|
|
def get_audio(filename):
|
|
if request.method == 'OPTIONS':
|
|
return '', 204
|
|
try:
|
|
return send_file(os.path.join(AUDIO_DIR, filename), mimetype='audio/wav')
|
|
except Exception as e:
|
|
return jsonify({"error": str(e)}), 404
|
|
|
|
if __name__ == '__main__':
|
|
app.run(port=5002) |