File size: 8,780 Bytes
2fa8637 dec8bb3 2fa8637 3090f63 59d09f0 dec8bb3 88afdfa 2fa8637 3090f63 2fa8637 88afdfa 59d09f0 2fa8637 88afdfa 2fa8637 59d09f0 3090f63 88afdfa 59d09f0 dec8bb3 59d09f0 88afdfa 59d09f0 3090f63 dec8bb3 3090f63 59d09f0 3090f63 169ec87 3090f63 59d09f0 3090f63 59d09f0 3090f63 169ec87 59d09f0 169ec87 59d09f0 3090f63 59d09f0 3090f63 59d09f0 169ec87 3090f63 169ec87 59d09f0 3090f63 59d09f0 2fa8637 3090f63 2fa8637 169ec87 dec8bb3 169ec87 dec8bb3 169ec87 88afdfa 169ec87 88afdfa 169ec87 dec8bb3 169ec87 dec8bb3 169ec87 88afdfa dec8bb3 169ec87 dec8bb3 169ec87 88afdfa dec8bb3 169ec87 dec8bb3 169ec87 3090f63 2fa8637 dec8bb3 2fa8637 3090f63 169ec87 2fa8637 3090f63 2fa8637 88afdfa 59d09f0 3090f63 2fa8637 dec8bb3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# app.py
import gradio as gr
import google.generativeai as genai
# from google.generativeai import types # دیگر نیازی به types برای GenerationConfig با response_modalities نیست
import os
import io
from scipy.io.wavfile import write as write_wav
import numpy as np
import traceback
import json # برای parse کردن خطای JSON احتمالی
GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
if not GOOGLE_API_KEY:
raise ValueError("GOOGLE_API_KEY not found in environment variables.")
genai.configure(api_key=GOOGLE_API_KEY)
# --- تغییر نام مدل به نسخه Pro TTS ---
TTS_MODEL_NAME = "gemini-2.5-pro-preview-tts"
# --- پایان تغییر ---
AVAILABLE_VOICES = ["پیشفرض (مدل انتخاب کند)"]
def generate_audio(text_to_speak, selected_voice_name="پیشفرض (مدل انتخاب کند)"):
if not text_to_speak:
raise gr.Error("لطفاً متنی را برای تبدیل به صدا وارد کنید.")
print(f"درخواست TTS برای متن: '{text_to_speak[:50]}...' با گوینده: {selected_voice_name} و مدل: models/{TTS_MODEL_NAME}")
try:
model = genai.GenerativeModel(f"models/{TTS_MODEL_NAME}")
generation_config_params = {} # فعلاً بدون پارامتر خاص برای generation_config
if selected_voice_name != "پیشفرض (مدل انتخاب کند)":
print(f"توجه: انتخاب گوینده ('{selected_voice_name}') هنوز به طور کامل پیادهسازی نشده است.")
generation_config_to_pass = None
if generation_config_params:
generation_config_to_pass = genai.types.GenerationConfig(**generation_config_params)
print(f"ارسال درخواست به Gemini با generation_config: {generation_config_params}")
else:
print("ارسال درخواست به Gemini بدون generation_config خاص (با تنظیمات پیشفرض مدل).")
response = model.generate_content(
text_to_speak,
generation_config=generation_config_to_pass
)
audio_bytes = None
generated_mime_type = None
sample_rate = 24000
if hasattr(response, 'candidates') and response.candidates and \
response.candidates[0].content and response.candidates[0].content.parts:
for part in response.candidates[0].content.parts:
if hasattr(part, 'inline_data') and part.inline_data and \
hasattr(part.inline_data, 'mime_type') and part.inline_data.mime_type.startswith("audio/"):
audio_bytes = part.inline_data.data
generated_mime_type = part.inline_data.mime_type
if ";rate=" in generated_mime_type:
try:
sample_rate = int(generated_mime_type.split(";rate=")[1])
print(f"نرخ نمونهبرداری از MIME type استخراج شد: {sample_rate} Hz")
except:
print(f"خطا در استخراج نرخ نمونهبرداری از MIME type: {generated_mime_type}. از پیشفرض {sample_rate} Hz استفاده میشود.")
print(f"داده صوتی با MIME type: {generated_mime_type} دریافت شد.")
break
if audio_bytes is None:
if hasattr(response, 'audio_content'):
audio_bytes = response.audio_content
generated_mime_type = "audio/wav"
print("داده صوتی از فیلد audio_content دریافت شد.")
else:
print("پاسخ کامل مدل (برای دیباگ):", response)
error_text = response.prompt_feedback if hasattr(response, 'prompt_feedback') else str(response)
raise gr.Error(f"پاسخ صوتی از مدل دریافت نشد. پاسخ مدل: {error_text}")
output_filename = "output.wav"
if "pcm" in (generated_mime_type or "").lower():
print(f"داده PCM خام ({len(audio_bytes)} بایت) با نرخ نمونهبرداری {sample_rate} Hz دریافت شد، در حال تبدیل به WAV...")
audio_np = np.frombuffer(audio_bytes, dtype=np.int16)
wav_io = io.BytesIO()
write_wav(wav_io, sample_rate, audio_np)
wav_io.seek(0)
with open(output_filename, "wb") as f:
f.write(wav_io.read())
elif audio_bytes:
print(f"داده صوتی با فرمت {generated_mime_type} ({len(audio_bytes)} بایت) دریافت شد، مستقیم ذخیره میشود.")
with open(output_filename, "wb") as f:
f.write(audio_bytes)
else:
raise gr.Error("هیچ داده صوتی برای ذخیره وجود ندارد.")
print(f"فایل صوتی در {output_filename} ذخیره شد.")
return output_filename
except genai.types.BlockedPromptException as bpe:
print(f"درخواست توسط مدل بلاک شد: {bpe}")
raise gr.Error(f"محتوای شما توسط مدل پذیرفته نشد. لطفاً متن دیگری را امتحان کنید. دلیل: {bpe}")
except Exception as e:
print(f"خطای کلی در تولید صدا: {e}")
traceback.print_exc()
error_message_from_api = ""
# ... (بقیه کد مدیریت خطا که قبلاً داشتیم) ...
if hasattr(e, 'args') and e.args:
if isinstance(e.args[0], str) and "HttpError" in e.args[0]:
error_message_from_api = str(e.args[0])
try:
details_start = error_message_from_api.find('{')
if details_start != -1:
json_str_candidate = error_message_from_api[details_start:]
cleaned_json_str = ''.join(c for c in json_str_candidate if ord(c) >= 32 or c in ('\t','\r','\n')).strip()
error_obj = json.loads(cleaned_json_str)
if 'error' in error_obj and 'message' in error_obj['error']:
error_message_from_api = error_obj['error']['message']
elif 'message' in error_obj :
error_message_from_api = error_obj['message']
except Exception as json_e:
print(f"خطا در parse کردن جزئیات JSON از پیام خطای API: {json_e}")
else:
error_message_from_api = str(e.args[0])
elif hasattr(e, 'message') and isinstance(e.message, str):
error_message_from_api = e.message
final_error_message = f"خطا در ارتباط با Gemini API یا پردازش صدا: {str(e)}"
if error_message_from_api and error_message_from_api not in final_error_message :
final_error_message += f" | پیام دقیقتر API: {error_message_from_api}"
raise gr.Error(final_error_message)
# --- رابط کاربری Gradio بدون تغییر ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# تبدیل متن به صدا با Gemini ♊")
gr.Markdown("متن خود را وارد کنید تا با استفاده از مدلهای جدید Gemini به صدا تبدیل شود.")
with gr.Row():
with gr.Column(scale=2):
text_input = gr.Textbox(lines=5, label="متن ورودی", placeholder="متن خود را اینجا بنویسید...")
submit_button = gr.Button("🔊 تبدیل به صدا", variant="primary")
with gr.Column(scale=1):
audio_output = gr.Audio(label="خروجی صدا", type="filepath")
gr.Examples(
examples=[
["سلام، حال شما چطور است؟"],
["به دنیای هوش مصنوعی خوش آمدید."],
["این یک تست برای تبدیل متن به صدا با استفاده از جیمینای است."]
],
inputs=[text_input]
)
submit_button.click(
fn=generate_audio,
inputs=[text_input],
outputs=[audio_output],
api_name="text_to_speech"
)
gr.Markdown("---")
gr.Markdown(f"مدل مورد استفاده: `models/{TTS_MODEL_NAME}`") # نام مدل به روز شده را نمایش میدهد
gr.Markdown("توجه: برای انتخاب گویندههای مختلف، نیاز به بررسی مستندات دقیق مدل TTS و بروزرسانی کد است.")
if __name__ == "__main__":
demo.launch(debug=True) |