Hamed744 commited on
Commit
2fa8637
·
verified ·
1 Parent(s): d93cc04

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +160 -0
app.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import gradio as gr
3
+ import google.generativeai as genai
4
+ import os
5
+ import io
6
+ from scipy.io.wavfile import write as write_wav # برای ذخیره فایل صوتی
7
+
8
+ # دریافت API Key از Secrets هاگینگ فیس
9
+ # مطمئن شوید که یک Secret به نام GOOGLE_API_KEY در اسپیس خود تعریف کرده‌اید
10
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
11
+
12
+ if not GOOGLE_API_KEY:
13
+ raise ValueError("GOOGLE_API_KEY not found in environment variables. Please set it in Hugging Face Secrets.")
14
+
15
+ genai.configure(api_key=GOOGLE_API_KEY)
16
+
17
+ # انتخاب مدل TTS
18
+ # گزینه ها: "gemini-2.5-flash-preview-tts" یا "gemini-2.5-pro-preview-tts"
19
+ # برای شروع، از flash استفاده می‌کنیم
20
+ TTS_MODEL_NAME = "gemini-2.5-flash-preview-tts" # یا "tts-1" اگر نام‌های ساده‌تر هم کار می‌کنند (باید مستندات دقیق را چک کرد)
21
+ # بر اساس مستندات جدید، نام دقیق مدل‌ها به این شکل است.
22
+
23
+ # لیستی از صداهای موجود (این لیست ممکن است نیاز به بروزرسانی بر اساس مستندات دقیق مدل TTS داشته باشد)
24
+ # این فقط یک مثال است، باید نام‌های دقیق voice ها را از مستندات پیدا کنید.
25
+ # مستندات قبلی برای Live API صداهایی مانند Puck, Charon, Kore, Fenrir, Aoede, Leda, Orus, and Zephyr را ذکر کرده بود.
26
+ # اما برای مدل‌های TTS اختصاصی، ممکن است لیست متفاوت باشد یا اصلاً نیازی به انتخاب voice نباشد و مدل خودش بهینه عمل کند.
27
+ # فعلاً این بخش را ساده نگه می‌داریم و به مدل اجازه می‌دهیم voice را انتخاب کند.
28
+ AVAILABLE_VOICES = ["Default"] # یا لیستی از نام‌های واقعی voice اگر دارید
29
+
30
+ def generate_audio(text_to_speak, voice_selection="Default"):
31
+ """
32
+ متن را به صدا تبدیل می‌کند با استفاده از Gemini API.
33
+ """
34
+ if not text_to_speak:
35
+ raise gr.Error("لطفاً متنی را برای تبدیل به صدا وارد کنید.")
36
+ print(f"درخواست TTS برای متن: '{text_to_speak[:50]}...' با voice: {voice_selection}")
37
+
38
+ try:
39
+ # ایجاد مدل
40
+ # توجه: نحوه فراخوانی مدل TTS ممکن است با generate_content متفاوت باشد.
41
+ # باید مستندات دقیق را برای "Text-to-speech (TTS)" با Gemini 2.5 Flash/Pro بررسی کنیم.
42
+ # فرض می‌کنیم که می‌توانیم با generate_content و ارسال متن، خروجی صوتی بگیریم.
43
+ # این بخش احتمالاً نیاز به اصلاح بر اساس API دقیق TTS دارد.
44
+
45
+ # بر اساس مستندات قیمت‌گذاری، مدل‌های TTS ورودی متن و خروجی صدا دارند.
46
+ # نحوه دقیق فراخوانی برای دریافت بایت‌های صوتی ممکن است به این شکل باشد:
47
+ model = genai.GenerativeModel(TTS_MODEL_NAME)
48
+
49
+ # برای مدل‌های TTS، "prompt" همان متنی است که می‌خواهیم به صدا تبدیل شود.
50
+ # ممکن است نیاز به پارامترهای خاصی در generation_config برای صدا باشد.
51
+ response = model.generate_content(
52
+ text_to_speak,
53
+ # generation_config=genai.types.GenerationConfig(
54
+ # # پارامترهای خاص TTS در اینجا قرار می‌گیرند، اگر وجود داشته باشد
55
+ # # مثلاً voice، سرعت، لحن و ...
56
+ # # response_mime_type="audio/wav" or "audio/mp3" ???
57
+ # )
58
+ )
59
+
60
+ # پاسخ مدل‌های TTS معمولاً شامل بایت‌های صوتی است.
61
+ # باید بررسی کنیم که پاسخ در چه فرمتی است.
62
+ # فرض می‌کنیم پاسخ دارای یک پراپرتی audio_content یا مشابه است که بایت‌ها را دارد.
63
+ # این بخش کاملاً به خروجی واقعی API بستگی دارد.
64
+
65
+ # --- این بخش حدسی است و باید با مستندات API تطبیق داده شود ---
66
+ if hasattr(response, 'audio_content') and response.audio_content:
67
+ audio_bytes = response.audio_content
68
+ elif hasattr(response, 'candidates') and response.candidates[0].content.parts[0].inline_data:
69
+ # این ساختار برای inline_data در پاسخ‌های چندوجهی است
70
+ audio_part = response.candidates[0].content.parts[0]
71
+ if audio_part.inline_data.mime_type.startswith("audio/"):
72
+ audio_bytes = audio_part.inline_data.data
73
+ else:
74
+ raise gr.Error(f"ف��مت پاسخ صوتی نامعتبر: {audio_part.inline_data.mime_type}")
75
+ elif hasattr(response, 'text'): # اگر به اشتباه پاسخ متنی گرفتیم
76
+ raise gr.Error(f"مدل پاسخ متنی برگرداند به جای صدا: {response.text}")
77
+ else:
78
+ print("پاسخ کامل مدل:", response) # برای دیباگ
79
+ raise gr.Error("پاسخ صوتی از مدل دریافت نشد یا فرمت آن ناشناخته است.")
80
+ # --- پایان بخش حدسی ---
81
+
82
+ # ذخیره بایت‌های صوتی در یک فایل WAV موقت
83
+ # ما به نرخ نمونه‌برداری (sample rate) صدای خروجی نیاز داریم.
84
+ # مدل‌های TTS معمولاً با نرخ نمونه‌برداری مشخصی خروجی می‌دهند (مثلاً 24000 Hz).
85
+ # این مقدار باید از مستندات API گرفته شود. فرض می‌کنیم 24000 Hz است.
86
+ sample_rate = 24000 # هرتز - این را از مستندات API برای مدل TTS خود چک کنید!
87
+
88
+ # تبدیل بایت‌ها به فرمتی که Gradio بتواند پخش کند (فایل WAV)
89
+ # کتابخانه google-generativeai ممکن است مستقیماً فایل صوتی برنگرداند، بلکه بایت‌های خام PCM.
90
+ # یا ممکن است یک آبجکت خاص Audio برگرداند.
91
+ # ساده‌ترین حالت این است که API مستقیماً بایت‌های یک فایل WAV را برگرداند.
92
+ # اگر بایت‌های خام PCM برمی‌گرداند، باید آنها را به WAV تبدیل کنیم.
93
+
94
+ # فرض می‌کنیم audio_bytes حاوی داده‌های یک فایل WAV کامل است
95
+ # یا باید با استفاده از scipy.io.wavfile یا wave آن را بسازیم.
96
+ # اگر audio_bytes داده خام PCM16 است:
97
+ # import numpy as np
98
+ # audio_np = np.frombuffer(audio_bytes, dtype=np.int16)
99
+ # wav_io = io.BytesIO()
100
+ # write_wav(wav_io, sample_rate, audio_np)
101
+ # output_audio_path = wav_io # Gradio می‌تواند BytesIO را به عنوان فایل صوتی بپذیرد
102
+
103
+ # برای سادگی، فرض می‌کنیم audio_bytes بایت‌های یک فایل صوتی قابل پخش است (مثلاً WAV)
104
+ # و Gradio می‌تواند آن را مستقیماً به عنوان (sample_rate, np_array) یا مسیر فایل یا BytesIO بپذیرد.
105
+ # اگر API یک آبجکت خاص برمی‌گرداند، باید آن را مطابق مستندات پردازش کنید.
106
+
107
+ # برای اینکه Gradio بتواند پخش کند، ما به (sample_rate, numpy_array) نیاز داریم
108
+ # یا مسیر یک فایل. اگر بایت‌های خام PCM داریم:
109
+ # این بخش نیاز به کار بیشتری دارد اگر API بایت‌های خام PCM برمی‌گرداند.
110
+ # فعلاً فرض می‌کنیم API یک فرمت قابل قبول برای Gradio برمی‌گرداند یا ما آن را تبدیل می‌کنیم.
111
+
112
+ # ساده‌ترین راه برای تست اولیه: ذخیره بایت‌ها در فایل و برگرداندن مسیر فایل
113
+ output_filename = "output_audio.wav"
114
+ with open(output_filename, "wb") as f:
115
+ f.write(audio_bytes)
116
+
117
+ print(f"فایل صوتی در {output_filename} ذخیره شد.")
118
+ return output_filename # Gradio می‌تواند مسیر فایل را برای Audio output بگیرد
119
+
120
+ except Exception as e:
121
+ print(f"خطا در تولید صدا: {e}")
122
+ # نمایش جزئیات بیشتر خطا برای دیباگ
123
+ import traceback
124
+ traceback.print_exc()
125
+ raise gr.Error(f"خطا در ارتباط با Gemini API یا پردازش صدا: {str(e)}")
126
+
127
+ # ایجاد رابط کاربری Gradio
128
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
129
+ gr.Markdown("# تبدیل متن به صدا با Gemini ♊")
130
+ gr.Markdown("متن خود را وارد کنید تا با استفاده از مدل‌های جدید Gemini به صدا تبدیل شود.")
131
+
132
+ with gr.Row():
133
+ with gr.Column(scale=2):
134
+ text_input = gr.Textbox(lines=5, label="متن ورودی", placeholder="متن خود را اینجا بنویسید...")
135
+ # voice_dropdown = gr.Dropdown(choices=AVAILABLE_VOICES, value="Default", label="انتخاب صدا (اختیاری)") # فعلاً ساده
136
+ submit_button = gr.Button("🔊 تبدیل به صدا", variant="primary")
137
+ with gr.Column(scale=1):
138
+ audio_output = gr.Audio(label="خروجی صدا", type="filepath") # یا type="numpy" اگر آرایه برمی‌گردانید
139
+
140
+ gr.Examples(
141
+ examples=[
142
+ ["سلام، حال شما چطور است؟"],
143
+ ["به دنیای هوش مصنوعی خوش آمدید."],
144
+ ["این یک تست برای تبدیل متن به صدا با استفاده از جیمینای است."]
145
+ ],
146
+ inputs=[text_input]
147
+ )
148
+
149
+ submit_button.click(
150
+ fn=generate_audio,
151
+ inputs=[text_input], # voice_dropdown اگر فعال بود
152
+ outputs=[audio_output],
153
+ api_name="text_to_speech"
154
+ )
155
+
156
+ gr.Markdown("---")
157
+ gr.Markdown(f"مدل مورد استفاده: `{TTS_MODEL_NAME}`")
158
+
159
+ if __name__ == "__main__":
160
+ demo.launch(debug=True) # debug=True برای دیدن لاگ‌های بیشتر در کنسول