|
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 |
|
|
|
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): |
|
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): |
|
|
|
char_limit = 100000000 |
|
if len(text) > char_limit: |
|
return f"Error: Use 15,000 Words at a time.", None, None |
|
|
|
|
|
voice = language_dict[language_code][speaker] |
|
communicate = edge_tts.Communicate(text, voice) |
|
|
|
|
|
temp_dir = os.path.join(tempfile.gettempdir(), "gradio") |
|
os.makedirs(temp_dir, exist_ok=True) |
|
|
|
|
|
tmp_path = os.path.join(temp_dir, f"audio_{int(time.time())}_{os.urandom(4).hex()}.mp3") |
|
|
|
try: |
|
await communicate.save(tmp_path) |
|
|
|
cleanup_file(tmp_path) |
|
|
|
|
|
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) |
|
output_audio = gr.Audio( |
|
type="filepath", |
|
label="Generated Audio" |
|
) |
|
download_link = gr.HTML( |
|
"", |
|
elem_classes="download-btn" |
|
) |
|
|
|
|
|
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) |
|
|