Uploaded sanitized BC250/ROCm Repository.

This commit is contained in:
Fabian
2026-08-20 00:45:43 +02:00
parent 7d2184f1e8
commit d7d22e93b3
678 changed files with 65963 additions and 1 deletions
@@ -0,0 +1,83 @@
"""Qwen3-TTS HTTP server — OpenAI-compatible /v1/audio/speech endpoint."""
import argparse, io, os, sys
from flask import Flask, request, send_file, jsonify
app = Flask(__name__)
MODEL_DIR = "/models/qwen3-tts"
engine = None
SPEAKERS = ["Vivian","Serena","uncle_fu","Dylan","Eric","Ryan","Aiden","ono_anna","Sohee"]
LANGUAGES = ["english","chinese","japanese","korean","german","spanish","french","russian","italian","portuguese"]
def init_engine():
global engine
# TTSEngine uses Path.cwd() as project_root and builds relative paths from it.
# model_dir must be a subdirectory of cwd for relative_to() to work.
parent = os.path.dirname(os.path.abspath(MODEL_DIR))
basename = os.path.basename(MODEL_DIR)
os.chdir(parent)
from qwen3_tts_gguf.inference import TTSEngine
engine = TTSEngine(model_dir=basename, onnx_provider="CPUExecutionProvider")
if not engine.ready:
print(f"[server] WARNING: engine created but not ready", flush=True)
@app.route("/health")
def health():
ready = engine is not None and engine.ready
return jsonify({"status": "ok" if ready else "loading", "speakers": SPEAKERS, "languages": LANGUAGES})
@app.route("/v1/audio/speech", methods=["POST"])
def speech():
if engine is None or not engine.ready:
return jsonify({"error": "engine not ready"}), 503
data = request.get_json(force=True)
text = data.get("input", "")
if not text:
return jsonify({"error": "missing input"}), 400
speaker = data.get("voice", "Vivian")
if speaker not in SPEAKERS:
speaker = "Vivian"
language = data.get("language", "english")
if language not in LANGUAGES:
language = "english"
instruct = data.get("instruct", "")
try:
import numpy as np, wave as _wave
from qwen3_tts_gguf.inference import TTSConfig
stream = engine.create_stream(n_ctx=2048)
if stream is None:
return jsonify({"error": "failed to create stream"}), 500
cfg = TTSConfig()
result = stream.custom(text=text, speaker=speaker, language=language,
instruct=instruct, config=cfg)
stream.join()
if result is None:
return jsonify({"error": "synthesis returned None"}), 500
audio = result.audio if hasattr(result, 'audio') and result.audio is not None else None
if audio is None:
tmp = os.path.join("/tmp", "tts_out.wav")
result.save(tmp)
import soundfile as sf
audio, _ = sf.read(tmp, dtype='float32')
os.remove(tmp)
buf = io.BytesIO()
with _wave.open(buf, "wb") as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(24000)
pcm = (np.clip(audio, -1.0, 1.0) * 32767).astype(np.int16).tobytes()
wf.writeframes(pcm)
buf.seek(0)
return send_file(buf, mimetype="audio/wav", download_name="speech.wav")
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("--host", default="0.0.0.0")
p.add_argument("--port", type=int, default=8072)
p.add_argument("--model-dir", default=MODEL_DIR)
a = p.parse_args()
MODEL_DIR = a.model_dir
init_engine()
app.run(host=a.host, port=a.port)