Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -83,43 +83,28 @@ class TTSGenerator:
|
|
83 |
|
84 |
tts_generator = TTSGenerator()
|
85 |
|
86 |
-
def generate_speech(text, lang
|
87 |
-
"""توليد الصوت باستخدام
|
88 |
try:
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
return None
|
92 |
-
|
93 |
-
processor, model = tts_generator.get_model(lang, gender)
|
94 |
-
style_params = VOICE_STYLES[style]
|
95 |
-
|
96 |
-
# تحويل النص إلى توكنز
|
97 |
-
inputs = processor(text=text, return_tensors="pt")
|
98 |
-
|
99 |
-
# توليد الصوت
|
100 |
-
speech = model.generate_speech(inputs["input_ids"], processor)
|
101 |
-
|
102 |
-
# تطبيق التأثيرات الصوتية
|
103 |
-
if style != 'normal':
|
104 |
-
speech = torchaudio.functional.speed(speech, style_params['speed_factor'])
|
105 |
-
if style_params['pitch_shift'] != 0:
|
106 |
-
speech = torchaudio.functional.pitch_shift(
|
107 |
-
speech,
|
108 |
-
sample_rate=16000,
|
109 |
-
n_steps=style_params['pitch_shift']
|
110 |
-
)
|
111 |
-
|
112 |
-
# حفظ الصوت في ملف مؤقت
|
113 |
-
audio_path = tempfile.mktemp(suffix='.wav')
|
114 |
-
torchaudio.save(audio_path, speech.unsqueeze(0), 16000)
|
115 |
-
|
116 |
-
return audio_path
|
117 |
|
118 |
except Exception as e:
|
119 |
logger.error(f"خطأ في توليد الصوت: {str(e)}")
|
120 |
return None
|
121 |
|
122 |
-
def text_to_speech(text, lang,
|
123 |
"""واجهة لتحويل النص إلى صوت"""
|
124 |
if not text:
|
125 |
logger.warning("لم يتم تقديم نص للتحويل إلى صوت")
|
@@ -129,14 +114,15 @@ def text_to_speech(text, lang, gender='male', style='normal', progress=gr.Progre
|
|
129 |
progress(0.2, desc="جاري تجهيز الصوت...")
|
130 |
logger.info(f"بدء تحويل النص إلى صوت باللغة: {lang}")
|
131 |
|
132 |
-
# تقسيم النص إلى
|
133 |
-
|
134 |
-
|
135 |
|
|
|
136 |
audio_files = []
|
137 |
-
for i,
|
138 |
-
progress((i + 1) / len(
|
139 |
-
audio_path = generate_speech(
|
140 |
if audio_path:
|
141 |
audio_files.append(audio_path)
|
142 |
|
@@ -144,28 +130,34 @@ def text_to_speech(text, lang, gender='male', style='normal', progress=gr.Progre
|
|
144 |
logger.error("لم يتم إنشاء أي ملفات صوتية")
|
145 |
return None
|
146 |
|
|
|
147 |
if len(audio_files) == 1:
|
148 |
return audio_files[0]
|
149 |
|
150 |
-
# دمج الملفات الصوتية
|
151 |
from pydub import AudioSegment
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
|
|
|
|
|
|
|
|
166 |
|
167 |
-
|
168 |
-
|
|
|
169 |
|
170 |
except Exception as e:
|
171 |
logger.error(f"خطأ في تحويل النص إلى صوت: {str(e)}")
|
|
|
83 |
|
84 |
tts_generator = TTSGenerator()
|
85 |
|
86 |
+
async def generate_speech(text, lang):
|
87 |
+
"""توليد الصوت باستخدام edge-tts"""
|
88 |
try:
|
89 |
+
voice = VOICE_MAPPINGS.get(lang, 'en-US-EricNeural')
|
90 |
+
communicate = edge_tts.Communicate(text, voice)
|
91 |
+
|
92 |
+
audio_path = tempfile.mktemp(suffix='.mp3')
|
93 |
+
await communicate.save(audio_path)
|
94 |
+
|
95 |
+
# التحقق من وجود الملف وحجمه
|
96 |
+
if os.path.exists(audio_path) and os.path.getsize(audio_path) > 0:
|
97 |
+
logger.info(f"تم إنشاء ملف صوتي: {audio_path}")
|
98 |
+
return audio_path
|
99 |
+
else:
|
100 |
+
logger.error("فشل إنشاء ملف صوتي صالح")
|
101 |
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
|
103 |
except Exception as e:
|
104 |
logger.error(f"خطأ في توليد الصوت: {str(e)}")
|
105 |
return None
|
106 |
|
107 |
+
def text_to_speech(text, lang, progress=gr.Progress()):
|
108 |
"""واجهة لتحويل النص إلى صوت"""
|
109 |
if not text:
|
110 |
logger.warning("لم يتم تقديم نص للتحويل إلى صوت")
|
|
|
114 |
progress(0.2, desc="جاري تجهيز الصوت...")
|
115 |
logger.info(f"بدء تحويل النص إلى صوت باللغة: {lang}")
|
116 |
|
117 |
+
# تقسيم النص إلى أجزاء إذا كان طويلاً
|
118 |
+
max_length = 1000
|
119 |
+
text_parts = [text[i:i+max_length] for i in range(0, len(text), max_length)]
|
120 |
|
121 |
+
# إنشاء ملف صوتي لكل جزء
|
122 |
audio_files = []
|
123 |
+
for i, part in enumerate(text_parts):
|
124 |
+
progress((i + 1) / len(text_parts), desc=f"معالجة الجزء {i+1} من {len(text_parts)}...")
|
125 |
+
audio_path = asyncio.run(generate_speech(part, lang))
|
126 |
if audio_path:
|
127 |
audio_files.append(audio_path)
|
128 |
|
|
|
130 |
logger.error("لم يتم إنشاء أي ملفات صوتية")
|
131 |
return None
|
132 |
|
133 |
+
# إذا كان هناك جزء واحد فقط
|
134 |
if len(audio_files) == 1:
|
135 |
return audio_files[0]
|
136 |
|
137 |
+
# دمج الملفات الصوتية إذا كان هناك أكثر من جزء
|
138 |
from pydub import AudioSegment
|
139 |
|
140 |
+
try:
|
141 |
+
final_audio = AudioSegment.from_mp3(audio_files[0])
|
142 |
+
for audio_file in audio_files[1:]:
|
143 |
+
final_audio += AudioSegment.from_mp3(audio_file)
|
144 |
+
|
145 |
+
final_path = tempfile.mktemp(suffix='.mp3')
|
146 |
+
final_audio.export(final_path, format="mp3")
|
147 |
+
|
148 |
+
# تنظيف الملفات المؤقتة
|
149 |
+
for file in audio_files:
|
150 |
+
try:
|
151 |
+
os.remove(file)
|
152 |
+
except:
|
153 |
+
pass
|
154 |
+
|
155 |
+
progress(1.0, desc="تم إنشاء الصوت بنجاح!")
|
156 |
+
return final_path
|
157 |
|
158 |
+
except Exception as e:
|
159 |
+
logger.error(f"خطأ في دمج الملفات الصوتية: {str(e)}")
|
160 |
+
return None
|
161 |
|
162 |
except Exception as e:
|
163 |
logger.error(f"خطأ في تحويل النص إلى صوت: {str(e)}")
|