Opera8 commited on
Commit
4d654ee
·
verified ·
1 Parent(s): aeed688

Upload 2 files

Browse files
Files changed (2) hide show
  1. app (2) (6).py +496 -0
  2. requirements (5) (5).txt +2 -0
app (2) (6).py ADDED
@@ -0,0 +1,496 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import edge_tts
3
+ import tempfile
4
+ import asyncio
5
+ import traceback
6
+ import threading
7
+ import os
8
+
9
+ # --- دیکشنری زبان‌ها و صداها با کلیدهای فارسی (نمونه) ---
10
+ # توجه: این فقط یک نمونه کوچک است. شما باید کل دیکشنری را به این شکل فارسی کنید.
11
+ # برای سادگی، من فقط چند مورد اول را تغییر می دهم و بقیه را انگلیسی نگه می دارم.
12
+ # شما باید برای هر کلید، نام زبان و جنسیت را به فارسی ترجمه کنید.
13
+
14
+ language_dict_persian_keys = {
15
+ 'انگلیسی - جنی (زن)': 'en-US-JennyNeural',
16
+ 'انگلیسی - گای (مرد)': 'en-US-GuyNeural',
17
+ 'انگلیسی - آنا (زن)': 'en-US-AnaNeural',
18
+ 'انگلیسی - آریا (زن)': 'en-US-AriaNeural',
19
+ 'انگلیسی - کریستوفر (مرد)': 'en-US-ChristopherNeural',
20
+ 'انگلیسی - اریک (مرد)': 'en-US-EricNeural',
21
+ 'انگلیسی - میشل (زن)': 'en-US-MichelleNeural',
22
+ 'انگلیسی - راجر (مرد)': 'en-US-RogerNeural',
23
+ 'اسپانیایی (مکزیک) - دالیا (زن)': 'es-MX-DaliaNeural',
24
+ 'اسپانیایی (مکزیک) - خورخه (مرد)': 'es-MX-JorgeNeural', # نام خورخه ممکن است دقیق نباشد
25
+ 'کره‌ای - سان-هی (زن)': 'ko-KR-SunHiNeural',
26
+ 'کره‌ای - این‌جون (مرد)': 'ko-KR-InJoonNeural',
27
+ 'تایلندی - پرموادی (زن)': 'th-TH-PremwadeeNeural',
28
+ 'تایلندی - نیوات (مرد)': 'th-TH-NiwatNeural',
29
+ 'ویتنامی - هوای‌می (زن)': 'vi-VN-HoaiMyNeural',
30
+ 'ویتنامی - نام‌مین (مرد)': 'vi-VN-NamMinhNeural',
31
+ 'ژاپنی - نانامی (زن)': 'ja-JP-NanamiNeural',
32
+ 'ژاپنی - کیتا (مرد)': 'ja-JP-KeitaNeural',
33
+ 'فرانسوی - دنیز (زن)': 'fr-FR-DeniseNeural',
34
+ 'فرانسوی - الوئیز (زن)': 'fr-FR-EloiseNeural',
35
+ 'فرانسوی - هانری (مرد)': 'fr-FR-HenriNeural',
36
+ 'پرتغالی (برزیل) - فرانسیسکا (زن)': 'pt-BR-FranciscaNeural',
37
+ 'پرتغالی (برزیل) - آنتونیو (مرد)': 'pt-BR-AntonioNeural',
38
+ 'اندونزیایی - آردی (مرد)': 'id-ID-ArdiNeural',
39
+ 'اندونزیایی - گادیس (زن)': 'id-ID-GadisNeural',
40
+ 'ایتالیایی - ایزابلا (زن)': 'it-IT-IsabellaNeural',
41
+ 'ایتالیایی - دیگو (مرد)': 'it-IT-DiegoNeural',
42
+ 'ایتالیایی - السا (زن)': 'it-IT-ElsaNeural',
43
+ 'هلندی - کولت (زن)': 'nl-NL-ColetteNeural',
44
+ 'هلندی - فنا (زن)': 'nl-NL-FennaNeural',
45
+ 'هلندی - مارتن (مرد)': 'nl-NL-MaartenNeural',
46
+ 'مالایی - عثمان (مرد)': 'ms-MY-OsmanNeural', # "Malese" به "مالایی"
47
+ 'مالایی - یاسمین (زن)': 'ms-MY-YasminNeural',
48
+ 'نروژی - پرنیل (زن)': 'nb-NO-PernilleNeural',
49
+ 'نروژی - فین (مرد)': 'nb-NO-FinnNeural',
50
+ 'سوئدی - سوفی (زن)': 'sv-SE-SofieNeural',
51
+ 'سوئدی - ماتیاس (مرد)': 'sv-SE-MattiasNeural',
52
+ 'عربی (عربستان) - حامد (مرد)': 'ar-SA-HamedNeural', # "عربی" به "عربی (عربستان)"
53
+ 'عربی (عربستان) - زاریا (زن)': 'ar-SA-ZariyahNeural',
54
+ 'یونانی - آتنا (زن)': 'el-GR-AthinaNeural',
55
+ 'یونانی - نستوراس (مرد)': 'el-GR-NestorasNeural',
56
+ 'آلمانی - کاتیا (زن)': 'de-DE-KatjaNeural',
57
+ 'آلمانی - آمالا (زن)': 'de-DE-AmalaNeural',
58
+ 'آلمانی - کنراد (مرد)': 'de-DE-ConradNeural',
59
+ 'آلمانی - کیلیان (مرد)': 'de-DE-KillianNeural',
60
+ 'آفریقایی - آدری (زن)': 'af-ZA-AdriNeural', # "Afrikaans" به "آفریقایی"
61
+ 'آفریقایی - ویلم (مرد)': 'af-ZA-WillemNeural',
62
+ 'اتیوپیایی - آمه‌ها (مرد)': 'am-ET-AmehaNeural', # "Ethiopian" به "اتیوپیایی"
63
+ 'اتیوپیایی - مکدس (زن)': 'am-ET-MekdesNeural',
64
+ 'عربی (امارات) - فاطمه (زن)': 'ar-AE-FatimaNeural',
65
+ 'عربی (امارات) - حمدان (مرد)': 'ar-AE-HamdanNeural',
66
+ 'عربی (بحرین) - علی (مرد)': 'ar-BH-AliNeural',
67
+ 'عربی (بحرین) - لیلا (زن)': 'ar-BH-LailaNeural',
68
+ 'عربی (الجزایر) - اسماعیل (مرد)': 'ar-DZ-IsmaelNeural',
69
+ 'عربی (مصر) - سلما (زن)': 'ar-EG-SalmaNeural',
70
+ 'عربی (مصر) - شاکر (مرد)': 'ar-EG-ShakirNeural',
71
+ 'عربی (عراق) - باسل (مرد)': 'ar-IQ-BasselNeural',
72
+ 'عربی (عراق) - رعنا (زن)': 'ar-IQ-RanaNeural', # "Rana" به "رعنا"
73
+ 'عربی (اردن) - سانا (زن)': 'ar-JO-SanaNeural',
74
+ 'عربی (اردن) - تایم (مرد)': 'ar-JO-TaimNeural', # "Taim"
75
+ 'عربی (کویت) - فهد (مرد)': 'ar-KW-FahedNeural',
76
+ 'عربی (کویت) - نورا (زن)': 'ar-KW-NouraNeural',
77
+ 'عربی (لبنان) - لیلا (زن)': 'ar-LB-LaylaNeural',
78
+ 'عربی (لبنان) - رامی (مرد)': 'ar-LB-RamiNeural',
79
+ 'عربی (لیبی) - ایمان (زن)': 'ar-LY-ImanNeural',
80
+ 'عربی (لیبی) - عمر (مرد)': 'ar-LY-OmarNeural',
81
+ 'عربی (مراکش) - جمال (مرد)': 'ar-MA-JamalNeural',
82
+ 'عربی (مراکش) - مونا (زن)': 'ar-MA-MounaNeural',
83
+ 'عربی (عمان) - عبدالله (مرد)': 'ar-OM-AbdullahNeural',
84
+ 'عربی (عمان) - عایشه (زن)': 'ar-OM-AyshaNeural',
85
+ 'عربی (قطر) - امل (زن)': 'ar-QA-AmalNeural', # "Amal"
86
+ 'عربی (قطر) - معاذ (مرد)': 'ar-QA-MoazNeural',
87
+ 'عربی (سوریه) - امانی (زن)': 'ar-SY-AmanyNeural',
88
+ 'عربی (سوریه) - لیث (مرد)': 'ar-SY-LaithNeural',
89
+ 'عربی (تونس) - هادی (مرد)': 'ar-TN-HediNeural', # "Hedi"
90
+ 'عربی (تونس) - ریم (زن)': 'ar-TN-ReemNeural',
91
+ 'عربی (یمن) - مریم (زن)': 'ar-YE-MaryamNeural',
92
+ 'عربی (یمن) - صالح (مرد)': 'ar-YE-SalehNeural',
93
+ 'آذربایجانی - بابک (مرد)': 'az-AZ-BabekNeural',
94
+ 'آذربایجانی - بانو (زن)': 'az-AZ-BanuNeural',
95
+ 'بلغاری - بوریسلاو (مرد)': 'bg-BG-BorislavNeural',
96
+ 'بلغاری - کالینا (زن)': 'bg-BG-KalinaNeural',
97
+ 'بنگالی (بنگلادش) - نابانیتا (زن)': 'bn-BD-NabanitaNeural',
98
+ 'بنگالی (بنگلادش) - پرادیپ (مرد)': 'bn-BD-PradeepNeural',
99
+ 'بنگالی (هند) - باشکار (مرد)': 'bn-IN-BashkarNeural',
100
+ 'بنگالی (هند) - تانیشا (زن)': 'bn-IN-TanishaaNeural', # "Tanishaa"
101
+ 'بوسنیایی - گوران (مرد)': 'bs-BA-GoranNeural', # "Bosnian" به "بوسنیایی"
102
+ 'بوسنیایی - وسنا (زن)': 'bs-BA-VesnaNeural',
103
+ 'کاتالان (اسپانیا) - جوآنا (زن)': 'ca-ES-JoanaNeural', # "Catalan"
104
+ 'کاتالان (اسپانیا) - انریک (مرد)': 'ca-ES-EnricNeural',
105
+ 'چکی - آنتونین (مرد)': 'cs-CZ-AntoninNeural', # "Czech" به "چکی"
106
+ 'چکی - ولاستا (زن)': 'cs-CZ-VlastaNeural',
107
+ 'ولزی (بریتانیا) - آلد (مرد)': 'cy-GB-AledNeural', # "Welsh"
108
+ 'ولزی (بریتانیا) - نیا (زن)': 'cy-GB-NiaNeural',
109
+ 'دانمارکی - کریستل (زن)': 'da-DK-ChristelNeural',
110
+ 'دانمارکی - یپه (مرد)': 'da-DK-JeppeNeural',
111
+ 'آلمانی (اتریش) - اینگرید (زن)': 'de-AT-IngridNeural',
112
+ 'آلمانی (اتریش) - یوناس (مرد)': 'de-AT-JonasNeural',
113
+ 'آلمانی (سوئیس) - یان (مرد)': 'de-CH-JanNeural',
114
+ 'آلمانی (سوئیس) - لنی (زن)': 'de-CH-LeniNeural',
115
+ 'انگلیسی (استرالیا) - ناتاشا (زن)': 'en-AU-NatashaNeural',
116
+ 'انگلیسی (استرالیا) - ویلیام (مرد)': 'en-AU-WilliamNeural',
117
+ 'انگلیسی (کانادا) - کلارا (زن)': 'en-CA-ClaraNeural',
118
+ 'انگلیسی (کانادا) - لیام (مرد)': 'en-CA-LiamNeural',
119
+ 'انگلیسی (بریتانیا) - لیبی (زن)': 'en-GB-LibbyNeural',
120
+ 'انگلیسی (بریتانیا) - میزی (زن)': 'en-GB-MaisieNeural',
121
+ 'انگلیسی (بریتانیا) - رایان (مرد)': 'en-GB-RyanNeural',
122
+ 'انگلیسی (بریتانیا) - سونیا (زن)': 'en-GB-SoniaNeural',
123
+ 'انگلیسی (بریتانیا) - توماس (مرد)': 'en-GB-ThomasNeural',
124
+ 'انگلیسی (هنگ کنگ) - سم (مرد)': 'en-HK-SamNeural',
125
+ 'انگلیسی (هنگ کنگ) - یان (زن)': 'en-HK-YanNeural',
126
+ 'انگلیسی (ایرلند) - کانر (مرد)': 'en-IE-ConnorNeural',
127
+ 'انگلیسی (ایرلند) - امیلی (زن)': 'en-IE-EmilyNeural',
128
+ 'انگلیسی (هند) - نیرجا (زن)': 'en-IN-NeerjaNeural',
129
+ 'انگلیسی (هند) - پرابهات (مرد)': 'en-IN-PrabhatNeural',
130
+ 'انگلیسی (کنیا) - آسیلیا (زن)': 'en-KE-AsiliaNeural',
131
+ 'انگلیسی (کنیا) - چیلمبا (مرد)': 'en-KE-ChilembaNeural',
132
+ 'انگلیسی (نیجریه) - آبئو (مرد)': 'en-NG-AbeoNeural',
133
+ 'انگلیسی (نیجریه) - ازینه (زن)': 'en-NG-EzinneNeural',
134
+ 'انگلیسی (نیوزیلند) - میچل (مرد)': 'en-NZ-MitchellNeural',
135
+ 'انگلیسی (نیوزیلند) - هیزل (زن)': 'en-NZ-HazelNeural',
136
+ 'انگلیسی (فیلیپین) - جیمز (مرد)': 'en-PH-JamesNeural',
137
+ 'انگلیسی (فیلیپین) - روزا (زن)': 'en-PH-RosaNeural',
138
+ 'انگلیسی (سنگاپور) - لونا (زن)': 'en-SG-LunaNeural',
139
+ 'انگلیسی (سنگاپور) - وین (مرد)': 'en-SG-WayneNeural',
140
+ 'انگلیسی (تانزانیا) - الیمو (مرد)': 'en-TZ-ElimuNeural',
141
+ 'انگلیسی (تانزانیا) - ایمانی (زن)': 'en-TZ-ImaniNeural',
142
+ 'انگلیسی (آفریقای جنوبی) - لیا (زن)': 'en-ZA-LeahNeural',
143
+ 'انگلیسی (آفریقای جنوبی) - لوک (مرد)': 'en-ZA-LukeNeural',
144
+ 'اسپانیایی (آرژانتین) - النا (زن)': 'es-AR-ElenaNeural',
145
+ 'اسپانیایی (آرژانتین) - توماس (مرد)': 'es-AR-TomasNeural',
146
+ 'اسپانیایی (بولیوی) - مارسلو (مرد)': 'es-BO-MarceloNeural',
147
+ 'اسپانیایی (بولیوی) - سوفیا (زن)': 'es-BO-SofiaNeural',
148
+ 'اسپانیایی (کلمبیا) - گونزالو (مرد)': 'es-CO-GonzaloNeural',
149
+ 'اسپانیایی (کلمبیا) - سالومه (زن)': 'es-CO-SalomeNeural',
150
+ 'اسپانیایی (کاستاریکا) - خوان (مرد)': 'es-CR-JuanNeural',
151
+ 'اسپانیایی (کاستاریکا) - ماریا (زن)': 'es-CR-MariaNeural',
152
+ 'اسپانیایی (کوبا) - بلکیس (زن)': 'es-CU-BelkysNeural',
153
+ 'اسپانیایی (کوبا) - مانوئل (مرد)': 'es-CU-ManuelNeural',
154
+ 'اسپانیایی (جمهوری دومینیکن) - امیلیو (مرد)': 'es-DO-EmilioNeural',
155
+ 'اسپانیایی (جمهوری دومینیکن) - رامونا (زن)': 'es-DO-RamonaNeural',
156
+ 'اسپانیایی (اکوادور) - آندریا (زن)': 'es-EC-AndreaNeural',
157
+ 'اسپانیایی (اکوادور) - لوئیس (مرد)': 'es-EC-LuisNeural',
158
+ 'اسپانیایی (اسپانیا) - آلوارو (مرد)': 'es-ES-AlvaroNeural',
159
+ 'اسپانیایی (اسپانیا) - الویرا (زن)': 'es-ES-ElviraNeural',
160
+ 'اسپانیایی (گینه استوایی) - ترزا (زن)': 'es-GQ-TeresaNeural',
161
+ 'اسپانیایی (گینه استوایی) - امیلیو (مرد)': 'es-GQ-EmilioNeural',
162
+ 'اسپانیایی (گواتمالا) - آندرس (مرد)': 'es-GT-AndresNeural',
163
+ 'اسپانیایی (گواتمالا) - مارتا (زن)': 'es-GT-MartaNeural',
164
+ 'اسپانیایی (هندوراس) - کارلوس (مرد)': 'es-HN-CarlosNeural',
165
+ 'اسپانیایی (هندوراس) - کارلا (زن)': 'es-HN-KarlaNeural',
166
+ 'اسپانیایی (نیکاراگوئه) - فدریکو (مرد)': 'es-NI-FedericoNeural',
167
+ 'اسپانیایی (نیکاراگوئه) - یولاندا (زن)': 'es-NI-YolandaNeural',
168
+ 'اسپانیایی (پاناما) - مارگاریتا (زن)': 'es-PA-MargaritaNeural',
169
+ 'اسپانیایی (پاناما) - روبرتو (مرد)': 'es-PA-RobertoNeural',
170
+ 'اسپانیایی (پرو) - الکس (مرد)': 'es-PE-AlexNeural',
171
+ 'اسپانیایی (پرو) - کامیلا (زن)': 'es-PE-CamilaNeural',
172
+ 'اسپانیایی (پورتوریکو) - کارینا (زن)': 'es-PR-KarinaNeural',
173
+ 'اسپانیایی (پورتوریکو) - ویکتور (مرد)': 'es-PR-VictorNeural',
174
+ 'اسپانیایی (پاراگوئه) - ماریو (مرد)': 'es-PY-MarioNeural',
175
+ 'اسپانیایی (پاراگوئه) - تانیا (زن)': 'es-PY-TaniaNeural',
176
+ 'اسپانیایی (السالوادور) - لورنا (زن)': 'es-SV-LorenaNeural',
177
+ 'اسپانیایی (السالوادور) - رودریگو (مرد)': 'es-SV-RodrigoNeural',
178
+ 'اسپانیایی (آمریکا) - آلونسو (مرد)': 'es-US-AlonsoNeural', # "United States" به "آمریکا"
179
+ 'اسپانیایی (آمریکا) - پالوما (زن)': 'es-US-PalomaNeural',
180
+ 'اسپانیایی (اروگوئه) - ماتئو (مرد)': 'es-UY-MateoNeural',
181
+ 'اسپانیایی (اروگوئه) - والنتینا (زن)': 'es-UY-ValentinaNeural',
182
+ 'اسپانیایی (ونزوئلا) - پائولا (زن)': 'es-VE-PaolaNeural',
183
+ 'اسپانیایی (ونزوئلا) - سباستین (مرد)': 'es-VE-SebastianNeural',
184
+ 'استونیایی - آنو (زن)': 'et-EE-AnuNeural', # "Estonian"
185
+ 'استونیایی - کرت (مرد)': 'et-EE-KertNeural',
186
+ 'فارسی (ایران) - دل‌آرا (زن)': 'fa-IR-DilaraNeural',
187
+ 'فارسی (ایران) - فرید (مرد)': 'fa-IR-FaridNeural',
188
+ 'فنلاندی - هاری (مرد)': 'fi-FI-HarriNeural',
189
+ 'فنلاندی - نوورا (زن)': 'fi-FI-NooraNeural',
190
+ 'فرانسوی (بلژیک) - شارلین (زن)': 'fr-BE-CharlineNeural',
191
+ 'فرانسوی (بلژیک) - جرارد (مرد)': 'fr-BE-GerardNeural',
192
+ 'فرانسوی (کانادا) - سیلوی (زن)': 'fr-CA-SylvieNeural',
193
+ 'فرانسوی (کانادا) - آنتوان (مرد)': 'fr-CA-AntoineNeural',
194
+ 'فرانسوی (کانادا) - ژان (مرد)': 'fr-CA-JeanNeural',
195
+ 'فرانسوی (سوئیس) - آریان (زن)': 'fr-CH-ArianeNeural',
196
+ 'فرانسوی (سوئیس) - فابریس (مرد)': 'fr-CH-FabriceNeural',
197
+ 'ایرلندی - کلم (مرد)': 'ga-IE-ColmNeural',
198
+ 'ایرلندی - اورلا (زن)': 'ga-IE-OrlaNeural',
199
+ 'گالیسی (اسپانیا) - روی (مرد)': 'gl-ES-RoiNeural', # "Galician"
200
+ 'گالیسی (اسپانیا) - سابلا (زن)': 'gl-ES-SabelaNeural',
201
+ 'گجراتی (هند) - دوانی (زن)': 'gu-IN-DhwaniNeural',
202
+ 'گجراتی (هند) - نیرانجان (مرد)': 'gu-IN-NiranjanNeural',
203
+ 'عبری (اسرائیل) - آوری (مرد)': 'he-IL-AvriNeural',
204
+ 'عبری (اسرائیل) - هیلا (زن)': 'he-IL-HilaNeural',
205
+ 'هندی (هند) - مادور (مرد)': 'hi-IN-MadhurNeural',
206
+ 'هندی (هند) - سوارا (زن)': 'hi-IN-SwaraNeural',
207
+ 'کروات - گابریلا (زن)': 'hr-HR-GabrijelaNeural', # "Croatian"
208
+ 'کروات - سرچکو (مرد)': 'hr-HR-SreckoNeural',
209
+ 'مجاری - نوئمی (زن)': 'hu-HU-NoemiNeural',
210
+ 'مجاری - تاماش (مرد)': 'hu-HU-TamasNeural',
211
+ 'ارمنی - آناهیت (زن)': 'hy-AM-AnahitNeural',
212
+ 'ارمنی - هایک (مرد)': 'hy-AM-HaykNeural',
213
+ 'ایسلندی - گودرون (زن)': 'is-IS-GudrunNeural',
214
+ 'ایسلندی - گونار (مرد)': 'is-IS-GunnarNeural',
215
+ 'جاوه‌ای (اندونزی) - دیماس (مرد)': 'jv-ID-DimasNeural', # "Javanese"
216
+ 'جاوه‌ای (اندونزی) - سیتی (زن)': 'jv-ID-SitiNeural',
217
+ 'گرجی - اکا (زن)': 'ka-GE-EkaNeural',
218
+ 'گرجی - گیورگی (مرد)': 'ka-GE-GiorgiNeural',
219
+ 'قزاقی - آیگول (زن)': 'kk-KZ-AigulNeural',
220
+ 'قزاقی - دولت (مرد)': 'kk-KZ-DauletNeural',
221
+ 'خمر (کامبوج) - پیست (مرد)': 'km-KH-PisethNeural', # "Khmer"
222
+ 'خمر (کامبوج) - سری‌مم (زن)': 'km-KH-SreymomNeural',
223
+ 'کانادایی (هند) - گاگان (مرد)': 'kn-IN-GaganNeural', # "Kannada"
224
+ 'کانادایی (هند) - ساپنا (زن)': 'kn-IN-SapnaNeural',
225
+ 'لائوسی - چانتاونگ (مرد)': 'lo-LA-ChanthavongNeural',
226
+ 'لائوسی - کئومانی (زن)': 'lo-LA-KeomanyNeural',
227
+ 'لیتوانیایی - لئوناس (مرد)': 'lt-LT-LeonasNeural',
228
+ 'لیتوانیایی - اونا (زن)': 'lt-LT-OnaNeural',
229
+ 'لتونیایی - اوریتا (زن)': 'lv-LV-EveritaNeural',
230
+ 'لتونیایی - نیلس (مرد)': 'lv-LV-NilsNeural',
231
+ 'مقدونیه‌ای - الکساندر (مرد)': 'mk-MK-AleksandarNeural',
232
+ 'مقدونیه‌ای - ماریا (زن)': 'mk-MK-MarijaNeural',
233
+ 'مالایالام (هند) - میدون (مرد)': 'ml-IN-MidhunNeural',
234
+ 'مالایالام (هند) - سوبهانا (زن)': 'ml-IN-SobhanaNeural',
235
+ 'مغولی - باتا (مرد)': 'mn-MN-BataaNeural',
236
+ 'مغولی - یسوی (زن)': 'mn-MN-YesuiNeural',
237
+ 'مراتی (هند) - آروهی (زن)': 'mr-IN-AarohiNeural',
238
+ 'مراتی (هند) - مانوهار (مرد)': 'mr-IN-ManoharNeural',
239
+ 'مالتی (مالت) - گریس (زن)': 'mt-MT-GraceNeural', # "Maltese"
240
+ 'مالتی (مالت) - جوزف (مرد)': 'mt-MT-JosephNeural',
241
+ 'برمه‌ای (میانمار) - نیلار (زن)': 'my-MM-NilarNeural',
242
+ 'برمه‌ای (میانمار) - تیها (مرد)': 'my-MM-ThihaNeural',
243
+ 'نپالی - همکالا (زن)': 'ne-NP-HemkalaNeural',
244
+ 'نپالی - ساگار (مرد)': 'ne-NP-SagarNeural',
245
+ 'هلندی (بلژیک) - آرنو (مرد)': 'nl-BE-ArnaudNeural',
246
+ 'هلندی (بلژیک) - دنا (زن)': 'nl-BE-DenaNeural',
247
+ 'لهستانی - مارک (مرد)': 'pl-PL-MarekNeural',
248
+ 'لهستانی - زوفیا (زن)': 'pl-PL-ZofiaNeural',
249
+ 'پشتو (افغانستان) - گل‌نواز (مرد)': 'ps-AF-GulNawazNeural',
250
+ 'پشتو (افغانستان) - لطیفه (زن)': 'ps-AF-LatifaNeural',
251
+ 'پرتغالی (پرتغال) - دوآرته (مرد)': 'pt-PT-DuarteNeural',
252
+ 'پرتغالی (پرتغال) - فرناندا (زن)': 'pt-PT-FernandaNeural',
253
+ 'رومانیایی - آلینا (زن)': 'ro-RO-AlinaNeural',
254
+ 'رومانیایی - امیل (مرد)': 'ro-RO-EmilNeural',
255
+ 'روسی - دیمیتری (مرد)': 'ru-RU-DmitryNeural',
256
+ 'روسی - سوتلانا (زن)': 'ru-RU-SvetlanaNeural',
257
+ 'سینهالی (سریلانکا) - دینوکا (مرد)': 'si-LK-DinukaNeural', # "Sinhala"
258
+ 'سینهالی (سریلانکا) - تیلینی (زن)': 'si-LK-ThiliniNeural',
259
+ 'اسلواک - لوکاش (مرد)': 'sk-SK-LukasNeural',
260
+ 'اسلواک - ویکتوریا (زن)': 'sk-SK-ViktoriaNeural',
261
+ 'اسلوونیایی - پترا (زن)': 'sl-SI-PetraNeural',
262
+ 'اسلوونیایی - روک (مرد)': 'sl-SI-RokNeural',
263
+ 'سومالیایی - موسه (مرد)': 'so-SO-MuuseNeural',
264
+ 'سومالیایی - اوباکس (زن)': 'so-SO-UbaxNeural',
265
+ 'آلبانیایی - آنیلا (زن)': 'sq-AL-AnilaNeural',
266
+ 'آلبانیایی - ایلیر (مرد)': 'sq-AL-IlirNeural',
267
+ 'صربی - نیکولا (مرد)': 'sr-RS-NikolaNeural',
268
+ 'صربی - سوفی (زن)': 'sr-RS-SophieNeural',
269
+ 'سوندانی (اندونزی) - جاجانگ (مرد)': 'su-ID-JajangNeural', # "Sundanese"
270
+ 'سوندانی (اندونزی) - توتی (زن)': 'su-ID-TutiNeural',
271
+ 'سواحیلی (کنیا) - رفیقی (مرد)': 'sw-KE-RafikiNeural',
272
+ 'سواحیلی (کنیا) - زوری (زن)': 'sw-KE-ZuriNeural',
273
+ 'سواحیلی (تانزانیا) - داوودی (مرد)': 'sw-TZ-DaudiNeural',
274
+ 'سواحیل�� (تانزانیا) - رхема (زن)': 'sw-TZ-RehemaNeural',
275
+ 'تامیلی (هند) - پالاوی (زن)': 'ta-IN-PallaviNeural',
276
+ 'تامیلی (هند) - والووار (مرد)': 'ta-IN-ValluvarNeural',
277
+ 'تامیلی (مالزی) - کانی (زن)': 'ta-MY-KaniNeural',
278
+ 'تامیلی (مالزی) - سوریا (مرد)': 'ta-MY-SuryaNeural',
279
+ 'تامیلی (سنگاپور) - آنبو (مرد)': 'ta-SG-AnbuNeural',
280
+ 'تامیلی (سنگاپور) - ونبا (زن)': 'ta-SG-VenbaNeural',
281
+ 'تامیلی (سریلانکا) - کومار (مرد)': 'ta-LK-KumarNeural',
282
+ 'تامیلی (سریلانکا) - سارانیا (زن)': 'ta-LK-SaranyaNeural',
283
+ 'تلوگو (هند) - موهان (مرد)': 'te-IN-MohanNeural',
284
+ 'تلوگو (هند) - شروتی (زن)': 'te-IN-ShrutiNeural',
285
+ 'ترکی - احمد (مرد)': 'tr-TR-AhmetNeural',
286
+ 'ترکی - امل (زن)': 'tr-TR-EmelNeural',
287
+ 'اوکراینی - اوستاپ (مرد)': 'uk-UA-OstapNeural',
288
+ 'اوکراینی - پولینا (زن)': 'uk-UA-PolinaNeural',
289
+ 'اردو (هند) - گل (زن)': 'ur-IN-GulNeural',
290
+ 'اردو (هند) - سلمان (مرد)': 'ur-IN-SalmanNeural',
291
+ 'اردو (پاکستان) - اسد (مرد)': 'ur-PK-AsadNeural',
292
+ 'اردو (پاکستان) - عظما (زن)': 'ur-PK-UzmaNeural',
293
+ 'ازبکی - مدینه (زن)': 'uz-UZ-MadinaNeural',
294
+ 'ازبکی - سردار (مرد)': 'uz-UZ-SardorNeural',
295
+ 'چینی (ماندارین ساده) - شیائوشیاو (زن)': 'zh-CN-XiaoxiaoNeural',
296
+ 'چینی (ماندارین ساده) - یون‌یانگ (مرد)': 'zh-CN-YunyangNeural',
297
+ 'چینی (کانتونی سنتی) - هیوگای (زن)': 'zh-HK-HiuGaaiNeural',
298
+ 'چینی (کانتونی سنتی) - وان‌لونگ (مرد)': 'zh-HK-WanLungNeural',
299
+ 'چینی (ماندارین تایوانی) - شیائوچن (زن)': 'zh-TW-HsiaoChenNeural',
300
+ 'چینی (ماندارین تایوانی) - یون‌جه (مرد)': 'zh-TW-YunJheNeural',
301
+ 'زولو (آفریقای جنوبی) - تاندو (زن)': 'zu-ZA-ThandoNeural',
302
+ 'زولو (آفریقای جنوبی) - تمبا (مرد)': 'zu-ZA-ThembaNeural',
303
+ }
304
+
305
+ # --- توابع تبدیل متن به گفتار و wrapper (همانند قبل) ---
306
+ async def text_to_speech_edge_async(text, language_code_persian, rate, volume, pitch): # language_code_persian نام پارامتر تغییر کرد
307
+ try:
308
+ if not text: return "خطا: لطفاً متنی را برای تبدیل وارد کنید.", None
309
+ # دریافت voice_id از دیکشنری با کلیدهای فارسی
310
+ voice_id = language_dict_persian_keys.get(language_code_persian)
311
+ if voice_id is None: return f"خطا: مدل صدای انتخاب شده ('{language_code_persian}') یافت نشد.", None
312
+ rate_str, volume_str, pitch_str = f"{int(rate):+g}%", f"{int(volume):+g}%", f"{int(pitch):+g}Hz"
313
+ communicate = edge_tts.Communicate(text, voice_id, rate=rate_str, volume=volume_str, pitch=pitch_str)
314
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file: tmp_path = tmp_file.name
315
+ await communicate.save(tmp_path)
316
+ return "تبدیل با موفقیت انجام شد.", tmp_path
317
+ except edge_tts.exceptions.NoAudioReceived:
318
+ error_msg = f"خطا: صدایی برای متن و صدای انتخاب شده دریافت نشد (صدا: {voice_id})."
319
+ return error_msg, None
320
+ except ValueError as ve:
321
+ error_msg = f"خطا در پارامترهای ورودی: {ve}" # حذف اشاره به edge-tts
322
+ return error_msg, None
323
+ except Exception as e:
324
+ return f"خطای غیرمنتظره در سرور: {type(e).__name__}", None
325
+
326
+ _event_loops_by_thread = {}
327
+ def _get_or_create_event_loop():
328
+ thread_id = threading.get_ident()
329
+ if thread_id not in _event_loops_by_thread or _event_loops_by_thread[thread_id].is_closed():
330
+ _event_loops_by_thread[thread_id] = asyncio.new_event_loop()
331
+ return _event_loops_by_thread[thread_id]
332
+
333
+ def text_to_speech_edge_sync_wrapper(text, language_code_persian, rate, volume, pitch):
334
+ try:
335
+ loop = _get_or_create_event_loop(); asyncio.set_event_loop(loop)
336
+ result = loop.run_until_complete(text_to_speech_edge_async(text, language_code_persian, rate, volume, pitch))
337
+ except RuntimeError as e:
338
+ if "no current event loop" in str(e).lower() or "cannot be called from a running event loop" in str(e).lower():
339
+ new_loop = asyncio.new_event_loop(); asyncio.set_event_loop(new_loop)
340
+ try: result = new_loop.run_until_complete(text_to_speech_edge_async(text, language_code_persian, rate, volume, pitch))
341
+ finally: new_loop.close()
342
+ else: return f"خطای اجرایی: {e}", None
343
+ except Exception as e: return f"خطای غیرمنتظره: {type(e).__name__}", None
344
+ return result
345
+
346
+ # --- تعریف تم و CSS ---
347
+ app_theme = gr.themes.Soft(
348
+ primary_hue=gr.themes.colors.blue,
349
+ secondary_hue=gr.themes.colors.sky,
350
+ neutral_hue=gr.themes.colors.slate,
351
+ font=[gr.themes.GoogleFont("Vazirmatn"), "Arial", "sans-serif"],
352
+ ).set(
353
+ body_background_fill="#f4f7f6",
354
+ )
355
+
356
+ custom_css = """
357
+ body { font-family: 'Vazirmatn', 'Arial', sans-serif; direction: rtl; }
358
+ .gradio-container {
359
+ max-width: 95% !important; margin: 1rem auto !important; padding: 1rem !important;
360
+ border-radius: 16px !important; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.07) !important;
361
+ background-color: #ffffff !important;
362
+ }
363
+ .app-header {
364
+ text-align: center; padding: 20px 10px; background: #34495e; color: white;
365
+ border-radius: 12px; margin-bottom: 1.5rem;
366
+ }
367
+ .app-header img.logo {
368
+ width: 50px; height: auto; margin-bottom: 5px;
369
+ animation: float_soft 4s ease-in-out infinite alternate;
370
+ }
371
+ .app-header h1 {
372
+ color: white !important; font-size: 1.6em !important; font-weight: 600 !important;
373
+ margin: 5px 0;
374
+ }
375
+ .app-header p { color: #bdc3c7 !important; font-size: 0.9em !important; margin-top: 5px; }
376
+ .main-content-row > .gr-column { margin-bottom: 1rem; }
377
+
378
+ .gr-button.lg.primary {
379
+ background: #3498db !important; color: white !important; font-weight: 500 !important;
380
+ border-radius: 8px !important; padding: 12px 15px !important; width: 100% !important;
381
+ font-size: 1em !important; transition: all 0.2s ease !important;
382
+ box-shadow: 0 3px 6px rgba(52, 152, 219, 0.25) !important; border: none !important;
383
+ }
384
+ .gr-button.lg.primary:hover {
385
+ background: #2980b9 !important; transform: translateY(-2px) !important;
386
+ box-shadow: 0 5px 10px rgba(52, 152, 219, 0.35) !important;
387
+ }
388
+ .gr-input, .gr-dropdown, .gr-textbox, .gr-slider {
389
+ border-radius: 8px !important; border: 1px solid #ced4da !important;
390
+ font-size: 0.95em !important;
391
+ }
392
+ .gr-input:focus, .gr-dropdown:focus, .gr-textbox:focus {
393
+ box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.15) !important;
394
+ border-color: #5dade2 !important;
395
+ }
396
+ .gr-panel {
397
+ border-radius: 10px !important; border: 1px solid #e9ecef !important;
398
+ background-color: #f8f9fa !important; padding: 0.75rem !important;
399
+ }
400
+ label > span {
401
+ font-weight: 500 !important; color: #495057 !important; font-size: 0.9em !important;
402
+ margin-bottom: 3px !important; display: block;
403
+ }
404
+ .gr-examples table { font-size: 0.85em; }
405
+ .gr-examples th, .gr-examples td { padding: 6px 8px !important; }
406
+
407
+ footer { display: none !important; visibility: hidden !important; }
408
+ .gradio-footer { display: none !important; visibility: hidden !important; }
409
+ .flagging-container { display: none !important; visibility: hidden !important; }
410
+ .flex.row.gap-2.absolute.bottom-2.right-2.gr-compact.gr-box.gr-text-gray-500 { display: none !important; visibility: hidden !important; }
411
+ div[data-testid="flag"] { display: none !important; }
412
+ button[title="Flag"], button[aria-label="Flag"] {display: none !important; }
413
+ .footer-utils { display: none !important; visibility: hidden !important; }
414
+
415
+ @keyframes float_soft {
416
+ 0% { transform: translatey(0px) scale(1); }
417
+ 50% { transform: translatey(-5px) scale(1.05); }
418
+ 100% { transform: translatey(0px) scale(1); }
419
+ }
420
+ @media (min-width: 768px) {
421
+ .gradio-container { max-width: 800px !important; padding: 1.5rem !important;}
422
+ .app-header h1 { font-size: 2em !important; }
423
+ .app-header p { font-size: 1em !important; }
424
+ .main-content-row { display: flex; flex-direction: row; gap: 1.5rem; }
425
+ .main-content-row > .gr-column { flex: 1; margin-bottom: 0; }
426
+ .main-content-row > .gr-column:nth-child(1) { flex-basis: 60%; }
427
+ .main-content-row > .gr-column:nth-child(2) { flex-basis: 40%; }
428
+ .gr-button.lg.primary { width: auto !important; }
429
+ }
430
+ """
431
+
432
+ # انتخاب صدای پیش فرض فارسی
433
+ default_voice_key_persian = 'فارسی (ایران) - فرید (مرد)'
434
+ if default_voice_key_persian not in language_dict_persian_keys:
435
+ # اگر به هر دلیلی صدای پیش فرض فارسی ما در لیست نبود، اولین مورد لیست را انتخاب کن
436
+ default_voice_key_persian = list(language_dict_persian_keys.keys())[0] if language_dict_persian_keys else None
437
+
438
+ # LOGO_URL دیگر استفاده نمی‌شود چون لوگو حذف شده است، اما برای حفظ سایر بخش‌های کد دست نخورده، آن را نگه می‌داریم
439
+ LOGO_URL = "https://www.gstatic.com/lamda/images/gemini/google_bard_logo_150_v2_dark_color_1x.png"
440
+
441
+ with gr.Blocks(theme=app_theme, css=custom_css) as demo:
442
+ with gr.Row():
443
+ gr.HTML(f"""
444
+ <div class="app-header">
445
+ <h1>مبدل هوشمند متن به گفتار</h1>
446
+ <p>با کیفیت صدای طبیعی و روان، متن خود را زنده کنید</p>
447
+ </div>
448
+ """)
449
+
450
+ with gr.Row(elem_classes="main-content-row"):
451
+ with gr.Column(scale=3):
452
+ input_text = gr.Textbox(
453
+ lines=5,
454
+ label="📝 متن خود را برای تبدیل وارد نمایید",
455
+ placeholder="اینجا بنوی��ید...",
456
+ value=""
457
+ )
458
+ language_dropdown = gr.Dropdown( # نام متغیر برای وضوح بیشتر
459
+ choices=list(language_dict_persian_keys.keys()),
460
+ value=default_voice_key_persian,
461
+ label="🗣️ زبان و گوینده را انتخاب کنید"
462
+ )
463
+ with gr.Accordion("⚙️ تنظیمات پیشرفته صدا (اختیاری)", open=False):
464
+ with gr.Row():
465
+ rate_slider = gr.Slider(minimum=-100, maximum=100, step=1, value=0, label="سرعت (%)", scale=1)
466
+ volume_slider = gr.Slider(minimum=-100, maximum=100, step=1, value=0, label="حجم (%)", scale=1)
467
+ pitch_slider = gr.Slider(minimum=-50, maximum=50, step=1, value=0, label="گام (Hz)", scale=2)
468
+
469
+ submit_button = gr.Button("🔊 تولید و پخش صدا", variant="primary")
470
+
471
+ with gr.Column(scale=2):
472
+ output_text_status = gr.Textbox(label="📊 وضعیت عملیات", interactive=False, lines=1, placeholder="نتیجه اینجا نمایش داده می‌شود...")
473
+ output_audio = gr.Audio(type="filepath", label="🎧 فایل صوتی خروجی", interactive=False)
474
+
475
+ gr.HTML("<hr style='margin-top: 1rem; margin-bottom: 1rem; border: 0; border-top: 1px solid #dee2e6;'>")
476
+
477
+ gr.Examples(
478
+ examples=[
479
+ ["سلام بر شما، روز خوبی داشته باشید.", 'فارسی (ایران) - دل‌آرا (زن)', 0, 0, 0],
480
+ ["This is a test of the speech synthesis system.", 'انگلیسی - جنی (زن)', +5, 0, 0],
481
+ ["تجربه کاربری در این سامانه بسیار روان است.", 'فارسی (ایران) - فرید (مرد)', -5, 0, 0],
482
+ ],
483
+ inputs=[input_text, language_dropdown, rate_slider, volume_slider, pitch_slider], # استفاده از نام متغیرهای جدید
484
+ outputs=[output_text_status, output_audio],
485
+ fn=text_to_speech_edge_sync_wrapper,
486
+ cache_examples=False,
487
+ label="💡 چند نمونه برای شروع"
488
+ )
489
+
490
+ submit_button.click(
491
+ fn=text_to_speech_edge_sync_wrapper,
492
+ inputs=[input_text, language_dropdown, rate_slider, volume_slider, pitch_slider], # استفاده از نام متغیرهای جدید
493
+ outputs=[output_text_status, output_audio],
494
+ )
495
+
496
+ demo.launch()
requirements (5) (5).txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio>=4.44.1
2
+ edge-tts