w-t-p-01 / app.py
hivecorp's picture
Update app.py
dd4d922 verified
raw
history blame
22.9 kB
import tempfile
import os
from pathlib import Path
import time
from threading import Timer
import edge_tts
import gradio as gr
language_dict = {
"Hindi": {
"Madhur": "hi-IN-MadhurNeural",
"Swara": "hi-IN-SwaraNeural"
},
"English": {
"Jenny": "en-US-JennyNeural",
"Guy": "en-US-GuyNeural",
"Ana": "en-US-AnaNeural",
"Aria": "en-US-AriaNeural",
"Brian": "en-US-BrianNeural",
"Christopher": "en-US-ChristopherNeural",
"Eric": "en-US-EricNeural",
"Michelle": "en-US-MichelleNeural",
"Roger": "en-US-RogerNeural",
"Natasha": "en-AU-NatashaNeural",
"William": "en-AU-WilliamNeural",
"Clara": "en-CA-ClaraNeural",
"Liam": "en-CA-LiamNeural",
"Libby": "en-GB-LibbyNeural",
"Maisie": "en-GB-MaisieNeural",
"Ryan": "en-GB-RyanNeural",
"Sonia": "en-GB-SoniaNeural",
"Thomas": "en-GB-ThomasNeural",
"Sam": "en-HK-SamNeural",
"Yan": "en-HK-YanNeural",
"Connor": "en-IE-ConnorNeural",
"Emily": "en-IE-EmilyNeural",
"Neerja": "en-IN-NeerjaNeural",
"Prabhat": "en-IN-PrabhatNeural",
"Asilia": "en-KE-AsiliaNeural",
"Chilemba": "en-KE-ChilembaNeural",
"Abeo": "en-NG-AbeoNeural",
"Ezinne": "en-NG-EzinneNeural",
"Mitchell": "en-NZ-MitchellNeural",
"James": "en-PH-JamesNeural",
"Rosa": "en-PH-RosaNeural",
"Luna": "en-SG-LunaNeural",
"Wayne": "en-SG-WayneNeural",
"Elimu": "en-TZ-ElimuNeural",
"Imani": "en-TZ-ImaniNeural",
"Leah": "en-ZA-LeahNeural",
"Luke": "en-ZA-LukeNeural"
},
"Spanish": {
"Elena": "es-AR-ElenaNeural",
"Tomas": "es-AR-TomasNeural",
"Marcelo": "es-BO-MarceloNeural",
"Sofia": "es-BO-SofiaNeural",
"Gonzalo": "es-CO-GonzaloNeural",
"Salome": "es-CO-SalomeNeural",
"Juan": "es-CR-JuanNeural",
"Maria": "es-CR-MariaNeural",
"Belkys": "es-CU-BelkysNeural",
"Emilio": "es-DO-EmilioNeural",
"Ramona": "es-DO-RamonaNeural",
"Andrea": "es-EC-AndreaNeural",
"Luis": "es-EC-LuisNeural",
"Alvaro": "es-ES-AlvaroNeural",
"Elvira": "es-ES-ElviraNeural",
"Teresa": "es-GQ-TeresaNeural",
"Andres": "es-GT-AndresNeural",
"Marta": "es-GT-MartaNeural",
"Carlos": "es-HN-CarlosNeural",
"Karla": "es-HN-KarlaNeural",
"Federico": "es-NI-FedericoNeural",
"Yolanda": "es-NI-YolandaNeural",
"Margarita": "es-PA-MargaritaNeural",
"Roberto": "es-PA-RobertoNeural",
"Alex": "es-PE-AlexNeural",
"Camila": "es-PE-CamilaNeural",
"Karina": "es-PR-KarinaNeural",
"Victor": "es-PR-VictorNeural",
"Mario": "es-PY-MarioNeural",
"Tania": "es-PY-TaniaNeural",
"Lorena": "es-SV-LorenaNeural",
"Rodrigo": "es-SV-RodrigoNeural",
"Alonso": "es-US-AlonsoNeural",
"Paloma": "es-US-PalomaNeural",
"Mateo": "es-UY-MateoNeural",
"Valentina": "es-UY-ValentinaNeural",
"Paola": "es-VE-PaolaNeural",
"Sebastian": "es-VE-SebastianNeural"
},
"Arabic": {
"Hamed": "ar-SA-HamedNeural",
"Zariyah": "ar-SA-ZariyahNeural",
"Fatima": "ar-AE-FatimaNeural",
"Hamdan": "ar-AE-HamdanNeural",
"Ali": "ar-BH-AliNeural",
"Laila": "ar-BH-LailaNeural",
"Ismael": "ar-DZ-IsmaelNeural",
"Salma": "ar-EG-SalmaNeural",
"Shakir": "ar-EG-ShakirNeural",
"Bassel": "ar-IQ-BasselNeural",
"Rana": "ar-IQ-RanaNeural",
"Sana": "ar-JO-SanaNeural",
"Taim": "ar-JO-TaimNeural",
"Fahed": "ar-KW-FahedNeural",
"Noura": "ar-KW-NouraNeural",
"Layla": "ar-LB-LaylaNeural",
"Rami": "ar-LB-RamiNeural",
"Iman": "ar-LY-ImanNeural",
"Omar": "ar-LY-OmarNeural",
"Jamal": "ar-MA-JamalNeural",
"Mouna": "ar-MA-MounaNeural",
"Abdullah": "ar-OM-AbdullahNeural",
"Aysha": "ar-OM-AyshaNeural",
"Amal": "ar-QA-AmalNeural",
"Moaz": "ar-QA-MoazNeural",
"Amany": "ar-SY-AmanyNeural",
"Laith": "ar-SY-LaithNeural",
"Hedi": "ar-TN-HediNeural",
"Reem": "ar-TN-ReemNeural",
"Maryam": "ar-YE-MaryamNeural",
"Saleh": "ar-YE-SalehNeural"
},
"Korean": {
"Sun-Hi": "ko-KR-SunHiNeural",
"InJoon": "ko-KR-InJoonNeural"
},
"Thai": {
"Premwadee": "th-TH-PremwadeeNeural",
"Niwat": "th-TH-NiwatNeural"
},
"Vietnamese": {
"HoaiMy": "vi-VN-HoaiMyNeural",
"NamMinh": "vi-VN-NamMinhNeural"
},
"Japanese": {
"Nanami": "ja-JP-NanamiNeural",
"Keita": "ja-JP-KeitaNeural"
},
"French": {
"Denise": "fr-FR-DeniseNeural",
"Eloise": "fr-FR-EloiseNeural",
"Henri": "fr-FR-HenriNeural",
"Sylvie": "fr-CA-SylvieNeural",
"Antoine": "fr-CA-AntoineNeural",
"Jean": "fr-CA-JeanNeural",
"Ariane": "fr-CH-ArianeNeural",
"Fabrice": "fr-CH-FabriceNeural",
"Charline": "fr-BE-CharlineNeural",
"Gerard": "fr-BE-GerardNeural"
},
"Portuguese": {
"Francisca": "pt-BR-FranciscaNeural",
"Antonio": "pt-BR-AntonioNeural",
"Duarte": "pt-PT-DuarteNeural",
"Raquel": "pt-PT-RaquelNeural"
},
"Indonesian": {
"Ardi": "id-ID-ArdiNeural",
"Gadis": "id-ID-GadisNeural"
},
"Hebrew": {
"Avri": "he-IL-AvriNeural",
"Hila": "he-IL-HilaNeural"
},
"Italian": {
"Isabella": "it-IT-IsabellaNeural",
"Diego": "it-IT-DiegoNeural",
"Elsa": "it-IT-ElsaNeural"
},
"Dutch": {
"Colette": "nl-NL-ColetteNeural",
"Fenna": "nl-NL-FennaNeural",
"Maarten": "nl-NL-MaartenNeural",
"Arnaud": "nl-BE-ArnaudNeural",
"Dena": "nl-BE-DenaNeural"
},
"Malay": {
"Osman": "ms-MY-OsmanNeural",
"Yasmin": "ms-MY-YasminNeural"
},
"Norwegian": {
"Pernille": "nb-NO-PernilleNeural",
"Finn": "nb-NO-FinnNeural"
},
"Swedish": {
"Sofie": "sv-SE-SofieNeural",
"Mattias": "sv-SE-MattiasNeural"
},
"Greek": {
"Athina": "el-GR-AthinaNeural",
"Nestoras": "el-GR-NestorasNeural"
},
"German": {
"Katja": "de-DE-KatjaNeural",
"Amala": "de-DE-AmalaNeural",
"Conrad": "de-DE-ConradNeural",
"Killian": "de-DE-KillianNeural",
"Ingrid": "de-AT-IngridNeural",
"Jonas": "de-AT-JonasNeural",
"Jan": "de-CH-JanNeural",
"Leni": "de-CH-LeniNeural"
},
"Afrikaans": {
"Adri": "af-ZA-AdriNeural",
"Willem": "af-ZA-WillemNeural"
},
"Amharic": {
"Ameha": "am-ET-AmehaNeural",
"Mekdes": "am-ET-MekdesNeural"
},
"Azerbaijani": {
"Babek": "az-AZ-BabekNeural",
"Banu": "az-AZ-BanuNeural"
},
"Bulgarian": {
"Borislav": "bg-BG-BorislavNeural",
"Kalina": "bg-BG-KalinaNeural"
},
"Bengali": {
"Nabanita": "bn-BD-NabanitaNeural",
"Pradeep": "bn-BD-PradeepNeural",
"Bashkar": "bn-IN-BashkarNeural",
"Tanishaa": "bn-IN-TanishaaNeural"
},
"Bosnian": {
"Goran": "bs-BA-GoranNeural",
"Vesna": "bs-BA-VesnaNeural"
},
"Catalan": {
"Joana": "ca-ES-JoanaNeural",
"Enric": "ca-ES-EnricNeural"
},
"Czech": {
"Antonin": "cs-CZ-AntoninNeural",
"Vlasta": "cs-CZ-VlastaNeural"
},
"Welsh": {
"Aled": "cy-GB-AledNeural",
"Nia": "cy-GB-NiaNeural"
},
"Danish": {
"Christel": "da-DK-ChristelNeural",
"Jeppe": "da-DK-JeppeNeural"
},
"Estonian": {
"Anu": "et-EE-AnuNeural",
"Kert": "et-EE-KertNeural"
},
"Persian": {
"Dilara": "fa-IR-DilaraNeural",
"Farid": "fa-IR-FaridNeural"
},
"Finnish": {
"Harri": "fi-FI-HarriNeural",
"Noora": "fi-FI-NooraNeural"
},
"Irish": {
"Colm": "ga-IE-ColmNeural",
"Orla": "ga-IE-OrlaNeural"
},
"Galician": {
"Roi": "gl-ES-RoiNeural",
"Sabela": "gl-ES-SabelaNeural"
},
"Gujarati": {
"Dhwani": "gu-IN-DhwaniNeural",
"Niranjan": "gu-IN-NiranjanNeural"
},
"Croatian": {
"Gabrijela": "hr-HR-GabrijelaNeural",
"Srecko": "hr-HR-SreckoNeural"
},
"Hungarian": {
"Noemi": "hu-HU-NoemiNeural",
"Tamas": "hu-HU-TamasNeural"
},
"Icelandic": {
"Gudrun": "is-IS-GudrunNeural",
"Gunnar": "is-IS-GunnarNeural"
},
"Javanese": {
"Dimas": "jv-ID-DimasNeural",
"Siti": "jv-ID-SitiNeural"
},
"Georgian": {
"Eka": "ka-GE-EkaNeural",
"Giorgi": "ka-GE-GiorgiNeural"
},
"Kazakh": {
"Aigul": "kk-KZ-AigulNeural",
"Daulet": "kk-KZ-DauletNeural"
},
"Khmer": {
"Piseth": "km-KH-PisethNeural",
"Sreymom": "km-KH-SreymomNeural"
},
"Kannada": {
"Gagan": "kn-IN-GaganNeural",
"Sapna": "kn-IN-SapnaNeural"
},
"Lao": {
"Chanthavong": "lo-LA-ChanthavongNeural",
"Keomany": "lo-LA-KeomanyNeural"
},
"Lithuanian": {
"Leonas": "lt-LT-LeonasNeural",
"Ona": "lt-LT-OnaNeural"
},
"Latvian": {
"Everita": "lv-LV-EveritaNeural",
"Nils": "lv-LV-NilsNeural"
},
"Macedonian": {
"Aleksandar": "mk-MK-AleksandarNeural",
"Marija": "mk-MK-MarijaNeural"
},
"Malayalam": {
"Midhun": "ml-IN-MidhunNeural",
"Sobhana": "ml-IN-SobhanaNeural"
},
"Mongolian": {
"Bataa": "mn-MN-BataaNeural",
"Yesui": "mn-MN-YesuiNeural"
},
"Marathi": {
"Aarohi": "mr-IN-AarohiNeural",
"Manohar": "mr-IN-ManoharNeural"
},
"Maltese": {
"Grace": "mt-MT-GraceNeural",
"Joseph": "mt-MT-JosephNeural"
},
"Burmese": {
"Nilar": "my-MM-NilarNeural",
"Thiha": "my-MM-ThihaNeural"
},
"Nepali": {
"Hemkala": "ne-NP-HemkalaNeural",
"Sagar": "ne-NP-SagarNeural"
},
"Polish": {
"Marek": "pl-PL-MarekNeural",
"Zofia": "pl-PL-ZofiaNeural"
},
"Pashto": {
"Gul Nawaz": "ps-AF-GulNawazNeural",
"Latifa": "ps-AF-LatifaNeural"
},
"Romanian": {
"Alina": "ro-RO-AlinaNeural",
"Emil": "ro-RO-EmilNeural"
},
"Russian": {
"Svetlana": "ru-RU-SvetlanaNeural",
"Dmitry": "ru-RU-DmitryNeural"
},
"Sinhala": {
"Sameera": "si-LK-SameeraNeural",
"Thilini": "si-LK-ThiliniNeural"
},
"Slovak": {
"Lukas": "sk-SK-LukasNeural",
"Viktoria": "sk-SK-ViktoriaNeural"
},
"Slovenian": {
"Petra": "sl-SI-PetraNeural",
"Rok": "sl-SI-RokNeural"
},
"Somali": {
"Muuse": "so-SO-MuuseNeural",
"Ubax": "so-SO-UbaxNeural"
},
"Albanian": {
"Anila": "sq-AL-AnilaNeural",
"Ilir": "sq-AL-IlirNeural"
},
"Serbian": {
"Nicholas": "sr-RS-NicholasNeural",
"Sophie": "sr-RS-SophieNeural"
},
"Sundanese": {
"Jajang": "su-ID-JajangNeural",
"Tuti": "su-ID-TutiNeural"
},
"Swahili": {
"Rafiki": "sw-KE-RafikiNeural",
"Zuri": "sw-KE-ZuriNeural",
"Daudi": "sw-TZ-DaudiNeural",
"Rehema": "sw-TZ-RehemaNeural"
},
"Tamil": {
"Pallavi": "ta-IN-PallaviNeural",
"Valluvar": "ta-IN-ValluvarNeural",
"Kumar": "ta-LK-KumarNeural",
"Saranya": "ta-LK-SaranyaNeural",
"Kani": "ta-MY-KaniNeural",
"Surya": "ta-MY-SuryaNeural",
"Anbu": "ta-SG-AnbuNeural"
},
"Telugu": {
"Mohan": "te-IN-MohanNeural",
"Shruti": "te-IN-ShrutiNeural"
},
"Turkish": {
"Ahmet": "tr-TR-AhmetNeural",
"Emel": "tr-TR-EmelNeural"
},
"Ukrainian": {
"Ostap": "uk-UA-OstapNeural",
"Polina": "uk-UA-PolinaNeural"
},
"Urdu": {
"Gul": "ur-IN-GulNeural",
"Salman": "ur-IN-SalmanNeural",
"Asad": "ur-PK-AsadNeural",
"Uzma": "ur-PK-UzmaNeural"
},
"Uzbek": {
"Madina": "uz-UZ-MadinaNeural",
"Sardor": "uz-UZ-SardorNeural"
},
"Mandarin": {
"Xiaoxiao": "zh-CN-XiaoxiaoNeural",
"Yunyang": "zh-CN-YunyangNeural",
"Yunxi": "zh-CN-YunxiNeural",
"Xiaoyi": "zh-CN-XiaoyiNeural",
"Yunjian": "zh-CN-YunjianNeural",
"Yunxia": "zh-CN-YunxiaNeural",
"Xiaobei": "zh-CN-liaoning-XiaobeiNeural",
"Xiaoni": "zh-CN-shaanxi-XiaoniNeural",
"HiuMaan": "zh-HK-HiuMaanNeural",
"HiuGaai": "zh-HK-HiuGaaiNeural",
"WanLung": "zh-HK-WanLungNeural",
"HsiaoChen": "zh-TW-HsiaoChenNeural",
"HsiaoYu": "zh-TW-HsiaoYuNeural",
"YunJhe": "zh-TW-YunJheNeural"
},
"Zulu": {
"Thando": "zu-ZA-ThandoNeural",
"Themba": "zu-ZA-ThembaNeural"
}
}
def create_download_link(audio_path):
if audio_path is None:
return None
filename = Path(audio_path).name
# Update URL format to match Gradio's file serving pattern
base_url = "hivecorp-w-t-p-01.hf.space"
file_url = f"https://{base_url}/file={audio_path}"
return f"""
<a href="{file_url}"
download="{filename}"
target="_blank"
rel="noopener noreferrer"
style="display: inline-block; padding: 10px 20px; background: linear-gradient(135deg, #4776E6, #8E54E9); color: white; text-decoration: none; border-radius: 8px; font-weight: 600; transition: all 0.3s ease;"
onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 5px 15px rgba(71, 118, 230, 0.3)';"
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='none';"
onclick="event.preventDefault(); fetch(this.href).then(resp => resp.blob()).then(blob => {{
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = '{filename}';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}});">
Download Audio File
</a>
"""
def cleanup_file(filepath, delay=300): # 300 seconds = 5 minutes
def delete_file():
try:
if os.path.exists(filepath):
os.remove(filepath)
print(f"Cleaned up file: {filepath}")
except Exception as e:
print(f"Error cleaning up file {filepath}: {e}")
Timer(delay, delete_file).start()
async def text_to_speech_edge(text, language_code, speaker, tashkeel_checkbox=False):
# Define the character limit
char_limit = 100000000
if len(text) > char_limit:
return f"Error: Use 15,000 Words at a time.", None, None
# Get the voice for the selected language and speaker
voice = language_dict[language_code][speaker]
communicate = edge_tts.Communicate(text, voice)
# Create temp directory if it doesn't exist
temp_dir = os.path.join(tempfile.gettempdir(), "gradio")
os.makedirs(temp_dir, exist_ok=True)
# Generate unique filename
tmp_path = os.path.join(temp_dir, f"audio_{int(time.time())}_{os.urandom(4).hex()}.mp3")
try:
await communicate.save(tmp_path)
# Schedule file cleanup after 5 minutes
cleanup_file(tmp_path)
# Update the download link HTML structure
download_html = f"""
<a href="https://hivecorp-w-t-p-01.hf.space/gradio_api/file={tmp_path}"
download="{Path(tmp_path).name}"
target="_blank"
rel="noopener noreferrer"
style="display: inline-block; padding: 10px 20px; background: linear-gradient(135deg, #4776E6, #8E54E9); color: white; text-decoration: none; border-radius: 8px; font-weight: 600; transition: all 0.3s ease;"
onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 5px 15px rgba(71, 118, 230, 0.3)';"
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='none';"
onclick="event.preventDefault(); fetch(this.href).then(resp => resp.blob()).then(blob => {{
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = '{Path(tmp_path).name}';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}});">
Download Audio File
</a>
"""
return text, tmp_path, download_html
except Exception as e:
print(f"Error generating audio: {e}")
return f"Error: {str(e)}", None, None
def get_speakers(language):
print(language)
speakers = list(language_dict[language].keys())
return gr.Dropdown(choices=speakers, value=speakers[0], interactive=True), gr.Checkbox(visible=language == "Arabic", interactive=True)
default_language = None
default_speaker = None
with gr.Blocks(
title="WritooAI Free Plan",
css="""
:root {
--primary-color: #4776E6;
--secondary-color: #8E54E9;
--background-light: #ffffff;
--card-light: #f8f9fa;
--text-dark: #2d3436;
--text-gray: #636e72;
--border-color: #e0e0e0;
}
@media (max-width: 768px) {
.container {
padding: 10px !important;
}
.header h1 {
font-size: 1.5em !important;
}
}
body {
background-color: var(--background-light);
}
.container {
background-color: var(--background-light);
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.header {
text-align: center;
margin-bottom: 30px;
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
padding: 25px;
border-radius: 15px;
color: white;
box-shadow: 0 4px 15px rgba(71, 118, 230, 0.2);
}
.input-section, .output-section {
background-color: var(--card-light);
padding: 25px;
border-radius: 15px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
border: 1px solid var(--border-color);
width: 100%;
}
.input-box textarea {
min-height: 120px !important;
font-size: 16px !important;
border: 1px solid var(--border-color) !important;
border-radius: 10px !important;
padding: 15px !important;
width: 100% !important;
}
.dropdown {
width: 100% !important;
}
select, input[type="text"] {
width: 100% !important;
padding: 12px !important;
border-radius: 8px !important;
border: 1px solid var(--border-color) !important;
}
.generate-btn {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)) !important;
padding: 15px 30px !important;
border-radius: 10px !important;
font-weight: 600 !important;
letter-spacing: 0.5px !important;
width: 100% !important;
margin-top: 15px !important;
}
.generate-btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(71, 118, 230, 0.3) !important;
}
.download-btn {
margin-top: 20px;
text-align: center;
}
.download-btn a {
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
padding: 12px 25px;
border-radius: 10px;
text-decoration: none;
font-weight: 600;
letter-spacing: 0.5px;
transition: all 0.3s ease;
gap: 8px;
width: 100%;
max-width: 300px;
}
.download-btn a:before {
content: "⬇️";
font-size: 1.2em;
}
.download-btn a:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(71, 118, 230, 0.3);
}
/* Audio player styling */
audio {
width: 100% !important;
margin: 15px 0 !important;
border-radius: 10px !important;
}
/* Hide output text */
#output-text {
display: none !important;
}
/* Download button styling */
.download-btn {
text-align: center;
margin-top: 15px;
}
.download-btn a {
display: inline-block;
padding: 10px 20px;
background: #4776e6;
color: white;
text-decoration: none;
border-radius: 5px;
transition: all 0.3s ease;
}
.download-btn a:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(71, 118, 230, 0.3);
}
"""
) as demo:
with gr.Column(elem_classes="container"):
gr.HTML(
"""
<div class="header">
<h2>WritooAI Pro Plan - 15+ more Human-like Voice </h2>
</div>
"""
)
with gr.Row(elem_classes="mobile-stack"):
with gr.Column(elem_classes="input-section mobile-full"):
input_text = gr.Textbox(
lines=5,
label="Input Text",
placeholder="Enter text to convert to speech...",
elem_classes="input-box"
)
with gr.Row(elem_classes="mobile-stack"):
language = gr.Dropdown(
choices=list(language_dict.keys()),
value=default_language,
label="Select Language",
interactive=True,
elem_classes="dropdown mobile-full"
)
speaker = gr.Dropdown(
choices=[],
value=default_speaker,
label="Choose Voice",
interactive=False,
elem_classes="dropdown mobile-full"
)
tashkeel_checkbox = gr.Checkbox(
label="Tashkeel (Arabic Only)",
value=False,
visible=False,
interactive=False
)
run_btn = gr.Button(
value="🎵 Generate Audio",
variant="primary",
elem_classes="generate-btn mobile-full"
)
with gr.Column(elem_classes="output-section mobile-full"):
output_text = gr.Textbox(label="", visible=False) # Hidden
output_audio = gr.Audio(
type="filepath",
label="Generated Audio"
)
download_link = gr.HTML(
"",
elem_classes="download-btn"
)
# Keep existing event handlers
language.change(get_speakers, inputs=[language], outputs=[speaker, tashkeel_checkbox])
run_btn.click(
text_to_speech_edge,
inputs=[input_text, language, speaker, tashkeel_checkbox],
outputs=[output_text, output_audio, download_link]
)
if __name__ == "__main__":
demo.queue().launch(share=False)