Spaces:
Sleeping
Sleeping
| 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() |