Add /api/mc/tts and /api/mc/voices endpoints, fix login to only show own voices
This commit is contained in:
+76
-3
@@ -590,7 +590,7 @@ def _resolve_guild_id() -> str:
|
|||||||
|
|
||||||
@app.route("/api/mc/login", methods=["POST"])
|
@app.route("/api/mc/login", methods=["POST"])
|
||||||
def api_mc_login():
|
def api_mc_login():
|
||||||
"""Minecraft mod login endpoint. Accepts JSON {"token": "..."} and returns user info + voices."""
|
"""Minecraft mod login endpoint. Accepts JSON {"token": "..."} and returns user info + personal voices."""
|
||||||
data = request.get_json(force=True) if request.is_json else {}
|
data = request.get_json(force=True) if request.is_json else {}
|
||||||
token = data.get("token", "").strip()
|
token = data.get("token", "").strip()
|
||||||
if not token:
|
if not token:
|
||||||
@@ -603,10 +603,11 @@ def api_mc_login():
|
|||||||
user_id = entry["user_id"]
|
user_id = entry["user_id"]
|
||||||
ucfg = get_user_config(user_id)
|
ucfg = get_user_config(user_id)
|
||||||
voices = ucfg.get("chatterbox_voices", [])
|
voices = ucfg.get("chatterbox_voices", [])
|
||||||
|
# Only return voices that belong to this user (prefixed with their user_id)
|
||||||
result = []
|
result = []
|
||||||
for v in voices:
|
for v in voices:
|
||||||
parts = v.split("_", 1)
|
if v.startswith(f"{user_id}_"):
|
||||||
display = parts[1].rsplit(".", 1)[0] if len(parts) > 1 else v.rsplit(".", 1)[0]
|
display = v.split("_", 1)[1].rsplit(".", 1)[0]
|
||||||
result.append({"filename": v, "display": display})
|
result.append({"filename": v, "display": display})
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -616,6 +617,78 @@ def api_mc_login():
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/mc/voices", methods=["GET"])
|
||||||
|
def api_mc_voices():
|
||||||
|
"""List all predefined voices from the Chatterbox server."""
|
||||||
|
try:
|
||||||
|
chatterbox_url = get_chatterbox_url()
|
||||||
|
r = requests.get(f"{chatterbox_url}/get_predefined_voices", timeout=10)
|
||||||
|
r.raise_for_status()
|
||||||
|
return jsonify(r.json())
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": str(e)}), 502
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/mc/tts", methods=["POST"])
|
||||||
|
def api_mc_tts():
|
||||||
|
"""Generate TTS audio. Returns WAV bytes.
|
||||||
|
JSON body: {"text": "...", "mode": "chatterbox|dectalk|morshu", "voice": "Emily.wav"}
|
||||||
|
"""
|
||||||
|
data = request.get_json(force=True) if request.is_json else {}
|
||||||
|
text = (data.get("text") or "").strip()
|
||||||
|
if not text:
|
||||||
|
return jsonify({"error": "Missing text"}), 400
|
||||||
|
|
||||||
|
mode = data.get("mode", "chatterbox")
|
||||||
|
voice = data.get("voice", "Emily.wav")
|
||||||
|
|
||||||
|
try:
|
||||||
|
if mode == "chatterbox":
|
||||||
|
chatterbox_url = get_chatterbox_url()
|
||||||
|
payload = {
|
||||||
|
"text": text,
|
||||||
|
"voice_mode": "predefined",
|
||||||
|
"predefined_voice_id": voice,
|
||||||
|
"output_format": "wav",
|
||||||
|
"split_text": False,
|
||||||
|
}
|
||||||
|
r = requests.post(f"{chatterbox_url}/tts", json=payload, timeout=120)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.content, 200, {"Content-Type": "audio/wav"}
|
||||||
|
|
||||||
|
elif mode == "clone":
|
||||||
|
chatterbox_url = get_chatterbox_url()
|
||||||
|
payload = {
|
||||||
|
"text": text,
|
||||||
|
"voice_mode": "clone",
|
||||||
|
"reference_audio_filename": voice,
|
||||||
|
"output_format": "wav",
|
||||||
|
"split_text": False,
|
||||||
|
}
|
||||||
|
r = requests.post(f"{chatterbox_url}/tts", json=payload, timeout=120)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.content, 200, {"Content-Type": "audio/wav"}
|
||||||
|
|
||||||
|
elif mode == "dectalk":
|
||||||
|
dectalk_url = get_dectalk_url()
|
||||||
|
r = requests.get(f"{dectalk_url}/say", params={"text": text}, timeout=30)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.content, 200, {"Content-Type": "audio/wav"}
|
||||||
|
|
||||||
|
elif mode == "morshu":
|
||||||
|
r = requests.get("http://127.0.0.1:3002/say", params={"text": text}, timeout=60)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.content, 200, {"Content-Type": "audio/wav"}
|
||||||
|
|
||||||
|
else:
|
||||||
|
return jsonify({"error": f"Unknown mode: {mode}"}), 400
|
||||||
|
|
||||||
|
except requests.exceptions.ConnectionError:
|
||||||
|
return jsonify({"error": f"{mode} server not reachable"}), 502
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Routes — Chatterbox voice management
|
# Routes — Chatterbox voice management
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user