Hamed744 commited on
Commit
da89421
·
verified ·
1 Parent(s): bf65522

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -317
app.py CHANGED
@@ -6,304 +6,62 @@ import traceback
6
  import threading
7
  import os
8
 
9
- # --- دیکشنری زبان‌ها و صداها ---
10
- language_dict = {
11
- 'English-Jenny (Female)': 'en-US-JennyNeural',
12
- 'English-Guy (Male)': 'en-US-GuyNeural',
13
- 'English-Ana (Female)': 'en-US-AnaNeural',
14
- 'English-Aria (Female)': 'en-US-AriaNeural',
15
- 'English-Christopher (Male)': 'en-US-ChristopherNeural',
16
- 'English-Eric (Male)': 'en-US-EricNeural',
17
- 'English-Michelle (Female)': 'en-US-MichelleNeural',
18
- 'English-Roger (Male)': 'en-US-RogerNeural',
19
- 'Spanish (Mexican)-Dalia (Female)': 'es-MX-DaliaNeural',
20
- 'Spanish (Mexican)-Jorge- (Male)': 'es-MX-JorgeNeural',
21
- 'Korean-Sun-Hi- (Female)': 'ko-KR-SunHiNeural',
22
- 'Korean-InJoon- (Male)': 'ko-KR-InJoonNeural',
23
- 'Thai-Premwadee- (Female)': 'th-TH-PremwadeeNeural',
24
- 'Thai-Niwat- (Male)': 'th-TH-NiwatNeural',
25
- 'Vietnamese-HoaiMy- (Female)': 'vi-VN-HoaiMyNeural',
26
- 'Vietnamese-NamMinh- (Male)': 'vi-VN-NamMinhNeural',
27
- 'Japanese-Nanami- (Female)': 'ja-JP-NanamiNeural',
28
- 'Japanese-Keita- (Male)': 'ja-JP-KeitaNeural',
29
- 'French-Denise- (Female)': 'fr-FR-DeniseNeural',
30
- 'French-Eloise- (Female)': 'fr-FR-EloiseNeural',
31
- 'French-Henri- (Male)': 'fr-FR-HenriNeural',
32
- 'Brazilian-Francisca- (Female)': 'pt-BR-FranciscaNeural',
33
- 'Brazilian-Antonio- (Male)': 'pt-BR-AntonioNeural',
34
- 'Indonesian-Ardi- (Male)': 'id-ID-ArdiNeural',
35
- 'Indonesian-Gadis- (Female)': 'id-ID-GadisNeural',
36
- 'Italian-Isabella- (Female)': 'it-IT-IsabellaNeural',
37
- 'Italian-Diego- (Male)': 'it-IT-DiegoNeural',
38
- 'Italian-Elsa- (Female)': 'it-IT-ElsaNeural',
39
- 'Dutch-Colette- (Female)': 'nl-NL-ColetteNeural',
40
- 'Dutch-Fenna- (Female)': 'nl-NL-FennaNeural',
41
- 'Dutch-Maarten- (Male)': 'nl-NL-MaartenNeural',
42
- 'Malese-Osman- (Male)': 'ms-MY-OsmanNeural',
43
- 'Malese-Yasmin- (Female)': 'ms-MY-YasminNeural',
44
- 'Norwegian-Pernille- (Female)': 'nb-NO-PernilleNeural',
45
- 'Norwegian-Finn- (Male)': 'nb-NO-FinnNeural',
46
- 'Swedish-Sofie- (Female)': 'sv-SE-SofieNeural',
47
- 'Swedish-Mattias- (Male)': 'sv-SE-MattiasNeural',
48
- 'Arabic-Hamed- (Male)': 'ar-SA-HamedNeural',
49
- 'Arabic-Zariyah- (Female)': 'ar-SA-ZariyahNeural',
50
- 'Greek-Athina- (Female)': 'el-GR-AthinaNeural',
51
- 'Greek-Nestoras- (Male)': 'el-GR-NestorasNeural',
52
- 'German-Katja- (Female)': 'de-DE-KatjaNeural',
53
- 'German-Amala- (Female)': 'de-DE-AmalaNeural',
54
- 'German-Conrad- (Male)': 'de-DE-ConradNeural',
55
- 'German-Killian- (Male)': 'de-DE-KillianNeural',
56
- 'Afrikaans-Adri- (Female)': 'af-ZA-AdriNeural',
57
- 'Afrikaans-Willem- (Male)': 'af-ZA-WillemNeural',
58
- 'Ethiopian-Ameha- (Male)': 'am-ET-AmehaNeural',
59
- 'Ethiopian-Mekdes- (Female)': 'am-ET-MekdesNeural',
60
- 'Arabic (UAE)-Fatima- (Female)': 'ar-AE-FatimaNeural',
61
- 'Arabic (UAE)-Hamdan- (Male)': 'ar-AE-HamdanNeural',
62
- 'Arabic (Bahrain)-Ali- (Male)': 'ar-BH-AliNeural',
63
- 'Arabic (Bahrain)-Laila- (Female)': 'ar-BH-LailaNeural',
64
- 'Arabic (Algeria)-Ismael- (Male)': 'ar-DZ-IsmaelNeural',
65
- 'Arabic (Egypt)-Salma- (Female)': 'ar-EG-SalmaNeural',
66
- 'Arabic (Egypt)-Shakir- (Male)': 'ar-EG-ShakirNeural',
67
- 'Arabic (Iraq)-Bassel- (Male)': 'ar-IQ-BasselNeural',
68
- 'Arabic (Iraq)-Rana- (Female)': 'ar-IQ-RanaNeural',
69
- 'Arabic (Jordan)-Sana- (Female)': 'ar-JO-SanaNeural',
70
- 'Arabic (Jordan)-Taim- (Male)': 'ar-JO-TaimNeural',
71
- 'Arabic (Kuwait)-Fahed- (Male)': 'ar-KW-FahedNeural',
72
- 'Arabic (Kuwait)-Noura- (Female)': 'ar-KW-NouraNeural',
73
- 'Arabic (Lebanon)-Layla- (Female)': 'ar-LB-LaylaNeural',
74
- 'Arabic (Lebanon)-Rami- (Male)': 'ar-LB-RamiNeural',
75
- 'Arabic (Libya)-Iman- (Female)': 'ar-LY-ImanNeural',
76
- 'Arabic (Libya)-Omar- (Male)': 'ar-LY-OmarNeural',
77
- 'Arabic (Morocco)-Jamal- (Male)': 'ar-MA-JamalNeural',
78
- 'Arabic (Morocco)-Mouna- (Female)': 'ar-MA-MounaNeural',
79
- 'Arabic (Oman)-Abdullah- (Male)': 'ar-OM-AbdullahNeural',
80
- 'Arabic (Oman)-Aysha- (Female)': 'ar-OM-AyshaNeural',
81
- 'Arabic (Qatar)-Amal- (Female)': 'ar-QA-AmalNeural',
82
- 'Arabic (Qatar)-Moaz- (Male)': 'ar-QA-MoazNeural',
83
- 'Arabic (Syrian Arab Republic)-Amany- (Female)': 'ar-SY-AmanyNeural',
84
- 'Arabic (Syrian Arab Republic)-Laith- (Male)': 'ar-SY-LaithNeural',
85
- 'Arabic (Tunisia)-Hedi- (Male)': 'ar-TN-HediNeural',
86
- 'Arabic (Tunisia)-Reem- (Female)': 'ar-TN-ReemNeural',
87
- 'Arabic (Yemen)-Maryam- (Female)': 'ar-YE-MaryamNeural',
88
- 'Arabic (Yemen)-Saleh- (Male)': 'ar-YE-SalehNeural',
89
- 'Azerbaijani-Babek- (Male)': 'az-AZ-BabekNeural',
90
- 'Azerbaijani-Banu- (Female)': 'az-AZ-BanuNeural',
91
- 'Bulgarian-Borislav- (Male)': 'bg-BG-BorislavNeural',
92
- 'Bulgarian-Kalina- (Female)': 'bg-BG-KalinaNeural',
93
- 'Bengali (Bangladesh)-Nabanita- (Female)': 'bn-BD-NabanitaNeural',
94
- 'Bengali (Bangladesh)-Pradeep- (Male)': 'bn-BD-PradeepNeural',
95
- 'Bengali (India)-Bashkar- (Male)': 'bn-IN-BashkarNeural',
96
- 'Bengali (India)-Tanishaa- (Female)': 'bn-IN-TanishaaNeural',
97
- 'Bosnian (Bosnia and Herzegovina)-Goran- (Male)': 'bs-BA-GoranNeural',
98
- 'Bosnian (Bosnia and Herzegovina)-Vesna- (Female)': 'bs-BA-VesnaNeural',
99
- 'Catalan (Spain)-Joana- (Female)': 'ca-ES-JoanaNeural',
100
- 'Catalan (Spain)-Enric- (Male)': 'ca-ES-EnricNeural',
101
- 'Czech (Czech Republic)-Antonin- (Male)': 'cs-CZ-AntoninNeural',
102
- 'Czech (Czech Republic)-Vlasta- (Female)': 'cs-CZ-VlastaNeural',
103
- 'Welsh (UK)-Aled- (Male)': 'cy-GB-AledNeural',
104
- 'Welsh (UK)-Nia- (Female)': 'cy-GB-NiaNeural',
105
- 'Danish (Denmark)-Christel- (Female)': 'da-DK-ChristelNeural',
106
- 'Danish (Denmark)-Jeppe- (Male)': 'da-DK-JeppeNeural',
107
- 'German (Austria)-Ingrid- (Female)': 'de-AT-IngridNeural',
108
- 'German (Austria)-Jonas- (Male)': 'de-AT-JonasNeural',
109
- 'German (Switzerland)-Jan- (Male)': 'de-CH-JanNeural',
110
- 'German (Switzerland)-Leni- (Female)': 'de-CH-LeniNeural',
111
- 'English (Australia)-Natasha- (Female)': 'en-AU-NatashaNeural',
112
- 'English (Australia)-William- (Male)': 'en-AU-WilliamNeural',
113
- 'English (Canada)-Clara- (Female)': 'en-CA-ClaraNeural',
114
- 'English (Canada)-Liam- (Male)': 'en-CA-LiamNeural',
115
- 'English (UK)-Libby- (Female)': 'en-GB-LibbyNeural',
116
- 'English (UK)-Maisie- (Female)': 'en-GB-MaisieNeural',
117
- 'English (UK)-Ryan- (Male)': 'en-GB-RyanNeural',
118
- 'English (UK)-Sonia- (Female)': 'en-GB-SoniaNeural',
119
- 'English (UK)-Thomas- (Male)': 'en-GB-ThomasNeural',
120
- 'English (Hong Kong)-Sam- (Male)': 'en-HK-SamNeural',
121
- 'English (Hong Kong)-Yan- (Female)': 'en-HK-YanNeural',
122
- 'English (Ireland)-Connor- (Male)': 'en-IE-ConnorNeural',
123
- 'English (Ireland)-Emily- (Female)': 'en-IE-EmilyNeural',
124
- 'English (India)-Neerja- (Female)': 'en-IN-NeerjaNeural',
125
- 'English (India)-Prabhat- (Male)': 'en-IN-PrabhatNeural',
126
- 'English (Kenya)-Asilia- (Female)': 'en-KE-AsiliaNeural',
127
- 'English (Kenya)-Chilemba- (Male)': 'en-KE-ChilembaNeural',
128
- 'English (Nigeria)-Abeo- (Male)': 'en-NG-AbeoNeural',
129
- 'English (Nigeria)-Ezinne- (Female)': 'en-NG-EzinneNeural',
130
- 'English (New Zealand)-Mitchell- (Male)': 'en-NZ-MitchellNeural',
131
- 'English (New Zealand)-Hazel- (Female)': 'en-NZ-HazelNeural',
132
- 'English (Philippines)-James- (Male)': 'en-PH-JamesNeural',
133
- 'English (Philippines)-Rosa- (Female)': 'en-PH-RosaNeural',
134
- 'English (Singapore)-Luna- (Female)': 'en-SG-LunaNeural',
135
- 'English (Singapore)-Wayne- (Male)': 'en-SG-WayneNeural',
136
- 'English (Tanzania)-Elimu- (Male)': 'en-TZ-ElimuNeural',
137
- 'English (Tanzania)-Imani- (Female)': 'en-TZ-ImaniNeural',
138
- 'English (South Africa)-Leah- (Female)': 'en-ZA-LeahNeural',
139
- 'English (South Africa)-Luke- (Male)': 'en-ZA-LukeNeural',
140
- 'Spanish (Argentina)-Elena- (Female)': 'es-AR-ElenaNeural',
141
- 'Spanish (Argentina)-Tomas- (Male)': 'es-AR-TomasNeural',
142
- 'Spanish (Bolivia)-Marcelo- (Male)': 'es-BO-MarceloNeural',
143
- 'Spanish (Bolivia)-Sofia- (Female)': 'es-BO-SofiaNeural',
144
- 'Spanish (Colombia)-Gonzalo- (Male)': 'es-CO-GonzaloNeural',
145
- 'Spanish (Colombia)-Salome- (Female)': 'es-CO-SalomeNeural',
146
- 'Spanish (Costa Rica)-Juan- (Male)': 'es-CR-JuanNeural',
147
- 'Spanish (Costa Rica)-Maria- (Female)': 'es-CR-MariaNeural',
148
- 'Spanish (Cuba)-Belkys- (Female)': 'es-CU-BelkysNeural',
149
- 'Spanish (Cuba)-Manuel- (Male)': 'es-CU-ManuelNeural',
150
- 'Spanish (Dominican Republic)-Emilio- (Male)': 'es-DO-EmilioNeural',
151
- 'Spanish (Dominican Republic)-Ramona- (Female)': 'es-DO-RamonaNeural',
152
- 'Spanish (Ecuador)-Andrea- (Female)': 'es-EC-AndreaNeural',
153
- 'Spanish (Ecuador)-Luis- (Male)': 'es-EC-LuisNeural',
154
- 'Spanish (Spain)-Alvaro- (Male)': 'es-ES-AlvaroNeural',
155
- 'Spanish (Spain)-Elvira- (Female)': 'es-ES-ElviraNeural',
156
- 'Spanish (Equatorial Guinea)-Teresa- (Female)': 'es-GQ-TeresaNeural',
157
- 'Spanish (Equatorial Guinea)-Emilio- (Male)': 'es-GQ-EmilioNeural',
158
- 'Spanish (Guatemala)-Andres- (Male)': 'es-GT-AndresNeural',
159
- 'Spanish (Guatemala)-Marta- (Female)': 'es-GT-MartaNeural',
160
- 'Spanish (Honduras)-Carlos- (Male)': 'es-HN-CarlosNeural',
161
- 'Spanish (Honduras)-Karla- (Female)': 'es-HN-KarlaNeural',
162
- 'Spanish (Nicaragua)-Federico- (Male)': 'es-NI-FedericoNeural',
163
- 'Spanish (Nicaragua)-Yolanda- (Female)': 'es-NI-YolandaNeural',
164
- 'Spanish (Panama)-Margarita- (Female)': 'es-PA-MargaritaNeural',
165
- 'Spanish (Panama)-Roberto- (Male)': 'es-PA-RobertoNeural',
166
- 'Spanish (Peru)-Alex- (Male)': 'es-PE-AlexNeural',
167
- 'Spanish (Peru)-Camila- (Female)': 'es-PE-CamilaNeural',
168
- 'Spanish (Puerto Rico)-Karina- (Female)': 'es-PR-KarinaNeural',
169
- 'Spanish (Puerto Rico)-Victor- (Male)': 'es-PR-VictorNeural',
170
- 'Spanish (Paraguay)-Mario- (Male)': 'es-PY-MarioNeural',
171
- 'Spanish (Paraguay)-Tania- (Female)': 'es-PY-TaniaNeural',
172
- 'Spanish (El Salvador)-Lorena- (Female)': 'es-SV-LorenaNeural',
173
- 'Spanish (El Salvador)-Rodrigo- (Male)': 'es-SV-RodrigoNeural',
174
- 'Spanish (United States)-Alonso- (Male)': 'es-US-AlonsoNeural',
175
- 'Spanish (United States)-Paloma- (Female)': 'es-US-PalomaNeural',
176
- 'Spanish (Uruguay)-Mateo- (Male)': 'es-UY-MateoNeural',
177
- 'Spanish (Uruguay)-Valentina- (Female)': 'es-UY-ValentinaNeural',
178
- 'Spanish (Venezuela)-Paola- (Female)': 'es-VE-PaolaNeural',
179
- 'Spanish (Venezuela)-Sebastian- (Male)': 'es-VE-SebastianNeural',
180
- 'Estonian (Estonia)-Anu- (Female)': 'et-EE-AnuNeural',
181
- 'Estonian (Estonia)-Kert- (Male)': 'et-EE-KertNeural',
182
- 'Persian (Iran)-Dilara- (Female)': 'fa-IR-DilaraNeural',
183
- 'Persian (Iran)-Farid- (Male)': 'fa-IR-FaridNeural',
184
- 'Finnish (Finland)-Harri- (Male)': 'fi-FI-HarriNeural',
185
- 'Finnish (Finland)-Noora- (Female)': 'fi-FI-NooraNeural',
186
- 'French (Belgium)-Charline- (Female)': 'fr-BE-CharlineNeural',
187
- 'French (Belgium)-Gerard- (Male)': 'fr-BE-GerardNeural',
188
- 'French (Canada)-Sylvie- (Female)': 'fr-CA-SylvieNeural',
189
- 'French (Canada)-Antoine- (Male)': 'fr-CA-AntoineNeural',
190
- 'French (Canada)-Jean- (Male)': 'fr-CA-JeanNeural',
191
- 'French (Switzerland)-Ariane- (Female)': 'fr-CH-ArianeNeural',
192
- 'French (Switzerland)-Fabrice- (Male)': 'fr-CH-FabriceNeural',
193
- 'Irish (Ireland)-Colm- (Male)': 'ga-IE-ColmNeural',
194
- 'Irish (Ireland)-Orla- (Female)': 'ga-IE-OrlaNeural',
195
- 'Galician (Spain)-Roi- (Male)': 'gl-ES-RoiNeural',
196
- 'Galician (Spain)-Sabela- (Female)': 'gl-ES-SabelaNeural',
197
- 'Gujarati (India)-Dhwani- (Female)': 'gu-IN-DhwaniNeural',
198
- 'Gujarati (India)-Niranjan- (Male)': 'gu-IN-NiranjanNeural',
199
- 'Hebrew (Israel)-Avri- (Male)': 'he-IL-AvriNeural',
200
- 'Hebrew (Israel)-Hila- (Female)': 'he-IL-HilaNeural',
201
- 'Hindi (India)-Madhur- (Male)': 'hi-IN-MadhurNeural',
202
- 'Hindi (India)-Swara- (Female)': 'hi-IN-SwaraNeural',
203
- 'Croatian (Croatia)-Gabrijela- (Female)': 'hr-HR-GabrijelaNeural',
204
- 'Croatian (Croatia)-Srecko- (Male)': 'hr-HR-SreckoNeural',
205
- 'Hungarian (Hungary)-Noemi- (Female)': 'hu-HU-NoemiNeural',
206
- 'Hungarian (Hungary)-Tamas- (Male)': 'hu-HU-TamasNeural',
207
- 'Armenian (Armenia)-Anahit- (Female)': 'hy-AM-AnahitNeural',
208
- 'Armenian (Armenia)-Hayk- (Male)': 'hy-AM-HaykNeural',
209
- 'Icelandic (Iceland)-Gudrun- (Female)': 'is-IS-GudrunNeural',
210
- 'Icelandic (Iceland)-Gunnar- (Male)': 'is-IS-GunnarNeural',
211
- 'Javanese (Indonesia)-Dimas- (Male)': 'jv-ID-DimasNeural',
212
- 'Javanese (Indonesia)-Siti- (Female)': 'jv-ID-SitiNeural',
213
- 'Georgian (Georgia)-Eka- (Female)': 'ka-GE-EkaNeural',
214
- 'Georgian (Georgia)-Giorgi- (Male)': 'ka-GE-GiorgiNeural',
215
- 'Kazakh (Kazakhstan)-Aigul- (Female)': 'kk-KZ-AigulNeural',
216
- 'Kazakh (Kazakhstan)-Daulet- (Male)': 'kk-KZ-DauletNeural',
217
- 'Khmer (Cambodia)-Piseth- (Male)': 'km-KH-PisethNeural',
218
- 'Khmer (Cambodia)-Sreymom- (Female)': 'km-KH-SreymomNeural',
219
- 'Kannada (India)-Gagan- (Male)': 'kn-IN-GaganNeural',
220
- 'Kannada (India)-Sapna- (Female)': 'kn-IN-SapnaNeural',
221
- 'Lao (Laos)-Chanthavong- (Male)': 'lo-LA-ChanthavongNeural',
222
- 'Lao (Laos)-Keomany- (Female)': 'lo-LA-KeomanyNeural',
223
- 'Lithuanian (Lithuania)-Leonas- (Male)': 'lt-LT-LeonasNeural',
224
- 'Lithuanian (Lithuania)-Ona- (Female)': 'lt-LT-OnaNeural',
225
- 'Latvian (Latvia)-Everita- (Female)': 'lv-LV-EveritaNeural',
226
- 'Latvian (Latvia)-Nils- (Male)': 'lv-LV-NilsNeural',
227
- 'Macedonian (North Macedonia)-Aleksandar- (Male)': 'mk-MK-AleksandarNeural',
228
- 'Macedonian (North Macedonia)-Marija- (Female)': 'mk-MK-MarijaNeural',
229
- 'Malayalam (India)-Midhun- (Male)': 'ml-IN-MidhunNeural',
230
- 'Malayalam (India)-Sobhana- (Female)': 'ml-IN-SobhanaNeural',
231
- 'Mongolian (Mongolia)-Bataa- (Male)': 'mn-MN-BataaNeural',
232
- 'Mongolian (Mongolia)-Yesui- (Female)': 'mn-MN-YesuiNeural',
233
- 'Marathi (India)-Aarohi- (Female)': 'mr-IN-AarohiNeural',
234
- 'Marathi (India)-Manohar- (Male)': 'mr-IN-ManoharNeural',
235
- 'Maltese (Malta)-Grace- (Female)': 'mt-MT-GraceNeural',
236
- 'Maltese (Malta)-Joseph- (Male)': 'mt-MT-JosephNeural',
237
- 'Burmese (Myanmar)-Nilar- (Female)': 'my-MM-NilarNeural',
238
- 'Burmese (Myanmar)-Thiha- (Male)': 'my-MM-ThihaNeural',
239
- 'Nepali (Nepal)-Hemkala- (Female)': 'ne-NP-HemkalaNeural',
240
- 'Nepali (Nepal)-Sagar- (Male)': 'ne-NP-SagarNeural',
241
- 'Dutch (Belgium)-Arnaud- (Male)': 'nl-BE-ArnaudNeural',
242
- 'Dutch (Belgium)-Dena- (Female)': 'nl-BE-DenaNeural',
243
- 'Polish (Poland)-Marek- (Male)': 'pl-PL-MarekNeural',
244
- 'Polish (Poland)-Zofia- (Female)': 'pl-PL-ZofiaNeural',
245
- 'Pashto (Afghanistan)-Gul Nawaz- (Male)': 'ps-AF-GulNawazNeural',
246
- 'Pashto (Afghanistan)-Latifa- (Female)': 'ps-AF-LatifaNeural',
247
- 'Portuguese (Portugal)-Duarte- (Male)': 'pt-PT-DuarteNeural',
248
- 'Portuguese (Portugal)-Fernanda- (Female)': 'pt-PT-FernandaNeural',
249
- 'Romanian (Romania)-Alina- (Female)': 'ro-RO-AlinaNeural',
250
- 'Romanian (Romania)-Emil- (Male)': 'ro-RO-EmilNeural',
251
- 'Russian (Russia)-Dmitry- (Male)': 'ru-RU-DmitryNeural',
252
- 'Russian (Russia)-Svetlana- (Female)': 'ru-RU-SvetlanaNeural',
253
- 'Sinhala (Sri Lanka)-Dinuka- (Male)': 'si-LK-DinukaNeural',
254
- 'Sinhala (Sri Lanka)-Thilini- (Female)': 'si-LK-ThiliniNeural',
255
- 'Slovak (Slovakia)-Lukas- (Male)': 'sk-SK-LukasNeural',
256
- 'Slovak (Slovakia)-Viktoria- (Female)': 'sk-SK-ViktoriaNeural',
257
- 'Slovenian (Slovenia)-Petra- (Female)': 'sl-SI-PetraNeural',
258
- 'Slovenian (Slovenia)-Rok- (Male)': 'sl-SI-RokNeural',
259
- 'Somali (Somalia)-Muuse- (Male)': 'so-SO-MuuseNeural',
260
- 'Somali (Somalia)-Ubax- (Female)': 'so-SO-UbaxNeural',
261
- 'Albanian (Albania)-Anila- (Female)': 'sq-AL-AnilaNeural',
262
- 'Albanian (Albania)-Ilir- (Male)': 'sq-AL-IlirNeural',
263
- 'Serbian (Serbia)-Nikola- (Male)': 'sr-RS-NikolaNeural',
264
- 'Serbian (Serbia)-Sophie- (Female)': 'sr-RS-SophieNeural',
265
- 'Sundanese (Indonesia)-Jajang- (Male)': 'su-ID-JajangNeural',
266
- 'Sundanese (Indonesia)-Tuti- (Female)': 'su-ID-TutiNeural',
267
- 'Swahili (Kenya)-Rafiki- (Male)': 'sw-KE-RafikiNeural',
268
- 'Swahili (Kenya)-Zuri- (Female)': 'sw-KE-ZuriNeural',
269
- 'Swahili (Tanzania)-Daudi- (Male)': 'sw-TZ-DaudiNeural',
270
- 'Swahili (Tanzania)-Rehema- (Female)': 'sw-TZ-RehemaNeural',
271
- 'Tamil (India)-Pallavi- (Female)': 'ta-IN-PallaviNeural',
272
- 'Tamil (India)-Valluvar- (Male)': 'ta-IN-ValluvarNeural',
273
- 'Tamil (Malaysia)-Kani- (Female)': 'ta-MY-KaniNeural',
274
- 'Tamil (Malaysia)-Surya- (Male)': 'ta-MY-SuryaNeural',
275
- 'Tamil (Singapore)-Anbu- (Male)': 'ta-SG-AnbuNeural',
276
- 'Tamil (Singapore)-Venba- (Female)': 'ta-SG-VenbaNeural',
277
- 'Tamil (Sri Lanka)-Kumar- (Male)': 'ta-LK-KumarNeural',
278
- 'Tamil (Sri Lanka)-Saranya- (Female)': 'ta-LK-SaranyaNeural',
279
- 'Telugu (India)-Mohan- (Male)': 'te-IN-MohanNeural',
280
- 'Telugu (India)-Shruti- (Female)': 'te-IN-ShrutiNeural',
281
- 'Turkish (Turkey)-Ahmet- (Male)': 'tr-TR-AhmetNeural',
282
- 'Turkish (Turkey)-Emel- (Female)': 'tr-TR-EmelNeural',
283
- 'Ukrainian (Ukraine)-Ostap- (Male)': 'uk-UA-OstapNeural',
284
- 'Ukrainian (Ukraine)-Polina- (Female)': 'uk-UA-PolinaNeural',
285
- 'Urdu (India)-Gul- (Female)': 'ur-IN-GulNeural',
286
- 'Urdu (India)-Salman- (Male)': 'ur-IN-SalmanNeural',
287
- 'Urdu (Pakistan)-Asad- (Male)': 'ur-PK-AsadNeural',
288
- 'Urdu (Pakistan)-Uzma- (Female)': 'ur-PK-UzmaNeural',
289
- 'Uzbek (Uzbekistan)-Madina- (Female)': 'uz-UZ-MadinaNeural',
290
- 'Uzbek (Uzbekistan)-Sardor- (Male)': 'uz-UZ-SardorNeural',
291
- 'Chinese (Mandarin, Simplified)-Xiaoxiao- (Female)': 'zh-CN-XiaoxiaoNeural',
292
- 'Chinese (Mandarin, Simplified)-Yunyang- (Male)': 'zh-CN-YunyangNeural',
293
- 'Chinese (Cantonese, Traditional)-HiuGaai- (Female)': 'zh-HK-HiuGaaiNeural',
294
- 'Chinese (Cantonese, Traditional)-WanLung- (Male)': 'zh-HK-WanLungNeural',
295
- 'Chinese (Taiwanese Mandarin)-HsiaoChen- (Female)': 'zh-TW-HsiaoChenNeural',
296
- 'Chinese (Taiwanese Mandarin)-YunJhe- (Male)': 'zh-TW-YunJheNeural',
297
- 'Zulu (South Africa)-Thando- (Female)': 'zu-ZA-ThandoNeural',
298
- 'Zulu (South Africa)-Themba- (Male)': 'zu-ZA-ThembaNeural',
299
  }
300
 
301
- # --- توابع تبدیل متن به گفتار و wrapper (همانند قبل) ---
302
- async def text_to_speech_edge_async(text, language_code, rate, volume, pitch):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  try:
304
  if not text: return "خطا: لطفاً متنی را برای تبدیل وارد کنید.", None
305
- voice_id = language_dict.get(language_code)
306
- if voice_id is None: return f"خطا: مدل صدای انتخاب شده ('{language_code}') یافت نشد.", None
 
 
 
307
  rate_str, volume_str, pitch_str = f"{int(rate):+g}%", f"{int(volume):+g}%", f"{int(pitch):+g}Hz"
308
  communicate = edge_tts.Communicate(text, voice_id, rate=rate_str, volume=volume_str, pitch=pitch_str)
309
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file: tmp_path = tmp_file.name
@@ -325,20 +83,20 @@ def _get_or_create_event_loop():
325
  _event_loops_by_thread[thread_id] = asyncio.new_event_loop()
326
  return _event_loops_by_thread[thread_id]
327
 
328
- def text_to_speech_edge_sync_wrapper(text, language_code, rate, volume, pitch):
329
  try:
330
  loop = _get_or_create_event_loop(); asyncio.set_event_loop(loop)
331
- result = loop.run_until_complete(text_to_speech_edge_async(text, language_code, rate, volume, pitch))
332
  except RuntimeError as e:
333
  if "no current event loop" in str(e).lower() or "cannot be called from a running event loop" in str(e).lower():
334
  new_loop = asyncio.new_event_loop(); asyncio.set_event_loop(new_loop)
335
- try: result = new_loop.run_until_complete(text_to_speech_edge_async(text, language_code, rate, volume, pitch))
336
  finally: new_loop.close()
337
  else: return f"خطای اجرایی: {e}", None
338
  except Exception as e: return f"خطای غیرمنتظره: {type(e).__name__}", None
339
  return result
340
 
341
- # --- تعریف تم و CSS ---
342
  app_theme = gr.themes.Soft(
343
  primary_hue=gr.themes.colors.blue,
344
  secondary_hue=gr.themes.colors.sky,
@@ -380,10 +138,13 @@ body { font-family: 'Vazirmatn', 'Arial', sans-serif; direction: rtl; }
380
  background: #2980b9 !important; transform: translateY(-2px) !important;
381
  box-shadow: 0 5px 10px rgba(52, 152, 219, 0.35) !important;
382
  }
383
- .gr-input, .gr-dropdown, .gr-textbox, .gr-slider {
384
  border-radius: 8px !important; border: 1px solid #ced4da !important;
385
  font-size: 0.95em !important;
386
  }
 
 
 
387
  .gr-input:focus, .gr-dropdown:focus, .gr-textbox:focus {
388
  box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.15) !important;
389
  border-color: #5dade2 !important;
@@ -392,21 +153,20 @@ body { font-family: 'Vazirmatn', 'Arial', sans-serif; direction: rtl; }
392
  border-radius: 10px !important; border: 1px solid #e9ecef !important;
393
  background-color: #f8f9fa !important; padding: 0.75rem !important;
394
  }
395
- label > span {
396
  font-weight: 500 !important; color: #495057 !important; font-size: 0.9em !important;
397
  margin-bottom: 3px !important; display: block;
398
  }
399
  .gr-examples table { font-size: 0.85em; }
400
  .gr-examples th, .gr-examples td { padding: 6px 8px !important; }
401
 
402
- /* مخفی کردن پاورقی پیش فرض Gradio و دکمه Flag و لینک های Settings/API */
403
- footer { display: none !important; visibility: hidden !important; } /* برای اطمینان از مخفی شدن پاورقی اصلی */
404
  .gradio-footer { display: none !important; visibility: hidden !important; }
405
  .flagging-container { display: none !important; visibility: hidden !important; }
406
  .flex.row.gap-2.absolute.bottom-2.right-2.gr-compact.gr-box.gr-text-gray-500 { display: none !important; visibility: hidden !important; }
407
  div[data-testid="flag"] { display: none !important; }
408
  button[title="Flag"], button[aria-label="Flag"] {display: none !important; }
409
- .footer-utils { display: none !important; visibility: hidden !important; } /* یک کلاس دیگر که گاهی برای پاورقی utils استفاده می شود */
410
 
411
  @keyframes float_soft {
412
  0% { transform: translatey(0px) scale(1); }
@@ -422,12 +182,36 @@ button[title="Flag"], button[aria-label="Flag"] {display: none !important; }
422
  .main-content-row > .gr-column:nth-child(1) { flex-basis: 60%; }
423
  .main-content-row > .gr-column:nth-child(2) { flex-basis: 40%; }
424
  .gr-button.lg.primary { width: auto !important; }
 
 
 
425
  }
426
  """
427
 
428
- default_voice_key = 'Persian (Iran)-Farid- (Male)'
429
- if default_voice_key not in language_dict:
430
- default_voice_key = list(language_dict.keys())[0] if language_dict else None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
 
432
  LOGO_URL = "https://raw.githubusercontent.com/gradio-app/gradio/main/guides/assets/gradio-logo.svg"
433
 
@@ -441,6 +225,14 @@ with gr.Blocks(theme=app_theme, css=custom_css) as demo:
441
  </div>
442
  """)
443
 
 
 
 
 
 
 
 
 
444
  with gr.Row(elem_classes="main-content-row"):
445
  with gr.Column(scale=3):
446
  input_text = gr.Textbox(
@@ -449,9 +241,10 @@ with gr.Blocks(theme=app_theme, css=custom_css) as demo:
449
  placeholder="متن برای تبدیل...",
450
  value=""
451
  )
452
- language = gr.Dropdown(
453
- choices=list(language_dict.keys()),
454
- value=default_voice_key,
 
455
  label="🗣️ زبان و مدل صدا"
456
  )
457
  with gr.Accordion("⚙️ تنظیمات بیشتر (اختیاری)", open=False):
@@ -470,25 +263,28 @@ with gr.Blocks(theme=app_theme, css=custom_css) as demo:
470
 
471
  gr.Examples(
472
  examples=[
473
- ["سلام بر شما، این یک آزمایش تبدیل متن به گفتار با صدای فارسی است.", 'Persian (Iran)-Dilara- (Female)', 0, 0, 0],
474
- ["Gradio is a fantastic library for building ML demos quickly and easily.", 'English-Jenny (Female)', +10, -5, 0],
475
- ["株式会社グラディオへようこそ。", 'Japanese-Keita- (Male)', -5, 0, +5],
476
  ],
477
- inputs=[input_text, language, rate, volume, pitch],
478
  outputs=[output_text_status, output_audio],
479
  fn=text_to_speech_edge_sync_wrapper,
480
  cache_examples=False,
481
  label="💡 نمونه‌های آماده برای تست"
482
  )
483
 
484
- # بخش پاورقی کاملا حذف شده است تا هیچ نامی از Gradio یا چیز دیگری نباشد
485
- # اگر نیاز به پاورقی سفارشی دارید، اینجا می توانید gr.HTML یا gr.Markdown خود را قرار دهید.
 
 
 
 
486
 
487
  submit_button.click(
488
  fn=text_to_speech_edge_sync_wrapper,
489
- inputs=[input_text, language, rate, volume, pitch],
490
  outputs=[output_text_status, output_audio],
491
  )
492
 
493
- # اجرای برنامه بدون پارامترهای اضافی در launch
494
  demo.launch()
 
6
  import threading
7
  import os
8
 
9
+ # --- دیکشنری زبان‌ها و صداها با اضافه کردن نام فارسی (نمونه) ---
10
+ # شما باید این لیست را برای همه زبان ها کامل کنید
11
+ # ساختار جدید کلید: 'نام نمایشی فارسی (نام انگلیسی - جنسیت)'
12
+ # یا: 'نام نمایشی فارسی (نام انگلیسی)' اگر جنسیت مشخص نیست یا برای همه است
13
+ original_language_dict = {
14
+ 'English-Jenny (Female)': ('en-US-JennyNeural', 'زن'),
15
+ 'English-Guy (Male)': ('en-US-GuyNeural', 'مرد'),
16
+ 'English-Ana (Female)': ('en-US-AnaNeural', 'زن'),
17
+ 'English-Aria (Female)': ('en-US-AriaNeural', 'زن'),
18
+ 'English-Christopher (Male)': ('en-US-ChristopherNeural', 'مرد'),
19
+ 'English-Eric (Male)': ('en-US-EricNeural', 'مرد'),
20
+ 'English-Michelle (Female)': ('en-US-MichelleNeural', 'زن'),
21
+ 'English-Roger (Male)': ('en-US-RogerNeural', 'مرد'),
22
+ 'Spanish (Mexican)-Dalia (Female)': ('es-MX-DaliaNeural', 'زن'),
23
+ 'Spanish (Mexican)-Jorge- (Male)': ('es-MX-JorgeNeural', 'مرد'),
24
+ 'Korean-Sun-Hi- (Female)': ('ko-KR-SunHiNeural', 'زن'),
25
+ 'Korean-InJoon- (Male)': ('ko-KR-InJoonNeural', 'مرد'),
26
+ 'Persian (Iran)-Dilara- (Female)': ('fa-IR-DilaraNeural', 'زن'), # فارسی اضافه شده
27
+ 'Persian (Iran)-Farid- (Male)': ('fa-IR-FaridNeural', 'مرد'), # فارسی اضافه شده
28
+ # ... بقیه زبان‌ها را به همین ترتیب با (voice_id, gender_tag) تکمیل کنید ...
29
+ # مثال برای زبانی که فقط یک مدل دارد یا جنسیت نامشخص است
30
+ # 'Some Language-Model': ('xx-XX-ModelNeural', 'همه'),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
+ # ساخت دیکشنری جدید برای نمایش و استفاده در برنامه
34
+ # کلیدها نام های نمایشی جدید خواهند بود
35
+ language_display_dict = {}
36
+ for display_key_english, (voice_id, gender_tag) in original_language_dict.items():
37
+ # استخراج زبان و نام از کلید انگلیسی
38
+ lang_name_part = display_key_english.split('-')[0]
39
+ model_name_part = display_key_english.split('-', 1)[1] if '-' in display_key_english else display_key_english
40
+
41
+ persian_lang_name = lang_name_part # به طور پیش فرض، اگر ترجمه نداشتیم
42
+ if "English" in lang_name_part:
43
+ persian_lang_name = "انگلیسی"
44
+ elif "Spanish (Mexican)" in lang_name_part:
45
+ persian_lang_name = "اسپانیایی (مکزیک)"
46
+ elif "Korean" in lang_name_part:
47
+ persian_lang_name = "کره‌ای"
48
+ elif "Persian (Iran)" in lang_name_part:
49
+ persian_lang_name = "فارسی (ایران)"
50
+ # ... اضافه کردن ترجمه برای سایر زبان ها ...
51
+
52
+ new_display_key = f"{persian_lang_name} - {model_name_part}"
53
+ language_display_dict[new_display_key] = {'id': voice_id, 'gender': gender_tag.lower()}
54
+
55
+
56
+ # --- توابع تبدیل متن به گفتار و wrapper (همانند قبل، اما از language_display_dict استفاده می کند) ---
57
+ async def text_to_speech_edge_async(text, language_display_key, rate, volume, pitch): # ورودی به language_display_key تغییر کرد
58
  try:
59
  if not text: return "خطا: لطفاً متنی را برای تبدیل وارد کنید.", None
60
+
61
+ voice_info = language_display_dict.get(language_display_key)
62
+ if not voice_info: return f"خطا: مدل صدای انتخاب شده ('{language_display_key}') یافت نشد.", None
63
+ voice_id = voice_info['id']
64
+
65
  rate_str, volume_str, pitch_str = f"{int(rate):+g}%", f"{int(volume):+g}%", f"{int(pitch):+g}Hz"
66
  communicate = edge_tts.Communicate(text, voice_id, rate=rate_str, volume=volume_str, pitch=pitch_str)
67
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file: tmp_path = tmp_file.name
 
83
  _event_loops_by_thread[thread_id] = asyncio.new_event_loop()
84
  return _event_loops_by_thread[thread_id]
85
 
86
+ def text_to_speech_edge_sync_wrapper(text, language_display_key, rate, volume, pitch):
87
  try:
88
  loop = _get_or_create_event_loop(); asyncio.set_event_loop(loop)
89
+ result = loop.run_until_complete(text_to_speech_edge_async(text, language_display_key, rate, volume, pitch))
90
  except RuntimeError as e:
91
  if "no current event loop" in str(e).lower() or "cannot be called from a running event loop" in str(e).lower():
92
  new_loop = asyncio.new_event_loop(); asyncio.set_event_loop(new_loop)
93
+ try: result = new_loop.run_until_complete(text_to_speech_edge_async(text, language_display_key, rate, volume, pitch))
94
  finally: new_loop.close()
95
  else: return f"خطای اجرایی: {e}", None
96
  except Exception as e: return f"خطای غیرمنتظره: {type(e).__name__}", None
97
  return result
98
 
99
+ # --- تعریف تم و CSS (همانند قبل، با تغییرات جزئی در صورت نیاز) ---
100
  app_theme = gr.themes.Soft(
101
  primary_hue=gr.themes.colors.blue,
102
  secondary_hue=gr.themes.colors.sky,
 
138
  background: #2980b9 !important; transform: translateY(-2px) !important;
139
  box-shadow: 0 5px 10px rgba(52, 152, 219, 0.35) !important;
140
  }
141
+ .gr-input, .gr-dropdown, .gr-textbox, .gr-slider, .gr-radio label span { /* استایل برای رادیو هم اضافه شد */
142
  border-radius: 8px !important; border: 1px solid #ced4da !important;
143
  font-size: 0.95em !important;
144
  }
145
+ .gr-radio label input { margin-left: 5px; margin-right: 2px; } /* تنظیم فاصله دکمه های رادیو */
146
+ .gr-radio { padding: 5px; border:none !important; } /* حذف حاشیه اضافی از رادیو */
147
+
148
  .gr-input:focus, .gr-dropdown:focus, .gr-textbox:focus {
149
  box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.15) !important;
150
  border-color: #5dade2 !important;
 
153
  border-radius: 10px !important; border: 1px solid #e9ecef !important;
154
  background-color: #f8f9fa !important; padding: 0.75rem !important;
155
  }
156
+ label > span { /* شامل برچسب های رادیو هم می شود */
157
  font-weight: 500 !important; color: #495057 !important; font-size: 0.9em !important;
158
  margin-bottom: 3px !important; display: block;
159
  }
160
  .gr-examples table { font-size: 0.85em; }
161
  .gr-examples th, .gr-examples td { padding: 6px 8px !important; }
162
 
163
+ footer { display: none !important; visibility: hidden !important; }
 
164
  .gradio-footer { display: none !important; visibility: hidden !important; }
165
  .flagging-container { display: none !important; visibility: hidden !important; }
166
  .flex.row.gap-2.absolute.bottom-2.right-2.gr-compact.gr-box.gr-text-gray-500 { display: none !important; visibility: hidden !important; }
167
  div[data-testid="flag"] { display: none !important; }
168
  button[title="Flag"], button[aria-label="Flag"] {display: none !important; }
169
+ .footer-utils { display: none !important; visibility: hidden !important; }
170
 
171
  @keyframes float_soft {
172
  0% { transform: translatey(0px) scale(1); }
 
182
  .main-content-row > .gr-column:nth-child(1) { flex-basis: 60%; }
183
  .main-content-row > .gr-column:nth-child(2) { flex-basis: 40%; }
184
  .gr-button.lg.primary { width: auto !important; }
185
+ .gr-radio { display: flex; justify-content: center; gap: 15px; margin-bottom: 10px;} /* چیدمان بهتر رادیو در دسکتاپ */
186
+ .gr-radio label { margin-bottom: 0 !important; } /* جلوگیری از پرش برچسب رادیو */
187
+
188
  }
189
  """
190
 
191
+ # --- تابع برای آپدیت لیست زبان ها بر اساس جنسیت ---
192
+ def update_language_dropdown(gender_filter):
193
+ filtered_choices = []
194
+ first_choice = None
195
+ if gender_filter == "همه":
196
+ filtered_choices = list(language_display_dict.keys())
197
+ else: # "مرد" یا "زن"
198
+ for display_key, voice_info in language_display_dict.items():
199
+ if voice_info['gender'] == gender_filter:
200
+ filtered_choices.append(display_key)
201
+
202
+ if filtered_choices:
203
+ first_choice = filtered_choices[0]
204
+ # برگرداندن آپدیت برای Dropdown
205
+ return gr.Dropdown(choices=filtered_choices, value=first_choice, label="🗣️ زبان و مدل صدا (فیلتر شده)")
206
+
207
+
208
+ default_voice_key_display = "فارسی (ایران) - Farid- (Male)" # نام نمایشی جدید برای صدای پیش فرض
209
+ if default_voice_key_display not in language_display_dict:
210
+ # اگر صدای پیش فرض فارسی در لیست نبود (مثلا به خاطر فیلتر اولیه)، اولین مورد موجود را انتخاب کن
211
+ if list(language_display_dict.keys()):
212
+ default_voice_key_display = list(language_display_dict.keys())[0]
213
+ else:
214
+ default_voice_key_display = None # اگر لیست کلا خالی است
215
 
216
  LOGO_URL = "https://raw.githubusercontent.com/gradio-app/gradio/main/guides/assets/gradio-logo.svg"
217
 
 
225
  </div>
226
  """)
227
 
228
+ # --- دکمه های رادیویی برای انتخاب جنسیت ---
229
+ gender_radio = gr.Radio(
230
+ choices=["همه", "مرد", "زن"],
231
+ value="همه",
232
+ label="انتخاب جنسیت صدا",
233
+ elem_classes="gr-radio" # برای استایل دهی بهتر
234
+ )
235
+
236
  with gr.Row(elem_classes="main-content-row"):
237
  with gr.Column(scale=3):
238
  input_text = gr.Textbox(
 
241
  placeholder="متن برای تبدیل...",
242
  value=""
243
  )
244
+ # --- Dropdown زبان با قابلیت آپدیت ---
245
+ language_dropdown = gr.Dropdown(
246
+ choices=list(language_display_dict.keys()), # لیست اولیه
247
+ value=default_voice_key_display,
248
  label="🗣️ زبان و مدل صدا"
249
  )
250
  with gr.Accordion("⚙️ تنظیمات بیشتر (اختیاری)", open=False):
 
263
 
264
  gr.Examples(
265
  examples=[
266
+ ["سلام بر شما، این یک آزمایش تبدیل متن به گفتار با صدای فارسی است.", "فارسی (ایران) - Dilara- (Female)", 0, 0, 0],
267
+ ["Gradio is a fantastic library for building ML demos quickly and easily.", "انگلیسی - Jenny (Female)", +10, -5, 0],
268
+ ["株式会社グラディオへようこそ。", "ژاپنی - Keita- (Male)", -5, 0, +5],
269
  ],
270
+ inputs=[input_text, language_dropdown, rate, volume, pitch], # ورودی language_dropdown است
271
  outputs=[output_text_status, output_audio],
272
  fn=text_to_speech_edge_sync_wrapper,
273
  cache_examples=False,
274
  label="💡 نمونه‌های آماده برای تست"
275
  )
276
 
277
+ # --- اتصال دکمه رادیو به تابع آپدیت Dropdown ---
278
+ gender_radio.change(
279
+ fn=update_language_dropdown,
280
+ inputs=gender_radio,
281
+ outputs=language_dropdown
282
+ )
283
 
284
  submit_button.click(
285
  fn=text_to_speech_edge_sync_wrapper,
286
+ inputs=[input_text, language_dropdown, rate, volume, pitch], # ورودی language_dropdown است
287
  outputs=[output_text_status, output_audio],
288
  )
289
 
 
290
  demo.launch()