| import gradio as gr |
| import os |
| import torch |
| from TTS.api import TTS |
| import soundfile as sf |
|
|
| |
| |
| |
|
|
| |
| DEVICE = "cuda:0" if torch.cuda.is_available() else "cpu" |
| print(f"Using device: {DEVICE}") |
|
|
| |
| |
| 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}") |
| |
|
|
| |
|
|
| |
| |
| 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: |
| |
| |
| |
| sf.read(audio_path) |
| except Exception as e: |
| return None, f"خطأ في قراءة الملف الصوتي: {e}. تأكد من أنه ملف صوتي صالح." |
|
|
| print(f"Reference audio set to: {audio_path}") |
| return audio_path, "تم تحميل الصوت المرجعي بنجاح! يمكنك الآن تحويل النص إلى صوتك المستنسخ." |
|
|
| |
| 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: |
| |
| 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}. تأكد من جودة الصوت المرجعي." |
|
|
| |
| 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("يرجى تحديد الصوت المرجعي لبدء الاستنساخ.") |
|
|
| |
| 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() |