Spaces:
Running
Running
import gradio as gr | |
import os | |
import uuid | |
import time | |
import logging | |
from gtts import gTTS, gTTSError | |
from fastapi import FastAPI # Import FastAPI for mounting | |
# --- Configuration --- | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
# Define a temporary directory for audio files if needed | |
# Gradio often handles temporary files well, but explicit control can be useful. | |
TEMP_DIR = "temp_audio_gradio" | |
os.makedirs(TEMP_DIR, exist_ok=True) | |
# Supported languages for the dropdown (add more as needed) | |
# You can find codes here: https://gtts.readthedocs.io/en/latest/module.html#languages-gtts-lang | |
SUPPORTED_LANGUAGES = { | |
"English": "en", | |
"Spanish": "es", | |
"French": "fr", | |
"German": "de", | |
"Italian": "it", | |
"Portuguese": "pt", | |
"Dutch": "nl", | |
"Russian": "ru", | |
"Japanese": "ja", | |
"Korean": "ko", | |
"Chinese (Mandarin/Simplified)": "zh-cn", | |
"Chinese (Mandarin/Traditional)": "zh-tw", | |
"Hindi": "hi", | |
"Arabic": "ar", | |
} | |
LANGUAGE_NAMES = list(SUPPORTED_LANGUAGES.keys()) | |
# --- Core gTTS Function for Gradio --- | |
def generate_gtts_audio(text_input: str, language_name: str): | |
""" | |
Takes text and language name, generates MP3 using gTTS, saves it temporarily, | |
and returns the filepath for the Gradio Audio component. | |
""" | |
if not text_input or not text_input.strip(): | |
# Raise a Gradio-specific error to show in the UI | |
raise gr.Error("Please enter some text to synthesize.") | |
if not language_name or language_name not in SUPPORTED_LANGUAGES: | |
raise gr.Error(f"Invalid language selected: {language_name}") | |
lang_code = SUPPORTED_LANGUAGES[language_name] | |
logger.info(f"Gradio request: lang='{lang_code}', text='{text_input[:50]}...'") | |
start_synth_time = time.time() | |
try: | |
# Create gTTS object | |
tts = gTTS(text=text_input, lang=lang_code, slow=False) | |
# Generate a unique filename for the temporary MP3 file | |
filename = f"gtts_speech_{uuid.uuid4()}.mp3" | |
filepath = os.path.join(TEMP_DIR, filename) | |
# Save the audio file | |
tts.save(filepath) | |
synthesis_time = time.time() - start_synth_time | |
logger.info(f"gTTS audio saved to '{filepath}' in {synthesis_time:.2f} seconds.") | |
# Return the path to the generated audio file | |
# Gradio's Audio component with type="filepath" will handle serving this file. | |
return filepath | |
except gTTSError as e: | |
logger.error(f"gTTS Error during generation: {e}", exc_info=True) | |
raise gr.Error(f"gTTS failed to generate speech. Error: {e}") | |
except Exception as e: | |
logger.error(f"An unexpected error occurred: {e}", exc_info=True) | |
raise gr.Error(f"An unexpected server error occurred. Error: {str(e)}") | |
# --- Create Gradio Interface --- | |
iface = gr.Interface( | |
fn=generate_gtts_audio, | |
inputs=[ | |
gr.Textbox( | |
label="Text to Synthesize", | |
placeholder="Enter the text you want to convert to speech...", | |
lines=4 | |
), | |
gr.Dropdown( | |
label="Language", | |
choices=LANGUAGE_NAMES, | |
value="English", # Default language | |
info="Select the language for the speech." | |
) | |
], | |
outputs=gr.Audio( | |
label="Generated Speech (MP3)", | |
type="filepath" # Gradio handles serving the file from the returned path | |
), | |
title="Text-to-Speech with gTTS", | |
description="Enter text and select a language to generate an MP3 audio file using Google Text-to-Speech.", | |
examples=[ | |
["Hello, this is a demonstration of the gTTS library.", "English"], | |
["Bonjour le monde, ceci est un test.", "French"], | |
["Hola mundo, esto es un ejemplo en español.", "Spanish"], | |
], | |
allow_flagging="never", # Disable the flagging feature if not needed | |
# You can add custom CSS or themes here if desired | |
# theme=gr.themes.Default() | |
) | |
# --- Setup FastAPI App (Optional, but standard for Spaces) --- | |
# This allows Gradio to be served alongside other potential FastAPI endpoints. | |
app = FastAPI() | |
# --- Mount the Gradio Interface onto the FastAPI app --- | |
# The Gradio UI will be available at the '/ ' route of your Space URL | |
app = gr.mount_gradio_app(app, iface, path="/") | |
# --- Optional: Add a simple health check for FastAPI --- | |
async def health_check(): | |
return {"status": "ok", "message": "Gradio service running"} | |
# --- How to Run Locally (for testing) --- | |
# if __name__ == "__main__": | |
# # When running locally, Gradio's launch() is often simpler | |
# # iface.launch(server_name="127.0.0.1", server_port=7860) | |
# # Or, if you want to test the FastAPI mounting locally: | |
# import uvicorn | |
# uvicorn.run(app, host="127.0.0.1", port=8000) |