import os import time import tempfile import gradio as gr import soundfile as sf import torch from qwen_tts import Qwen3TTSModel MODEL_ID = os.getenv("MODEL_ID", "Qwen/Qwen3-TTS-12Hz-0.6B-CustomVoice") model = None def get_model(): global model if model is not None: return model if torch.cuda.is_available(): model = Qwen3TTSModel.from_pretrained( MODEL_ID, device_map="cuda:0", dtype=torch.bfloat16, ) else: model = Qwen3TTSModel.from_pretrained( MODEL_ID, device_map="cpu", dtype=torch.float32, ) return model def generate_tts(text, language, speaker, instruction): text = (text or "").strip() instruction = (instruction or "").strip() if not text: raise gr.Error("Écris une phrase à synthétiser.") tts = get_model() wavs, sr = tts.generate_custom_voice( text=text, language=language, speaker=speaker, instruct=instruction, ) output_path = os.path.join( tempfile.gettempdir(), f"qwen_tts_{int(time.time() * 1000)}.wav", ) sf.write(output_path, wavs[0], sr) intent_json = { "detected_glosses": [], "detected_facial_expression": "not_connected_yet", "subtitle": text, "voice_instruction": instruction, "language": language, "speaker": speaker, "pipeline_stage": "tts_only_mvp", } return output_path, text, intent_json with gr.Blocks(title="ASL to TTS MVP") as demo: gr.Markdown( """ # ASL to TTS MVP Première version: on teste seulement la brique TTS. Ensuite, on branchera: video ASL -> glosses -> emotion -> intent JSON -> subtitle -> voice instruction -> TTS. """ ) with gr.Row(): with gr.Column(): text_input = gr.Textbox( label="Subtitle temporaire", value="Hello, I am happy to see you today.", lines=3, ) instruction_input = gr.Textbox( label="Voice instruction", value="Speak with a warm, happy, expressive voice.", lines=2, ) language_input = gr.Dropdown( label="Language", choices=[ "Auto", "Chinese", "English", "Japanese", "Korean", "German", "French", "Russian", "Portuguese", "Spanish", "Italian", ], value="English", ) speaker_input = gr.Dropdown( label="Speaker", choices=[ "Vivian", "Serena", "Uncle_Fu", "Dylan", "Eric", "Ryan", "Aiden", "Ono_Anna", "Sohee", ], value="Ryan", ) button = gr.Button("Generate speech") with gr.Column(): audio_output = gr.Audio(label="Generated audio", type="filepath") subtitle_output = gr.Textbox(label="Subtitle") json_output = gr.JSON(label="Intent JSON") button.click( fn=generate_tts, inputs=[ text_input, language_input, speaker_input, instruction_input, ], outputs=[ audio_output, subtitle_output, json_output, ], ) if __name__ == "__main__": demo.queue().launch()