File size: 9,077 Bytes
f79c89e
36abef4
70d5a19
d5f394e
 
f79c89e
36abef4
70d5a19
36abef4
f670263
d5f394e
f79c89e
 
 
d5f394e
f79c89e
d5f394e
36abef4
 
 
 
d5f394e
 
f670263
 
 
 
 
 
 
 
 
 
70d5a19
 
36abef4
 
 
 
 
 
 
 
 
 
 
 
 
f670263
36abef4
 
 
 
70d5a19
 
36abef4
 
d5f394e
36abef4
 
 
 
 
 
 
 
 
 
 
f670263
 
 
36abef4
f670263
36abef4
f670263
 
36abef4
f670263
 
 
36abef4
 
 
 
 
f670263
36abef4
 
f79c89e
d5f394e
36abef4
d5f394e
f79c89e
f670263
d5f394e
 
618c56b
d5f394e
f670263
 
 
 
 
 
 
 
 
 
 
 
 
b0e29e7
f670263
 
 
 
 
b0e29e7
f670263
 
 
 
 
d5f394e
 
 
36abef4
 
70d5a19
36abef4
70d5a19
 
 
36abef4
 
 
 
 
18820a6
36abef4
70d5a19
36abef4
70d5a19
36abef4
 
70d5a19
36abef4
 
 
 
70d5a19
 
 
 
36abef4
 
 
 
f79c89e
 
 
 
f670263
 
 
 
 
 
 
618c56b
36abef4
f670263
36abef4
f4ac0b9
 
 
36abef4
f4ac0b9
f670263
f79c89e
 
 
 
36abef4
 
f79c89e
 
 
 
618c56b
f79c89e
 
618c56b
 
f4ac0b9
 
 
 
 
 
 
 
 
 
f79c89e
 
 
 
 
 
 
618c56b
70d5a19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36abef4
70d5a19
 
 
d5f394e
f79c89e
70d5a19
 
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
import os
import asyncio
import tempfile
import gradio as gr
import whisper
import torch
import edge_tts
from pathlib import Path
from moviepy.editor import VideoFileClip
from transformers import MarianMTModel, MarianTokenizer

# تهيئة النماذج
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
whisper_model = whisper.load_model("base")

# قاموس للغات المدعومة
SUPPORTED_LANGUAGES = {
    "ar": {"name": "العربية", "code": "ar-SA"},
    "en": {"name": "English", "code": "en-US"},
    "fr": {"name": "Français", "code": "fr-FR"},
    "es": {"name": "Español", "code": "es-ES"}
}

# قاموس لنماذج الترجمة
TRANSLATION_MODELS = {
    "ar-en": "Helsinki-NLP/opus-mt-ar-en",
    "en-ar": "Helsinki-NLP/opus-mt-en-ar",
    "fr-en": "Helsinki-NLP/opus-mt-fr-en",
    "en-fr": "Helsinki-NLP/opus-mt-en-fr",
    "es-en": "Helsinki-NLP/opus-mt-es-en",
    "en-es": "Helsinki-NLP/opus-mt-en-es"
}

# قاموس لأنواع الأصوات
VOICE_TYPES = {
    "رجل": {
        "ar": "ar-SA-HamedNeural",
        "en": "en-US-ChristopherNeural",
        "fr": "fr-FR-HenriNeural",
        "es": "es-ES-AlvaroNeural"
    },
    "امرأة": {
        "ar": "ar-SA-ZariyahNeural",
        "en": "en-US-JennyNeural",
        "fr": "fr-FR-DeniseNeural",
        "es": "es-ES-ElviraNeural"
    },
    "طفل": {
        "ar": "ar-SA-ZariyahNeural",
        "en": "en-US-JennyNeural",
        "fr": "fr-FR-DeniseNeural",
        "es": "es-ES-ElviraNeural"
    }
}

def extract_audio_from_video(video_path):
    """استخراج الصوت من الفيديو"""
    try:
        video = VideoFileClip(video_path)
        temp_audio_path = tempfile.mktemp(suffix=".mp3")
        video.audio.write_audiofile(temp_audio_path, codec='mp3')
        video.close()
        return temp_audio_path
    except Exception as e:
        raise Exception(f"خطأ في استخراج الصوت من الفيديو: {str(e)}")

def process_media_file(file_path, source_lang):
    """معالجة ملف الوسائط (صوت أو فيديو)"""
    try:
        if file_path is None:
            return "الرجاء تحميل ملف صوتي أو فيديو"
            
        # التحقق من نوع الملف
        if file_path.name.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
            # إذا كان فيديو، استخرج الصوت منه
            audio_path = extract_audio_from_video(file_path.name)
        elif file_path.name.lower().endswith(('.mp3', '.wav', '.m4a')):
            # إذا كان ملف صوتي، استخدمه مباشرة
            audio_path = file_path.name
        else:
            return "نوع الملف غير مدعوم. الأنواع المدعومة هي: MP3, WAV, M4A, MP4, AVI, MOV, MKV"
        
        # تحويل الصوت إلى نص
        result = whisper_model.transcribe(audio_path, language=source_lang)
        
        # حذف الملف المؤقت إذا كان فيديو
        if file_path.name.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
            os.remove(audio_path)
        
        return result["text"]
    except Exception as e:
        return f"خطأ في معالجة الملف: {str(e)}"

def translate_text(text, source_lang, target_lang):
    """ترجمة النص باستخدام MarianMT"""
    if source_lang == target_lang:
        return text
    
    try:
        # إذا كانت اللغة المصدر ليست الإنجليزية، نترجم أولاً إلى الإنجليزية
        if source_lang != "en":
            model_name = TRANSLATION_MODELS[f"{source_lang}-en"]
            model = MarianMTModel.from_pretrained(model_name)
            tokenizer = MarianTokenizer.from_pretrained(model_name)
            
            inputs = tokenizer(text, return_tensors="pt", padding=True)
            translated = model.generate(**inputs)
            text = tokenizer.decode(translated[0], skip_special_tokens=True)
            
            # إذا كانت اللغة الهدف هي الإنجليزية، نتوقف هنا
            if target_lang == "en":
                return text
        
        # ترجمة من الإنجليزية إلى اللغة الهدف
        if target_lang != "en":
            model_name = TRANSLATION_MODELS[f"en-{target_lang}"]
            model = MarianMTModel.from_pretrained(model_name)
            tokenizer = MarianTokenizer.from_pretrained(model_name)
            
            inputs = tokenizer(text, return_tensors="pt", padding=True)
            translated = model.generate(**inputs)
            text = tokenizer.decode(translated[0], skip_special_tokens=True)
        
        return text
    except Exception as e:
        return f"خطأ في الترجمة: {str(e)}"

async def text_to_speech(text, language, voice_type):
    """تحويل النص إلى صوت باستخدام Edge TTS"""
    try:
        # إنشاء مجلد مؤقت للملفات الصوتية
        temp_dir = Path("temp_audio")
        temp_dir.mkdir(exist_ok=True)
        
        # اختيار الصوت المناسب
        voice = VOICE_TYPES[voice_type][language]
        
        # تعديل السرعة والنبرة حسب نوع الصوت
        rate = "+0%" if voice_type != "طفل" else "+15%"
        pitch = "+0Hz" if voice_type == "رجل" else "+10Hz" if voice_type == "امرأة" else "+60Hz"
        
        # إنشاء ملف صوتي مؤقت
        output_file = temp_dir / f"output_{voice_type}_{language}.mp3"
        
        # تكوين كائن communicate
        communicate = edge_tts.Communicate(text, voice, rate=rate, pitch=pitch)
        
        # حفظ الملف الصوتي
        await communicate.save(str(output_file))
        
        return str(output_file)
    
    except Exception as e:
        return f"خطأ في تحويل النص إلى صوت: {str(e)}"

def text_to_speech_wrapper(text, language, voice_type):
    """wrapper function لتشغيل الدالة غير المتزامنة"""
    return asyncio.run(text_to_speech(text, language, voice_type))

# إنشاء واجهة Gradio
with gr.Blocks(title="معالج الصوت والترجمة", theme=gr.themes.Soft()) as demo:
    gr.Markdown("# معالج الصوت والترجمة متعدد اللغات")
    
    with gr.Tab("تحويل الوسائط إلى نص"):
        gr.Markdown("""
        ### الملفات المدعومة:
        - ملفات الصوت: MP3, WAV, M4A
        - ملفات الفيديو: MP4, AVI, MOV, MKV
        """)
        
        with gr.Row():
            media_input = gr.File(
                label="ملف صوتي أو فيديو"
            )
            source_lang = gr.Dropdown(
                choices=list(SUPPORTED_LANGUAGES.keys()),
                value="ar",
                label="لغة الملف"
            )
        
        transcribe_btn = gr.Button("تحويل إلى نص")
        transcribed_text = gr.Textbox(label="النص المستخرج", lines=5)
        
        transcribe_btn.click(
            fn=process_media_file,
            inputs=[media_input, source_lang],
            outputs=transcribed_text
        )
    
    with gr.Tab("ترجمة النص"):
        with gr.Row():
            input_text = gr.Textbox(label="النص المراد ترجمته", lines=5)
            translated_text = gr.Textbox(label="النص المترجم", lines=5)
        
        with gr.Row():
            trans_source_lang = gr.Dropdown(
                choices=list(SUPPORTED_LANGUAGES.keys()),
                value="ar",
                label="اللغة المصدر"
            )
            trans_target_lang = gr.Dropdown(
                choices=list(SUPPORTED_LANGUAGES.keys()),
                value="en",
                label="اللغة الهدف"
            )
        
        translate_btn = gr.Button("ترجمة")
        
        translate_btn.click(
            fn=translate_text,
            inputs=[input_text, trans_source_lang, trans_target_lang],
            outputs=translated_text
        )
    
    with gr.Tab("تحويل النص إلى صوت"):
        with gr.Row():
            tts_text = gr.Textbox(label="النص المراد تحويله إلى صوت", lines=5)
            tts_output = gr.Audio(label="الصوت الناتج")
        
        with gr.Row():
            tts_lang = gr.Dropdown(
                choices=list(SUPPORTED_LANGUAGES.keys()),
                value="ar",
                label="لغة النص"
            )
            voice_type = gr.Radio(
                choices=list(VOICE_TYPES.keys()),
                value="رجل",
                label="نوع الصوت"
            )
        
        tts_btn = gr.Button("تحويل إلى صوت")
        
        tts_btn.click(
            fn=text_to_speech_wrapper,
            inputs=[tts_text, tts_lang, voice_type],
            outputs=tts_output
        )

# تشغيل التطبيق
if __name__ == "__main__":
    demo.launch()