import torch import torchaudio import io import base64 from typing import Dict, Any from chatterbox.mtl_tts import ChatterboxMultilingualTTS class EndpointHandler: def __init__(self, path=""): device = "cuda" if torch.cuda.is_available() else "cpu" print(f"🚀 Loading Chatterbox-Multilingual model on {device}...") self.model = ChatterboxMultilingualTTS.from_pretrained(device=device) self.device = device print("✅ Model loaded successfully") def __call__(self, data: Dict[str, Any]) -> Dict[str, Any]: inputs = data.pop("inputs", data) text = inputs.get("text") if not text: return {"error": "Missing required parameter: text"} reference_audio = inputs.get("reference_audio") if not reference_audio: return {"error": "Missing required parameter: reference_audio"} cfg_weight = inputs.get("cfg_weight", 1.0) exaggeration = inputs.get("exaggeration", 1.0) language_id = inputs.get("language", "en") if isinstance(reference_audio, str) and reference_audio.startswith("data:"): header, encoded = reference_audio.split(",", 1) reference_audio_bytes = base64.b64decode(encoded) elif isinstance(reference_audio, str): reference_audio_bytes = base64.b64decode(reference_audio) else: reference_audio_bytes = reference_audio with open("/tmp/reference_audio.tmp", "wb") as f: f.write(reference_audio_bytes) try: wav = self.model.generate( text, audio_prompt_path="/tmp/reference_audio.tmp", language_id=language_id, exaggeration=exaggeration, cfg_weight=cfg_weight ) buffer = io.BytesIO() torchaudio.save(buffer, wav, self.model.sr, format="wav") buffer.seek(0) audio_base64 = base64.b64encode(buffer.read()).decode("utf-8") return { "audio": audio_base64, "sample_rate": self.model.sr, "format": "wav" } except Exception as e: return {"error": str(e)}