Aittsg / app.py
Athspi's picture
Update app.py
ae19a5c verified
raw
history blame
4.81 kB
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 ---
@app.get("/health", tags=["System"])
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)