Spaces:
Paused
Paused
| import gradio as gr | |
| import os | |
| import torch | |
| from TTS.api import TTS # مكتبة Coqui TTS | |
| import soundfile as sf # للتعامل مع الملفات الصوتية (Coqui TTS قد تستخدمها داخلياً) | |
| # --- 1. تحميل النموذج (يتم مرة واحدة عند بدء التطبيق) --- | |
| # هذا الجزء يستغرق وقتاً طويلاً ويستهلك ذاكرة كبيرة. | |
| # يفضل وضع النماذج في Cache Hugging Face إذا أمكن. | |
| # تحديد الجهاز (GPU إذا كان متاحاً، وإلا CPU) | |
| DEVICE = "cuda:0" if torch.cuda.is_available() else "cpu" | |
| print(f"Using device: {DEVICE}") | |
| # تحميل نموذج Coqui TTS (XTTS-v2) | |
| # هذا النموذج هو الذي يقوم باستنساخ الصوت وتحويل النص إلى كلام | |
| tts = None # تهيئة المتغير | |
| try: | |
| tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=torch.cuda.is_available()) | |
| print("Coqui TTS XTTS-v2 model loaded successfully.") | |
| except Exception as e: | |
| print(f"Error loading Coqui TTS model: {e}") | |
| # إذا فشل التحميل، لن يكون tts متاحاً وستظهر رسالة خطأ للمستخدم. | |
| # --- 2. تعريف وظائف التطبيق --- | |
| # دالة لتخزين مسار الصوت المرجعي المستنسخ | |
| # تتلقى مسار الصوت من مدخل الميكروفون أو من مدخل رفع الملفات | |
| def set_reference_audio(mic_path, upload_path): | |
| audio_path = None | |
| if mic_path: | |
| audio_path = mic_path | |
| elif upload_path: | |
| audio_path = upload_path | |
| if not audio_path: | |
| return None, "خطأ: لم يتم تسجيل أو رفع صوت لنسخه. يرجى المحاولة مرة أخرى." | |
| # التأكد من أن الملف الصوتي صالح للقراءة | |
| try: | |
| # اختبار قراءة الملف للتأكد من سلامته وقابليته للوصول | |
| # بعض الأحيان Gradio يمرر مساراً غير صالح أو فارغاً. | |
| # sf.read سيقوم بفحص الملف | |
| sf.read(audio_path) | |
| except Exception as e: | |
| return None, f"خطأ في قراءة الملف الصوتي: {e}. تأكد من أنه ملف صوتي صالح." | |
| print(f"Reference audio set to: {audio_path}") | |
| return audio_path, "تم تحميل الصوت المرجعي بنجاح! يمكنك الآن تحويل النص إلى صوتك المستنسخ." | |
| # دالة لتحويل النص إلى كلام بالصوت المستنسخ (Text-to-Speech) | |
| def synthesize_text(reference_audio_path, text_input): | |
| if not tts: | |
| return None, "خطأ: نموذج استنساخ الصوت لم يتم تحميله بشكل صحيح عند بدء التطبيق. الرجاء التحقق من سجلات Space." | |
| if not reference_audio_path: | |
| return None, "خطأ: يرجى أولاً تسجيل أو رفع صوت لنسخه وتحديده." | |
| if not text_input: | |
| return None, "خطأ: يرجى إدخال نص لتحويله." | |
| try: | |
| # XTTS-v2 يدعم لغات متعددة، بما في ذلك العربية (ar) | |
| output_file = "output_tts.wav" | |
| tts.tts_to_file( | |
| text=text_input, | |
| speaker_wav=reference_audio_path, | |
| language="ar", # تحديد اللغة العربية | |
| file_path=output_file | |
| ) | |
| print(f"Text-to-Speech generated: {output_file}") | |
| return output_file, "تم تحويل النص إلى صوت بنجاح!" | |
| except Exception as e: | |
| print(f"Error during TTS synthesis: {e}") | |
| return None, f"خطأ أثناء تحويل النص إلى صوت: {e}. تأكد من جودة الصوت المرجعي." | |
| # --- 3. بناء واجهة Gradio --- | |
| with gr.Blocks(theme="soft", title="تطبيق استنساخ الصوت (TTS)") as demo: | |
| gr.Markdown("# تطبيق استنساخ الصوت (تحويل النص إلى كلام)") | |
| gr.Markdown("قم بتسجيل أو رفع **صوت مرجعي واضح (5-10 ثواني على الأقل)** لاستنساخه، ثم استخدمه لتحويل النص إلى صوتك المستنسخ.") | |
| # متغير الحالة لتخزين مسار الصوت المرجعي | |
| reference_audio_path_state = gr.State(None) | |
| # قسم تسجيل/رفع الصوت المراد استنساخه | |
| with gr.Column(elem_id="reference_section"): | |
| gr.Markdown("## 1. تسجيل/رفع الصوت المراد استنساخه") | |
| with gr.Row(): | |
| record_ref_audio_input = gr.Audio( | |
| sources=["microphone"], type="filepath", label="سجل صوتك لنسخه" | |
| ) | |
| upload_ref_audio_input = gr.Audio( | |
| sources=["upload"], type="filepath", label="أو ارفع ملف صوتي لنسخه (.wav, .mp3)" | |
| ) | |
| set_ref_audio_btn = gr.Button("تحديد الصوت المرجعي") | |
| ref_status_msg = gr.Markdown("يرجى تحديد الصوت المرجعي لبدء الاستنساخ.") | |
| # قسم تحويل النص إلى كلام (Text-to-Speech) | |
| with gr.Column(elem_id="tts_section"): | |
| gr.Markdown("## 2. تحويل النص إلى كلام (TTS)") | |
| text_input = gr.Textbox(label="أدخل النص المطلوب تحويله إلى صوتك المستنسخ", placeholder="مثال: مرحباً بكم في عالم الذكاء الاصطناعي.") | |
| tts_output = gr.Audio(label="الصوت المستنسخ (من النص)", autoplay=True) | |
| synthesize_btn = gr.Button("تحويل النص إلى صوت") | |
| tts_status_msg = gr.Markdown("") | |
| # رسالة تحذير حول الموارد والأداء (مهمة جداً) | |
| gr.Markdown(""" | |
| <p style="font-size: 0.9em; color: #a00; margin-top: 30px; padding-top: 15px; border-top: 1px dashed #f00; text-align: center; font-weight: bold;"> | |
| ⚠️ ملاحظة هامة: هذا التطبيق يستخدم نموذج ذكاء اصطناعي كبير (XTTS-v2). | |
| <br> | |
| * **سيستغرق التحميل الأولي (عند بدء Space) وقتاً طويلاً جداً (عدة دقائق).** | |
| * **يوصى بشدة باستخدام موارد GPU (مثل T4 Small) للحصول على أداء مقبول.** | |
| * على موارد CPU (Basic)، قد تكون العمليات بطيئة للغاية أو تفشل بسبب تجاوز المهلة أو نفاد الذاكرة. | |
| * جودة الاستنساخ تعتمد بشكل كبير على وضوح ونقاء الصوت المرجعي الذي تقدمه. | |
| </p> | |
| """, elem_id="disclaimer") | |
| # --- تعريف تفاعلات الأزرار --- | |
| # عند النقر على "تحديد الصوت المرجعي" | |
| set_ref_audio_btn.click( | |
| fn=set_reference_audio, | |
| inputs=[record_ref_audio_input, upload_ref_audio_input], | |
| outputs=[reference_audio_path_state, ref_status_msg] | |
| ) | |
| # عند النقر على "تحويل النص إلى صوت" | |
| synthesize_btn.click( | |
| fn=synthesize_text, | |
| inputs=[reference_audio_path_state, text_input], | |
| outputs=[tts_output, tts_status_msg] | |
| ) | |
| # تشغيل التطبيق | |
| if __name__ == "__main__": | |
| demo.launch() |