Hamed744 commited on
Commit
c462bd9
·
verified ·
1 Parent(s): 317630c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -70
app.py CHANGED
@@ -6,11 +6,12 @@ import traceback
6
  import threading
7
  import os
8
 
9
- # --- دیکشنری زبان‌ها و صداها با نام‌های فارسی برای نمایش ---
10
- # توجه: این یک فرآیند دستی است. من تعدادی را به عنوان نمونه فارسی کرده ام.
11
- # شما باید این لیست را با دقت بررسی و تکمیل کنید.
12
- # مقادیر (Value) باید انگلیسی و دقیقاً مطابق با شناسه صدای edge-tts باشند.
13
- language_dict = {
 
14
  'انگلیسی - جنی (زن)': 'en-US-JennyNeural',
15
  'انگلیسی - گای (مرد)': 'en-US-GuyNeural',
16
  'انگلیسی - آنا (زن)': 'en-US-AnaNeural',
@@ -20,12 +21,12 @@ language_dict = {
20
  'انگلیسی - میشل (زن)': 'en-US-MichelleNeural',
21
  'انگلیسی - راجر (مرد)': 'en-US-RogerNeural',
22
  'اسپانیایی (مکزیک) - دالیا (زن)': 'es-MX-DaliaNeural',
23
- 'اسپانیایی (مکزیک) - خورخه (مرد)': 'es-MX-JorgeNeural',
24
  'کره‌ای - سان-هی (زن)': 'ko-KR-SunHiNeural',
25
- 'کره‌ای - این-جون (مرد)': 'ko-KR-InJoonNeural',
26
  'تایلندی - پرموادی (زن)': 'th-TH-PremwadeeNeural',
27
  'تایلندی - نیوات (مرد)': 'th-TH-NiwatNeural',
28
- 'ویتنامی - هوآی‌می (زن)': 'vi-VN-HoaiMyNeural',
29
  'ویتنامی - نام‌مین (مرد)': 'vi-VN-NamMinhNeural',
30
  'ژاپنی - نانامی (زن)': 'ja-JP-NanamiNeural',
31
  'ژاپنی - کیتا (مرد)': 'ja-JP-KeitaNeural',
@@ -42,24 +43,24 @@ language_dict = {
42
  'هلندی - کولت (زن)': 'nl-NL-ColetteNeural',
43
  'هلندی - فنا (زن)': 'nl-NL-FennaNeural',
44
  'هلندی - مارتن (مرد)': 'nl-NL-MaartenNeural',
45
- 'مالایی - عثمان (مرد)': 'ms-MY-OsmanNeural',
46
  'مالایی - یاسمین (زن)': 'ms-MY-YasminNeural',
47
  'نروژی - پرنیل (زن)': 'nb-NO-PernilleNeural',
48
  'نروژی - فین (مرد)': 'nb-NO-FinnNeural',
49
  'سوئدی - سوفی (زن)': 'sv-SE-SofieNeural',
50
  'سوئدی - ماتیاس (مرد)': 'sv-SE-MattiasNeural',
51
- 'عربی (عربستان) - حامد (مرد)': 'ar-SA-HamedNeural',
52
- 'عربی (عربستان) - زریه (زن)': 'ar-SA-ZariyahNeural',
53
  'یونانی - آتنا (زن)': 'el-GR-AthinaNeural',
54
  'یونانی - نستوراس (مرد)': 'el-GR-NestorasNeural',
55
  'آلمانی - کاتیا (زن)': 'de-DE-KatjaNeural',
56
  'آلمانی - آمالا (زن)': 'de-DE-AmalaNeural',
57
  'آلمانی - کنراد (مرد)': 'de-DE-ConradNeural',
58
  'آلمانی - کیلیان (مرد)': 'de-DE-KillianNeural',
59
- 'آفریکانس - آدری (زن)': 'af-ZA-AdriNeural',
60
- 'آفریکانس - ویلم (مرد)': 'af-ZA-WillemNeural',
61
- 'امهری (اتیوپی) - آمه ها (مرد)': 'am-ET-AmehaNeural',
62
- 'امهری (اتیوپی) - مکدس (زن)': 'am-ET-MekdesNeural',
63
  'عربی (امارات) - فاطمه (زن)': 'ar-AE-FatimaNeural',
64
  'عربی (امارات) - حمدان (مرد)': 'ar-AE-HamdanNeural',
65
  'عربی (بحرین) - علی (مرد)': 'ar-BH-AliNeural',
@@ -68,9 +69,9 @@ language_dict = {
68
  'عربی (مصر) - سلما (زن)': 'ar-EG-SalmaNeural',
69
  'عربی (مصر) - شاکر (مرد)': 'ar-EG-ShakirNeural',
70
  'عربی (عراق) - باسل (مرد)': 'ar-IQ-BasselNeural',
71
- 'عربی (عراق) - رعنا (زن)': 'ar-IQ-RanaNeural',
72
- 'عربی (اردن) - سنا (زن)': 'ar-JO-SanaNeural',
73
- 'عربی (اردن) - تیم (مرد)': 'ar-JO-TaimNeural',
74
  'عربی (کویت) - فهد (مرد)': 'ar-KW-FahedNeural',
75
  'عربی (کویت) - نورا (زن)': 'ar-KW-NouraNeural',
76
  'عربی (لبنان) - لیلا (زن)': 'ar-LB-LaylaNeural',
@@ -81,11 +82,11 @@ language_dict = {
81
  'عربی (مراکش) - مونا (زن)': 'ar-MA-MounaNeural',
82
  'عربی (عمان) - عبدالله (مرد)': 'ar-OM-AbdullahNeural',
83
  'عربی (عمان) - عایشه (زن)': 'ar-OM-AyshaNeural',
84
- 'عربی (قطر) - امل (زن)': 'ar-QA-AmalNeural',
85
  'عربی (قطر) - معاذ (مرد)': 'ar-QA-MoazNeural',
86
  'عربی (سوریه) - امانی (زن)': 'ar-SY-AmanyNeural',
87
  'عربی (سوریه) - لیث (مرد)': 'ar-SY-LaithNeural',
88
- 'عربی (تونس) - هادی (مرد)': 'ar-TN-HediNeural',
89
  'عربی (تونس) - ریم (زن)': 'ar-TN-ReemNeural',
90
  'عربی (یمن) - مریم (زن)': 'ar-YE-MaryamNeural',
91
  'عربی (یمن) - صالح (مرد)': 'ar-YE-SalehNeural',
@@ -96,15 +97,15 @@ language_dict = {
96
  'بنگالی (بنگلادش) - نابانیتا (زن)': 'bn-BD-NabanitaNeural',
97
  'بنگالی (بنگلادش) - پرادیپ (مرد)': 'bn-BD-PradeepNeural',
98
  'بنگالی (هند) - باشکار (مرد)': 'bn-IN-BashkarNeural',
99
- 'بنگالی (هند) - تانیشا (زن)': 'bn-IN-TanishaaNeural',
100
- 'بوسنیایی - گوران (مرد)': 'bs-BA-GoranNeural',
101
  'بوسنیایی - وسنا (زن)': 'bs-BA-VesnaNeural',
102
- 'کاتالان - جوآنا (زن)': 'ca-ES-JoanaNeural',
103
- 'کاتالان - انریک (مرد)': 'ca-ES-EnricNeural',
104
- 'چکی - آنتونین (مرد)': 'cs-CZ-AntoninNeural',
105
  'چکی - ولاستا (زن)': 'cs-CZ-VlastaNeural',
106
- 'ولزی - آلد (مرد)': 'cy-GB-AledNeural',
107
- 'ولزی - نیا (زن)': 'cy-GB-NiaNeural',
108
  'دانمارکی - کریستل (زن)': 'da-DK-ChristelNeural',
109
  'دانمارکی - یپه (مرد)': 'da-DK-JeppeNeural',
110
  'آلمانی (اتریش) - اینگرید (زن)': 'de-AT-IngridNeural',
@@ -133,7 +134,7 @@ language_dict = {
133
  'انگلیسی (نیوزیلند) - میچل (مرد)': 'en-NZ-MitchellNeural',
134
  'انگلیسی (نیوزیلند) - هیزل (زن)': 'en-NZ-HazelNeural',
135
  'انگلیسی (فیلیپین) - جیمز (مرد)': 'en-PH-JamesNeural',
136
- 'انگلیسی (فیلیپین) - رزا (زن)': 'en-PH-RosaNeural',
137
  'انگلیسی (سنگاپور) - لونا (زن)': 'en-SG-LunaNeural',
138
  'انگلیسی (سنگاپور) - وین (مرد)': 'en-SG-WayneNeural',
139
  'انگلیسی (تانزانیا) - الیمو (مرد)': 'en-TZ-ElimuNeural',
@@ -142,23 +143,172 @@ language_dict = {
142
  'انگلیسی (آفریقای جنوبی) - لوک (مرد)': 'en-ZA-LukeNeural',
143
  'اسپانیایی (آرژانتین) - النا (زن)': 'es-AR-ElenaNeural',
144
  'اسپانیایی (آرژانتین) - توماس (مرد)': 'es-AR-TomasNeural',
145
- # ... (ادامه لیست زبان ها را به همین ترتیب فارسی کنید) ...
146
- # مثال برای فارسی:
147
- 'فارسی (ایران) - دلارا (زن)': 'fa-IR-DilaraNeural',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  'فارسی (ایران) - فرید (مرد)': 'fa-IR-FaridNeural',
149
- # ...
150
- 'چینی (ماندارین) - شیائوشیاو (زن)': 'zh-CN-XiaoxiaoNeural',
151
- 'چینی (ماندارین) - یون‌یانگ (مرد)': 'zh-CN-YunyangNeural',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
 
154
-
155
- # --- توابع تبدیل متن به گفتار و wrapper (همانند قبل، بدون تغییر) ---
156
- async def text_to_speech_edge_async(text, language_code, rate, volume, pitch):
157
  try:
158
  if not text: return "خطا: لطفاً متنی را برای تبدیل وارد کنید.", None
159
- # اینجا language_code کلید فارسی شده از dropdown است، پس مقدار آن را می گیریم
160
- voice_id = language_dict.get(language_code)
161
- if voice_id is None: return f"خطا: مدل صدای انتخاب شده ('{language_code}') یافت نشد.", None
162
  rate_str, volume_str, pitch_str = f"{int(rate):+g}%", f"{int(volume):+g}%", f"{int(pitch):+g}Hz"
163
  communicate = edge_tts.Communicate(text, voice_id, rate=rate_str, volume=volume_str, pitch=pitch_str)
164
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file: tmp_path = tmp_file.name
@@ -168,7 +318,7 @@ async def text_to_speech_edge_async(text, language_code, rate, volume, pitch):
168
  error_msg = f"خطا: صدایی برای متن و صدای انتخاب شده دریافت نشد (صدا: {voice_id})."
169
  return error_msg, None
170
  except ValueError as ve:
171
- error_msg = f"خطا در پارامترهای ورودی تبدیل صدا: {ve}"
172
  return error_msg, None
173
  except Exception as e:
174
  return f"خطای غیرمنتظره در سرور: {type(e).__name__}", None
@@ -180,20 +330,20 @@ def _get_or_create_event_loop():
180
  _event_loops_by_thread[thread_id] = asyncio.new_event_loop()
181
  return _event_loops_by_thread[thread_id]
182
 
183
- def text_to_speech_edge_sync_wrapper(text, language_code, rate, volume, pitch):
184
  try:
185
  loop = _get_or_create_event_loop(); asyncio.set_event_loop(loop)
186
- result = loop.run_until_complete(text_to_speech_edge_async(text, language_code, rate, volume, pitch))
187
  except RuntimeError as e:
188
  if "no current event loop" in str(e).lower() or "cannot be called from a running event loop" in str(e).lower():
189
  new_loop = asyncio.new_event_loop(); asyncio.set_event_loop(new_loop)
190
- try: result = new_loop.run_until_complete(text_to_speech_edge_async(text, language_code, rate, volume, pitch))
191
  finally: new_loop.close()
192
  else: return f"خطای اجرایی: {e}", None
193
  except Exception as e: return f"خطای غیرمنتظره: {type(e).__name__}", None
194
  return result
195
 
196
- # --- تعریف تم و CSS (همانند قبل با اصلاحات جزئی در متن ها) ---
197
  app_theme = gr.themes.Soft(
198
  primary_hue=gr.themes.colors.blue,
199
  secondary_hue=gr.themes.colors.sky,
@@ -279,21 +429,21 @@ button[title="Flag"], button[aria-label="Flag"] {display: none !important; }
279
  }
280
  """
281
 
282
- # انتخاب صدای پیش فرض (مطمئن شوید کلید فارسی شده در language_dict وجود دارد)
283
  default_voice_key_persian = 'فارسی (ایران) - فرید (مرد)'
284
- if default_voice_key_persian not in language_dict:
285
- # اگر کلید فارسی شده موجود نبود، اولین کلید موجود را انتخاب کن
286
- default_voice_key_persian = list(language_dict.keys())[0] if language_dict else None
287
 
288
- LOGO_URL = "https://uploadkon.ir/uploads/4a3e22_25IMG-%DB%B2%DB%B0%DB%B2%DB%B5%DB%B0%DB%B3%DB%B2%DB%B2-%DB%B1%DB%B7%DB%B1%DB%B8%DB%B5%DB%B2.jpg" # یا URL لوگوی شما
289
 
290
  with gr.Blocks(theme=app_theme, css=custom_css) as demo:
291
  with gr.Row():
292
  gr.HTML(f"""
293
  <div class="app-header">
294
- <img src="{LOGO_URL}" alt="لوگوی برنامه" class="logo">
295
  <h1>مبدل هوشمند متن به گفتار</h1>
296
- <p>کیفیت صدای طبیعی و روان برای متون شما</p>
297
  </div>
298
  """)
299
 
@@ -301,45 +451,45 @@ with gr.Blocks(theme=app_theme, css=custom_css) as demo:
301
  with gr.Column(scale=3):
302
  input_text = gr.Textbox(
303
  lines=5,
304
- label="📝 متن خود را اینجا وارد نمایید:",
305
- placeholder="مثال: به نام خداوند بخشنده مهربان...",
306
  value=""
307
  )
308
- language = gr.Dropdown(
309
- choices=list(language_dict.keys()), # استفاده از کلیدهای فارسی شده
310
- value=default_voice_key_persian, # مقدار پیش فرض با کلید فارسی شده
311
- label="🗣️ زبان و گوینده را انتخاب کنید:"
312
  )
313
- with gr.Accordion("⚙️ تنظیمات بیشتر صدا (اختیاری)", open=False):
314
  with gr.Row():
315
- rate = gr.Slider(minimum=-100, maximum=100, step=1, value=0, label="سرعت (%)", scale=1)
316
- volume = gr.Slider(minimum=-100, maximum=100, step=1, value=0, label="حجم (%)", scale=1)
317
- pitch = gr.Slider(minimum=-50, maximum=50, step=1, value=0, label="گام (Hz)", scale=2)
318
 
319
  submit_button = gr.Button("🔊 تولید و پخش صدا", variant="primary")
320
 
321
  with gr.Column(scale=2):
322
- output_text_status = gr.Textbox(label="📊 وضعیت عملیات:", interactive=False, lines=1, placeholder="نتیجه اینجا نمایش داده می‌شود...")
323
- output_audio = gr.Audio(type="filepath", label="🎧 فایل صوتی:", interactive=False)
324
 
325
  gr.HTML("<hr style='margin-top: 1rem; margin-bottom: 1rem; border: 0; border-top: 1px solid #dee2e6;'>")
326
 
327
  gr.Examples(
328
  examples=[
329
- ["به نام خداوند جان و خرد، کزین برتر اندیشه برنگذرد.", 'فارسی (ایران) - دلارا (زن)', 0, 0, 0],
330
- ["این یک نمونه متن انگلیسی برای آزمایش است.", 'انگلیسی - جنی (زن)', +5, -5, 0],
331
- ["این ابزار به شما کمک می‌کند متن را به صدا تبدیل کنید.", 'فارسی (ایران) - فرید (مرد)', -5, 0, +5],
332
  ],
333
- inputs=[input_text, language, rate, volume, pitch],
334
  outputs=[output_text_status, output_audio],
335
  fn=text_to_speech_edge_sync_wrapper,
336
  cache_examples=False,
337
- label="💡 چند نمونه برای امتحان:"
338
  )
339
 
340
  submit_button.click(
341
  fn=text_to_speech_edge_sync_wrapper,
342
- inputs=[input_text, language, rate, volume, pitch],
343
  outputs=[output_text_status, output_audio],
344
  )
345
 
 
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',
 
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',
 
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',
 
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',
 
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',
 
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',
 
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',
 
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
 
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
 
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,
 
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 = "https://www.gstatic.com/lamda/images/gemini/google_bard_logo_150_v2_dark_color_1x.png" # یک لوگوی جایگزین (می توانید تغییر دهید)
439
 
440
  with gr.Blocks(theme=app_theme, css=custom_css) as demo:
441
  with gr.Row():
442
  gr.HTML(f"""
443
  <div class="app-header">
444
+ <img src="{LOGO_URL}" alt="TTS App Logo" class="logo">
445
  <h1>مبدل هوشمند متن به گفتار</h1>
446
+ <p>با کیفیت صدای طبیعی و روان، متن خود را زنده کنید</p>
447
  </div>
448
  """)
449
 
 
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