voisclone / app.py
najimq59's picture
Update app.py
bc8d671 verified
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()