Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import edge_tts | |
| import tempfile | |
| import os | |
| import asyncio | |
| # Dictionary of voices with language and voice details | |
| language_dict = { | |
| 'English-Jenny (Female)': 'en-US-JennyNeural', | |
| 'English-Guy (Male)': 'en-US-GuyNeural', | |
| 'English-Ana (Female)': 'en-US-AnaNeural', | |
| 'English-Aria (Female)': 'en-US-AriaNeural', | |
| 'English-Christopher (Male)': 'en-US-ChristopherNeural', | |
| 'English-Eric (Male)': 'en-US-EricNeural', | |
| 'English-Michelle (Female)': 'en-US-MichelleNeural', | |
| 'English-Roger (Male)': 'en-US-RogerNeural', | |
| 'Spanish (Mexican)-Dalia (Female)': 'es-MX-DaliaNeural', | |
| 'Spanish (Mexican)-Jorge (Male)': 'es-MX-JorgeNeural', | |
| 'Korean-Sun-Hi (Female)': 'ko-KR-SunHiNeural', | |
| 'Korean-InJoon (Male)': 'ko-KR-InJoonNeural', | |
| 'Thai-Premwadee (Female)': 'th-TH-PremwadeeNeural', | |
| 'Thai-Niwat (Male)': 'th-TH-NiwatNeural', | |
| 'Vietnamese-HoaiMy (Female)': 'vi-VN-HoaiMyNeural', | |
| 'Vietnamese-NamMinh (Male)': 'vi-VN-NamMinhNeural', | |
| 'Japanese-Nanami (Female)': 'ja-JP-NanamiNeural', | |
| 'Japanese-Keita (Male)': 'ja-JP-KeitaNeural', | |
| 'French-Denise (Female)': 'fr-FR-DeniseNeural', | |
| 'French-Eloise (Female)': 'fr-FR-EloiseNeural', | |
| 'French-Henri (Male)': 'fr-FR-HenriNeural', | |
| 'Brazilian-Francisca (Female)': 'pt-BR-FranciscaNeural', | |
| 'Brazilian-Antonio (Male)': 'pt-BR-AntonioNeural', | |
| 'Indonesian-Ardi (Male)': 'id-ID-ArdiNeural', | |
| 'Indonesian-Gadis (Female)': 'id-ID-GadisNeural', | |
| 'Hebrew-Avri (Male)': 'he-IL-AvriNeural', | |
| 'Hebrew-Hila (Female)': 'he-IL-HilaNeural', | |
| 'Italian-Isabella (Female)': 'it-IT-IsabellaNeural', | |
| 'Italian-Diego (Male)': 'it-IT-DiegoNeural', | |
| 'Italian-Elsa (Female)': 'it-IT-ElsaNeural', | |
| 'Dutch-Colette (Female)': 'nl-NL-ColetteNeural', | |
| 'Dutch-Fenna (Female)': 'nl-NL-FennaNeural', | |
| 'Dutch-Maarten (Male)': 'nl-NL-MaartenNeural', | |
| 'Malay-Osman (Male)': 'ms-MY-OsmanNeural', | |
| 'Malay-Yasmin (Female)': 'ms-MY-YasminNeural', | |
| 'Norwegian-Pernille (Female)': 'nb-NO-PernilleNeural', | |
| 'Norwegian-Finn (Male)': 'nb-NO-FinnNeural', | |
| 'Swedish-Sofie (Female)': 'sv-SE-SofieNeural', | |
| 'Swedish-Mattias (Male)': 'sv-SE-MattiasNeural', | |
| 'Arabic-Hamed (Male)': 'ar-SA-HamedNeural', | |
| 'Arabic-Zariyah (Female)': 'ar-SA-ZariyahNeural', | |
| 'Greek-Athina (Female)': 'el-GR-AthinaNeural', | |
| 'Greek-Nestoras (Male)': 'el-GR-NestorasNeural', | |
| 'German-Katja (Female)': 'de-DE-KatjaNeural', | |
| 'German-Amala (Female)': 'de-DE-AmalaNeural', | |
| 'German-Conrad (Male)': 'de-DE-ConradNeural', | |
| 'German-Killian (Male)': 'de-DE-KillianNeural', | |
| 'Afrikaans-Adri (Female)': 'af-ZA-AdriNeural', | |
| 'Afrikaans-Willem (Male)': 'af-ZA-WillemNeural', | |
| 'Ethiopian-Ameha (Male)': 'am-ET-AmehaNeural', | |
| 'Ethiopian-Mekdes (Female)': 'am-ET-MekdesNeural', | |
| 'Arabic (UAE)-Fatima (Female)': 'ar-AE-FatimaNeural', | |
| 'Arabic (UAE)-Hamdan (Male)': 'ar-AE-HamdanNeural', | |
| 'Arabic (Bahrain)-Ali (Male)': 'ar-BH-AliNeural', | |
| 'Arabic (Bahrain)-Laila (Female)': 'ar-BH-LailaNeural', | |
| 'Arabic (Algeria)-Ismael (Male)': 'ar-DZ-IsmaelNeural', | |
| 'Arabic (Egypt)-Salma (Female)': 'ar-EG-SalmaNeural', | |
| 'Arabic (Egypt)-Shakir (Male)': 'ar-EG-ShakirNeural', | |
| 'Arabic (Iraq)-Bassel (Male)': 'ar-IQ-BasselNeural', | |
| 'Arabic (Iraq)-Rana (Female)': 'ar-IQ-RanaNeural', | |
| 'Arabic (Jordan)-Sana (Female)': 'ar-JO-SanaNeural', | |
| 'Arabic (Jordan)-Taim (Male)': 'ar-JO-TaimNeural', | |
| 'Arabic (Kuwait)-Fahed (Male)': 'ar-KW-FahedNeural', | |
| 'Arabic (Kuwait)-Noura (Female)': 'ar-KW-NouraNeural', | |
| 'Arabic (Lebanon)-Layla (Female)': 'ar-LB-LaylaNeural', | |
| 'Arabic (Lebanon)-Rami (Male)': 'ar-LB-RamiNeural', | |
| 'Arabic (Libya)-Iman (Female)': 'ar-LY-ImanNeural', | |
| 'Arabic (Libya)-Omar (Male)': 'ar-LY-OmarNeural', | |
| 'Arabic (Morocco)-Jamal (Male)': 'ar-MA-JamalNeural', | |
| 'Arabic (Morocco)-Mouna (Female)': 'ar-MA-MounaNeural', | |
| 'Arabic (Oman)-Abdullah (Male)': 'ar-OM-AbdullahNeural', | |
| 'Arabic (Oman)-Aysha (Female)': 'ar-OM-AyshaNeural', | |
| 'Arabic (Qatar)-Amal (Female)': 'ar-QA-AmalNeural', | |
| 'Arabic (Qatar)-Moaz (Male)': 'ar-QA-MoazNeural', | |
| 'Arabic (Syria)-Amany (Female)': 'ar-SY-AmanyNeural', | |
| 'Arabic (Syria)-Laith (Male)': 'ar-SY-LaithNeural', | |
| 'Arabic (Tunisia)-Hedi (Male)': 'ar-TN-HediNeural', | |
| 'Arabic (Tunisia)-Reem (Female)': 'ar-TN-ReemNeural', | |
| 'Arabic (Yemen)-Maryam (Female)': 'ar-YE-MaryamNeural', | |
| 'Arabic (Yemen)-Saleh (Male)': 'ar-YE-SalehNeural', | |
| 'Azerbaijani-Babek (Male)': 'az-AZ-BabekNeural', | |
| 'Azerbaijani-Banu (Female)': 'az-AZ-BanuNeural', | |
| 'Bulgarian-Borislav (Male)': 'bg-BG-BorislavNeural', | |
| 'Bulgarian-Kalina (Female)': 'bg-BG-KalinaNeural', | |
| 'Bengali (Bangladesh)-Nabanita (Female)': 'bn-BD-NabanitaNeural', | |
| 'Bengali (Bangladesh)-Pradeep (Male)': 'bn-BD-PradeepNeural', | |
| 'Bengali (India)-Bashkar (Male)': 'bn-IN-BashkarNeural', | |
| 'Bengali (India)-Tanishaa (Female)': 'bn-IN-TanishaaNeural', | |
| 'Bosniak (Bosnia and Herzegovina)-Goran (Male)': 'bs-BA-GoranNeural', | |
| 'Bosniak (Bosnia and Herzegovina)-Vesna (Female)': 'bs-BA-VesnaNeural', | |
| 'Catalan (Spain)-Joana (Female)': 'ca-ES-JoanaNeural', | |
| 'Catalan (Spain)-Enric (Male)': 'ca-ES-EnricNeural', | |
| 'Czech (Czech Republic)-Antonin (Male)': 'cs-CZ-AntoninNeural', | |
| 'Czech (Czech Republic)-Vlasta (Female)': 'cs-CZ-VlastaNeural', | |
| 'Welsh (UK)-Aled (Male)': 'cy-GB-AledNeural', | |
| 'Welsh (UK)-Nia (Female)': 'cy-GB-NiaNeural', | |
| 'Danish (Denmark)-Christel (Female)': 'da-DK-ChristelNeural', | |
| 'Danish (Denmark)-Jeppe (Male)': 'da-DK-JeppeNeural', | |
| 'German (Austria)-Ingrid (Female)': 'de-AT-IngridNeural', | |
| 'German (Austria)-Jonas (Male)': 'de-AT-JonasNeural', | |
| 'German (Switzerland)-Jan (Male)': 'de-CH-JanNeural', | |
| 'German (Switzerland)-Leni (Female)': 'de-CH-LeniNeural', | |
| 'English (Australia)-Natasha (Female)': 'en-AU-NatashaNeural', | |
| 'English (Australia)-William (Male)': 'en-AU-WilliamNeural', | |
| 'English (Canada)-Clara (Female)': 'en-CA-ClaraNeural', | |
| 'English (Canada)-Liam (Male)': 'en-CA-LiamNeural', | |
| 'English (UK)-Libby (Female)': 'en-GB-LibbyNeural', | |
| 'English (UK)-Maisie (Female)': 'en-GB-MaisieNeural', | |
| 'English (UK)-Ryan (Male)': 'en-GB-RyanNeural', | |
| 'English (UK)-Sonia (Female)': 'en-GB-SoniaNeural', | |
| 'English (UK)-Thomas (Male)': 'en-GB-ThomasNeural', | |
| 'English (Hong Kong)-Sam (Male)': 'en-HK-SamNeural', | |
| 'English (Hong Kong)-Yan (Female)': 'en-HK-YanNeural', | |
| 'English (Ireland)-Connor (Male)': 'en-IE-ConnorNeural', | |
| 'English (Ireland)-Emily (Female)': 'en-IE-EmilyNeural', | |
| 'English (India)-Neerja (Female)': 'en-IN-NeerjaNeural', | |
| 'English (India)-Prabhat (Male)': 'en-IN-PrabhatNeural', | |
| 'English (Kenya)-Asilia (Female)': 'en-KE-AsiliaNeural', | |
| 'English (Kenya)-Chilemba (Male)': 'en-KE-ChilembaNeural', | |
| 'English (Nigeria)-Abeo (Male)': 'en-NG-AbeoNeural', | |
| 'English (Nigeria)-Ezinne (Female)': 'en-NG-EzinneNeural', | |
| 'English (New Zealand)-Mitchell (Male)': 'en-NZ-MitchellNeural', | |
| 'English (Philippines)-James (Male)': 'en-PH-JamesNeural', | |
| 'English (Philippines)-Rosa (Female)': 'en-PH-RosaNeural', | |
| 'English (Singapore)-Luna (Female)': 'en-SG-LunaNeural', | |
| 'English (Singapore)-Wayne (Male)': 'en-SG-WayneNeural', | |
| 'English (Tanzania)-Elimu (Male)': 'en-TZ-ElimuNeural', | |
| 'English (Tanzania)-Imani (Female)': 'en-TZ-ImaniNeural', | |
| 'English (South Africa)-Leah (Female)': 'en-ZA-LeahNeural', | |
| 'English (South Africa)-Luke (Male)': 'en-ZA-LukeNeural', | |
| 'Spanish (Argentina)-Elena (Female)': 'es-AR-ElenaNeural', | |
| 'Spanish (Argentina)-Tomas (Male)': 'es-AR-TomasNeural', | |
| 'Spanish (Bolivia)-Marcelo (Male)': 'es-BO-MarceloNeural', | |
| 'Spanish (Bolivia)-Sofia (Female)': 'es-BO-SofiaNeural', | |
| 'Spanish (Colombia)-Gonzalo (Male)': 'es-CO-GonzaloNeural', | |
| 'Spanish (Colombia)-Salome (Female)': 'es-CO-SalomeNeural', | |
| 'Spanish (Costa Rica)-Juan (Male)': 'es-CR-JuanNeural', | |
| 'Spanish (Costa Rica)-Maria (Female)': 'es-CR-MariaNeural', | |
| 'Spanish (Cuba)-Belkys (Female)': 'es-CU-BelkysNeural', | |
| 'Spanish (Dominican Republic)-Emilio (Male)': 'es-DO-EmilioNeural', | |
| 'Spanish (Dominican Republic)-Ramona (Female)': 'es-DO-RamonaNeural', | |
| 'Spanish (Ecuador)-Andrea (Female)': 'es-EC-AndreaNeural', | |
| 'Spanish (Ecuador)-Luis (Male)': 'es-EC-LuisNeural', | |
| 'Spanish (Spain)-Alvaro (Male)': 'es-ES-AlvaroNeural', | |
| 'Spanish (Spain)-Elvira (Female)': 'es-ES-ElviraNeural', | |
| 'Spanish (Equatorial Guinea)-Teresa (Female)': 'es-GQ-TeresaNeural', | |
| 'Spanish (Guatemala)-Andres (Male)': 'es-GT-AndresNeural', | |
| 'Spanish (Guatemala)-Marta (Female)': 'es-GT-MartaNeural', | |
| 'Spanish (Honduras)-Carlos (Male)': 'es-HN-CarlosNeural', | |
| 'Spanish (Honduras)-Karla (Female)': 'es-HN-KarlaNeural', | |
| 'Spanish (Nicaragua)-Federico (Male)': 'es-NI-FedericoNeural', | |
| 'Spanish (Nicaragua)-Yolanda (Female)': 'es-NI-YolandaNeural', | |
| 'Spanish (Panama)-Margarita (Female)': 'es-PA-MargaritaNeural', | |
| 'Spanish (Panama)-Roberto (Male)': 'es-PA-RobertoNeural', | |
| 'Spanish (Peru)-Alex (Male)': 'es-PE-AlexNeural', | |
| 'Spanish (Peru)-Camila (Female)': 'es-PE-CamilaNeural', | |
| 'Spanish (Puerto Rico)-Karina (Female)': 'es-PR-KarinaNeural', | |
| 'Spanish (Puerto Rico)-Victor (Male)': 'es-PR-VictorNeural', | |
| 'Spanish (Paraguay)-Mario (Male)': 'es-PY-MarioNeural', | |
| 'Spanish (Paraguay)-Tania (Female)': 'es-PY-TaniaNeural', | |
| 'Spanish (El Salvador)-Lorena (Female)': 'es-SV-LorenaNeural', | |
| 'Spanish (El Salvador)-Rodrigo (Male)': 'es-SV-RodrigoNeural', | |
| 'Spanish (United States)-Alonso (Male)': 'es-US-AlonsoNeural', | |
| 'Spanish (United States)-Paloma (Female)': 'es-US-PalomaNeural', | |
| 'Spanish (Uruguay)-Mateo (Male)': 'es-UY-MateoNeural', | |
| 'Spanish (Uruguay)-Valentina (Female)': 'es-UY-ValentinaNeural', | |
| 'Spanish (Venezuela)-Paola (Female)': 'es-VE-PaolaNeural', | |
| 'Spanish (Venezuela)-Sebastian (Male)': 'es-VE-SebastianNeural', | |
| 'Estonian (Estonia)-Anu (Female)': 'et-EE-AnuNeural', | |
| 'Estonian (Estonia)-Kert (Male)': 'et-EE-KertNeural', | |
| 'Persian (Iran)-Dilara (Female)': 'fa-IR-DilaraNeural', | |
| 'Persian (Iran)-Farid (Male)': 'fa-IR-FaridNeural', | |
| 'Finnish (Finland)-Harri (Male)': 'fi-FI-HarriNeural', | |
| 'Finnish (Finland)-Noora (Female)': 'fi-FI-NooraNeural', | |
| 'French (Belgium)-Charline (Female)': 'fr-BE-CharlineNeural', | |
| 'French (Belgium)-Gerard (Male)': 'fr-BE-GerardNeural', | |
| 'French (Canada)-Sylvie (Female)': 'fr-CA-SylvieNeural', | |
| 'French (Canada)-Antoine (Male)': 'fr-CA-AntoineNeural', | |
| 'French (Canada)-Jean (Male)': 'fr-CA-JeanNeural', | |
| 'French (Switzerland)-Ariane (Female)': 'fr-CH-ArianeNeural', | |
| 'French (Switzerland)-Fabrice (Male)': 'fr-CH-FabriceNeural', | |
| 'Irish (Ireland)-Colm (Male)': 'ga-IE-ColmNeural', | |
| 'Irish (Ireland)-Orla (Female)': 'ga-IE-OrlaNeural', | |
| 'Galician (Spain)-Roi (Male)': 'gl-ES-RoiNeural', | |
| 'Galician (Spain)-Sabela (Female)': 'gl-ES-SabelaNeural', | |
| 'Gujarati (India)-Dhwani (Female)': 'gu-IN-DhwaniNeural', | |
| 'Gujarati (India)-Niranjan (Male)': 'gu-IN-NiranjanNeural', | |
| 'Hindi (India)-Madhur (Male)': 'hi-IN-MadhurNeural', | |
| 'Hindi (India)-Swara (Female)': 'hi-IN-SwaraNeural', | |
| 'Croatian (Croatia)-Gabrijela (Female)': 'hr-HR-GabrijelaNeural', | |
| 'Croatian (Croatia)-Srecko (Male)': 'hr-HR-SreckoNeural', | |
| 'Hungarian (Hungary)-Noemi (Female)': 'hu-HU-NoemiNeural', | |
| 'Hungarian (Hungary)-Tamas (Male)': 'hu-HU-TamasNeural', | |
| 'Icelandic (Iceland)-Gudrun (Female)': 'is-IS-GudrunNeural', | |
| 'Icelandic (Iceland)-Gunnar (Male)': 'is-IS-GunnarNeural', | |
| 'Javanese (Indonesia)-Dimas (Male)': 'jv-ID-DimasNeural', | |
| 'Javanese (Indonesia)-Siti (Female)': 'jv-ID-SitiNeural', | |
| 'Georgian (Georgia)-Eka (Female)': 'ka-GE-EkaNeural', | |
| 'Georgian (Georgia)-Giorgi (Male)': 'ka-GE-GiorgiNeural', | |
| 'Kazakh (Kazakhstan)-Aigul (Female)': 'kk-KZ-AigulNeural', | |
| 'Kazakh (Kazakhstan)-Daulet (Male)': 'kk-KZ-DauletNeural', | |
| 'Khmer (Cambodia)-Piseth (Male)': 'km-KH-PisethNeural', | |
| 'Khmer (Cambodia)-Sreymom (Female)': 'km-KH-SreymomNeural', | |
| 'Kannada (India)-Gagan (Male)': 'kn-IN-GaganNeural', | |
| 'Kannada (India)-Sapna (Female)': 'kn-IN-SapnaNeural', | |
| 'Lao (Laos)-Chanthavong (Male)': 'lo-LA-ChanthavongNeural', | |
| 'Lao (Laos)-Keomany (Female)': 'lo-LA-KeomanyNeural', | |
| 'Lithuanian (Lithuania)-Leonas (Male)': 'lt-LT-LeonasNeural', | |
| 'Lithuanian (Lithuania)-Ona (Female)': 'lt-LT-OnaNeural', | |
| 'Latvian (Latvia)-Everita (Female)': 'lv-LV-EveritaNeural', | |
| 'Latvian (Latvia)-Nils (Male)': 'lv-LV-NilsNeural', | |
| 'Macedonian (North Macedonia)-Aleksandar (Male)': 'mk-MK-AleksandarNeural', | |
| 'Macedonian (North Macedonia)-Marija (Female)': 'mk-MK-MarijaNeural', | |
| 'Malayalam (India)-Midhun (Male)': 'ml-IN-MidhunNeural', | |
| 'Malayalam (India)-Sobhana (Female)': 'ml-IN-SobhanaNeural', | |
| 'Mongolian (Mongolia)-Bataa (Male)': 'mn-MN-BataaNeural', | |
| 'Mongolian (Mongolia)-Yesui (Female)': 'mn-MN-YesuiNeural', | |
| 'Marathi (India)-Aarohi (Female)': 'mr-IN-AarohiNeural', | |
| 'Marathi (India)-Manohar (Male)': 'mr-IN-ManoharNeural', | |
| 'Maltese (Malta)-Grace (Female)': 'mt-MT-GraceNeural', | |
| 'Maltese (Malta)-Joseph (Male)': 'mt-MT-JosephNeural', | |
| 'Burmese (Myanmar)-Nilar (Female)': 'my-MM-NilarNeural', | |
| 'Burmese (Myanmar)-Thiha (Male)': 'my-MM-ThihaNeural', | |
| 'Nepali (Nepal)-Hemkala (Female)': 'ne-NP-HemkalaNeural', | |
| 'Nepali (Nepal)-Sagar (Male)': 'ne-NP-SagarNeural', | |
| 'Dutch (Belgium)-Arnaud (Male)': 'nl-BE-ArnaudNeural', | |
| 'Dutch (Belgium)-Dena (Female)': 'nl-BE-DenaNeural', | |
| 'Polish (Poland)-Marek (Male)': 'pl-PL-MarekNeural', | |
| 'Polish (Poland)-Zofia (Female)': 'pl-PL-ZofiaNeural', | |
| 'Pashto (Afghanistan)-Gul Nawaz (Male)': 'ps-AF-Gul' | |
| } | |
| # Organize voices by language | |
| language_groups = {} | |
| for voice_name, voice_code in language_dict.items(): | |
| language = voice_name.split('-')[0].strip() | |
| if language not in language_groups: | |
| language_groups[language] = [] | |
| language_groups[language].append(voice_name) | |
| # Comprehensive CSS for dark theme and three-dot menu | |
| st.markdown(""" | |
| <style> | |
| /* Main container and background */ | |
| .main { | |
| background-color: #000000 !important; | |
| padding: 20px; | |
| border-radius: 8px; | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| /* Override Streamlit's default white backgrounds */ | |
| .stApp { | |
| background-color: #000000 !important; | |
| } | |
| .st-emotion-cache-1gv3atu { | |
| background-color: #000000 !important; | |
| } | |
| /* Style for text area */ | |
| .stTextArea > div > div > textarea { | |
| background-color: #1a1a1a; | |
| color: #ffffff; | |
| border: 1px solid #333333; | |
| border-radius: 8px; | |
| } | |
| /* Style for dropdowns */ | |
| .stSelectbox > div > div > select { | |
| background-color: #1a1a1a; | |
| color: #ffffff; | |
| border: 1px solid #333333; | |
| border-radius: 8px; | |
| } | |
| /* Style for buttons */ | |
| .stButton > button { | |
| background-color: #1f77b4; | |
| color: #ffffff; | |
| border-radius: 8px; | |
| border: none; | |
| padding: 10px 20px; | |
| margin-left: auto; | |
| margin-right: auto; | |
| display: block; | |
| } | |
| .stDownloadButton > button { | |
| background-color: #1f77b4; | |
| color: #ffffff; | |
| border-radius: 8px; | |
| border: none; | |
| padding: 10px 20px; | |
| margin-left: auto; | |
| margin-right: auto; | |
| display: block; | |
| } | |
| /* Center audio player */ | |
| .stAudio { | |
| display: flex; | |
| justify-content: center; | |
| } | |
| /* Style text and labels */ | |
| h1, p, label, .stMarkdown, .stSpinner, .stError, .stWarning { | |
| color: #ffffff !important; | |
| text-align: center; | |
| } | |
| /* Style the three-dot menu */ | |
| .st-emotion-cache-1j0y6p8 { | |
| background-color: #000000 !important; | |
| color: #ffffff !important; | |
| } | |
| .st-emotion-cache-1j0y6p8 svg { | |
| fill: #ffffff !important; | |
| } | |
| .st-emotion-cache-1j0y6p8:hover { | |
| background-color: #1a1a1a !important; | |
| } | |
| .st-emotion-cache-1h0l5z3 { /* Menu dropdown */ | |
| background-color: #000000 !important; | |
| color: #ffffff !important; | |
| border: 1px solid #333333; | |
| border-radius: 8px; | |
| } | |
| .st-emotion-cache-1h0l5z3 a { | |
| color: #ffffff !important; | |
| } | |
| /* Override sidebar and other elements */ | |
| .st-emotion-cache-1r4v8oq, .st-emotion-cache-10trblm { | |
| background-color: #000000 !important; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| async def text_to_speech_edge(text, voice): | |
| communicate = edge_tts.Communicate(text, voice) | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file: | |
| tmp_path = tmp_file.name | |
| await communicate.save(tmp_path) | |
| return tmp_path | |
| def main(): | |
| # Center the title and description with white text | |
| #st.markdown("<h1 style='text-align: center; color: #ffffff;'>Text-to-Speech Converter</h1>", unsafe_allow_html=True) | |
| #st.markdown("<p style='text-align: center; color: #ffffff;'>Enter text and select a language and voice to generate an MP3 audio file.</p>", unsafe_allow_html=True) | |
| # Input text area, centered | |
| with st.container(): | |
| input_text = st.text_area("Input Text", height=150, placeholder="Enter the text you want to convert to speech...", key="input_text") | |
| # Side-by-side dropdowns for language and voice | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| languages = sorted(language_groups.keys()) | |
| selected_language = st.selectbox("Select Language", languages, index=languages.index("English") if "English" in languages else 0) | |
| with col2: | |
| voices = language_groups.get(selected_language, []) | |
| selected_voice = st.selectbox("Select Voice", voices, index=0) | |
| # Center the button with container width | |
| with st.container(): | |
| if st.button("Generate Audio", use_container_width=True): | |
| if input_text and selected_voice: | |
| with st.spinner("Generating audio... Please wait!"): | |
| voice_code = language_dict.get(selected_voice, "en-US-JennyNeural") | |
| try: | |
| loop = asyncio.new_event_loop() | |
| asyncio.set_event_loop(loop) | |
| audio_path = loop.run_until_complete(text_to_speech_edge(input_text, voice_code)) | |
| # Display audio player, centered | |
| st.audio(audio_path, format="audio/mp3") | |
| # Provide download link, centered | |
| with open(audio_path, "rb") as file: | |
| st.download_button( | |
| label="Download MP3", | |
| data=file, | |
| file_name="output.mp3", | |
| mime="audio/mp3", | |
| use_container_width=True | |
| ) | |
| # Clean up temporary file | |
| os.unlink(audio_path) | |
| except Exception as e: | |
| st.error(f"Error generating audio: {str(e)}") | |
| else: | |
| st.warning("Please enter text and select a voice.") | |
| if __name__ == "__main__": | |
| main() |