Spaces:
Runtime error
Runtime error
| import os | |
| os.environ["COQUI_TOS_AGREED"] = "1" # Coqui TOS auto-accept | |
| os.environ.setdefault("COQUI_CACHE_DIR", "/home/user/.coqui") | |
| import glob | |
| import gradio as gr | |
| import numpy as np | |
| import soundfile as sf | |
| from huggingface_hub import snapshot_download | |
| from TTS.api import TTS | |
| HF_REPO = "suhaibrashid17/XTTS-v2-Urdu-FT" | |
| SAMPLE_RATE = 24000 | |
| def _find_file(patterns, root): | |
| for pat in patterns: | |
| hits = glob.glob(os.path.join(root, pat), recursive=True) | |
| if hits: | |
| return hits[0] | |
| return None | |
| def load_finetuned_xtts(): | |
| # Download to local cache (no symlinks to avoid weird paths) | |
| repo_dir = snapshot_download( | |
| repo_id=HF_REPO, | |
| local_dir_use_symlinks=False, | |
| allow_patterns=["**/*"] # pull everything once; avoids missing tokenizer/vocab | |
| ) | |
| # Locate config + weight file | |
| cfg = _find_file(["config.json", "**/config.json"], repo_dir) | |
| mdl = _find_file( | |
| ["model.pth", "pytorch_model.bin", "**/model.pth", "**/pytorch_model.bin"], | |
| repo_dir, | |
| ) | |
| if not (cfg and mdl): | |
| raise RuntimeError( | |
| "Could not find model/config. Need config.json and model.pth (or pytorch_model.bin)." | |
| ) | |
| # >>> IMPORTANT FIX <<< | |
| # Coqui XTTS expects model_path = DIRECTORY that contains model.pth | |
| model_dir = os.path.dirname(mdl) | |
| # Load by giving directory (not the file) to model_path | |
| tts = TTS(model_path=model_dir, config_path=cfg, gpu=False, progress_bar=False) | |
| return tts | |
| # ---- load once on startup | |
| TTS_ENGINE = load_finetuned_xtts() | |
| # ---------- helpers ---------- | |
| def _ensure_wav_path(audio): | |
| """ | |
| Gradio v5: Audio can be filepath or dict/tuple/ndarray. | |
| Always return a real wav path. | |
| """ | |
| if audio is None: | |
| return None | |
| if isinstance(audio, str): | |
| return audio | |
| if isinstance(audio, dict) and "data" in audio: | |
| data = audio["data"] | |
| sr = int(audio.get("sampling_rate", SAMPLE_RATE)) | |
| path = "ref.wav" | |
| sf.write(path, data, sr) | |
| return path | |
| if isinstance(audio, (tuple, list)): | |
| # (sr, data) or (data, sr) | |
| if isinstance(audio[0], (int, float)): | |
| sr, data = audio | |
| else: | |
| data, sr = audio | |
| path = "ref.wav" | |
| sf.write(path, data, int(sr)) | |
| return path | |
| if isinstance(audio, np.ndarray): | |
| path = "ref.wav" | |
| sf.write(path, audio, SAMPLE_RATE) | |
| return path | |
| raise ValueError("Unsupported audio input format") | |
| def clean_urdu_text(txt: str) -> str: | |
| if not txt: | |
| return "" | |
| t = " ".join(txt.split()) | |
| if t and t[-1] not in "۔!?؟": | |
| t += "۔" | |
| return t | |
| # ---------- inference ---------- | |
| def clone_urdu(reference_audio, text): | |
| ref_path = _ensure_wav_path(reference_audio) | |
| if not ref_path: | |
| return gr.Error("Reference audio required (5–30 seconds).") | |
| txt = clean_urdu_text(text) | |
| try: | |
| out_path = "output_xtts_ur.wav" | |
| # XTTS fine-tuned for Urdu | |
| TTS_ENGINE.tts_to_file( | |
| text=txt, | |
| file_path=out_path, | |
| speaker_wav=ref_path, | |
| language="ur", | |
| ) | |
| return out_path | |
| except Exception as e: | |
| return gr.Error(f"XTTS-Urdu error: {e}") | |
| # ---------- UI ---------- | |
| with gr.Blocks(title="XTTS-v2 Urdu — Voice Clone (CPU)") as demo: | |
| gr.Markdown("## XTTS-v2 Urdu — Voice Clone") | |
| ref = gr.Audio( | |
| label="Reference voice (WAV/MP3, ~5–30 sec)", | |
| sources=["upload", "microphone"], | |
| type="filepath", | |
| waveform_options={"show_controls": True}, | |
| ) | |
| txt = gr.Textbox( | |
| label="Urdu text", | |
| lines=4, | |
| placeholder="یہاں اردو متن لکھیں… مختصر جملے بہتر نتیجہ دیتے ہیں۔" | |
| ) | |
| btn = gr.Button("Generate", variant="primary") | |
| out = gr.Audio(label="Output", type="filepath") | |
| btn.click(clone_urdu, inputs=[ref, txt], outputs=out) | |
| if __name__ == "__main__": | |
| demo.queue(max_size=8).launch(server_name="0.0.0.0", server_port=7860) | |