# app.py # Gradio TTS demo using GroqCloud / PlayAI TTS via the OpenAI-compatible Groq endpoint import os import tempfile import requests import gradio as gr from dotenv import load_dotenv # Load .env for local use (Hugging Face Spaces ignores if not present) load_dotenv() # --- Configuration --- GROQ_API_KEY = os.environ.get("GROQ_API_KEY") GROQ_TTS_ENDPOINT = "https://api.groq.com/openai/v1/audio/speech" DEFAULT_MODEL = "playai-tts" EXAMPLE_VOICES = [ "Fritz-PlayAI", "Emma-PlayAI", "Alloy-PlayAI", ] def synthesize_text(text: str, voice: str = None, model: str = DEFAULT_MODEL, response_format: str = "wav"): """Call Groq TTS and return path to temporary audio file.""" if not GROQ_API_KEY: return None, "Missing GROQ_API_KEY environment variable. Add it in your Hugging Face Space Secrets." if not text or text.strip() == "": return None, "Please provide some text to synthesize." payload = { "model": model, "input": text, "response_format": response_format, } if voice: payload["voice"] = voice headers = { "Content-Type": "application/json", "Authorization": f"Bearer {GROQ_API_KEY}", } try: resp = requests.post(GROQ_TTS_ENDPOINT, json=payload, headers=headers, stream=True, timeout=60) except Exception as e: return None, f"Request failed: {e}" if resp.status_code != 200: try: detail = resp.json() except Exception: detail = resp.text return None, f"Groq API error ({resp.status_code}): {detail}" suffix = ".wav" if response_format == "wav" else ".mp3" tmp = tempfile.NamedTemporaryFile(delete=False, suffix=suffix) for chunk in resp.iter_content(chunk_size=8192): if chunk: tmp.write(chunk) tmp.flush() tmp.close() return tmp.name, "Synthesis successful!" with gr.Blocks(title="GroqCloud TTS — Hugging Face Space") as demo: gr.Markdown("# 🎙️ GroqCloud Text-to-Speech\nConvert your text to natural speech using Groq TTS API.") with gr.Row(): with gr.Column(scale=3): txt = gr.Textbox(lines=6, label="Text", placeholder="Enter text here...") voice = gr.Dropdown(EXAMPLE_VOICES, label="Voice", value=EXAMPLE_VOICES[0]) resp_format = gr.Radio(["wav", "mp3"], value="wav", label="Output format") synth_btn = gr.Button("🔊 Synthesize") status = gr.Textbox(label="Status", interactive=False) with gr.Column(scale=2): audio_out = gr.Audio(label="Generated Audio", type="filepath") def on_synthesize(text, voice, response_format): path, msg = synthesize_text(text, voice, DEFAULT_MODEL, response_format) return path, msg synth_btn.click(on_synthesize, inputs=[txt, voice, resp_format], outputs=[audio_out, status]) # ✅ Important: launch the app! if __name__ == "__main__": demo.launch()