Spaces:
Sleeping
Sleeping
| from google import genai | |
| from google.genai import types | |
| import os | |
| import wave | |
| import tempfile | |
| import gradio as gr | |
| import requests | |
| # ─── 1. Read & validate API key from environment ──────────────────────────────── | |
| api_key = os.getenv("GOOGLE_API_KEY") | |
| eleven_api_key = os.getenv("ELEVEN_API_KEY") | |
| if not eleven_api_key: | |
| raise ValueError("Environment variable 'GOOGLE_API_KEY' غير موجود.") | |
| if not api_key: | |
| raise ValueError("Environment variable 'ELEVEN_API_KEY' غير موجود.") | |
| # ─── 2. Instantiate the new Gen AI client ─────────────────────────────────────── | |
| client = genai.Client(api_key=api_key) | |
| # ─── 3. Helper to write raw PCM bytes into a .wav file ─────────────────────────── | |
| def wave_file(pcm_bytes: bytes, channels: int = 1, rate: int = 24000, sample_width: int = 2) -> str: | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file: | |
| with wave.open(tmp_file.name, "wb") as wf: | |
| wf.setnchannels(channels) | |
| wf.setsampwidth(sample_width) | |
| wf.setframerate(rate) | |
| wf.writeframes(pcm_bytes) | |
| return tmp_file.name | |
| # ─── 4. Attribute descriptions (assumed imported in Arabic) ───────────────────── | |
| tone_descriptions = { | |
| "دافئة ومبهجة": "استخدم نبرة ودودة وجذابة. تحدث بنغمة مبهجة مع ابتسامة طفيفة في الصوت وإيقاع إيجابي يشعر المستمعين بالترحيب والراحة.", | |
| "جدية": "اعتمد أسلوبًا رصينًا وسلطويًا. حافظ على استقرار في النغمة وتحدث بوتيرة معتدلة لإيصال الجدية.", | |
| "متحمسة": "أضف طاقة عالية في كل عبارة. استخدم تغييرات ديناميكية في النغمة مع سرعة في الإلقاء لإيصال الحماس.", | |
| "هادئة": "تحدث بإيقاع ناعم وثابت. حافظ على نغمة لطيفة وتجنب تغييرات مفاجئة لخلق تأثير مريح.", | |
| "حزينة": "اخفض النغمة وقلل السرعة قليلًا. استخدم نغمة حزينة تعكس الأسى أو الشوق.", | |
| "غاضبة": "زد من حدة الصوت واستخدم نغمة حادة. تحدث بسرعة وبحدة لتوصيل الغضب دون أن تكون قاسيًا.", | |
| "ودودة": "استخدم نغمة دافئة ومحاكية للحوار. تحدث بإيقاع طبيعي ونغمة جذابة وكأنك تتحدث مع صديق.", | |
| "متعاطفة": "استخدم نبرة ناعمة وحنونة. قلل الحدة قليلاً وتحدث برقة لتظهر التعاطف.", | |
| "ساخرة": "استخدم نبرة مبالغ فيها قليلاً مع لمسة من التهكم. أبطئ في نهاية بعض الكلمات وغيّر النغمة للإشارة إلى السخرية.", | |
| "رومانسية": "تحدث بنغمة ناعمة ودافئة. استخدم إيقاعًا بطيئًا مع عاطفة واضحة لإيصال الحميمية.", | |
| "واثقة": "حافظ على صوت قوي وواضح. استخدم نغمة ثابتة وإلقاء واضح لعرض الثقة بالنفس.", | |
| "محايدة": "تحدث بنبرة متوازنة دون عاطفة. استخدم وتيرة ثابتة وصوت معتدل.", | |
| "مرحة": "أضف لمسة من الدعابة في الإلقاء. استخدم توقيتًا ذكيًا وتغييرات خفيفة في النغمة لخلق طابع مرح.", | |
| "درامية": "استخدم تعبيرًا قويًا مع تغييرات واسعة في النغمة. قف عند اللحظات المهمة وأبرز الكلمات الرئيسية.", | |
| "مشجعة": "اعتمد نبرة إيجابية وداعمة. استخدم نغمة صاعدة في الكلمات الإيجابية وحافظ على دفء في الإلقاء.", | |
| "فضولية": "تحدث بنغمة فضولية. ارفع النغمة في نهاية الجمل وأضف وقفات خفيفة وكأنك تتساءل.", | |
| "ملهمة": "استخدم نغمة قوية وملهمة. تحدث بإيقاع مقصود مع نغمة تصاعدية في العبارات المحفزة.", | |
| "متوترة": "استخدم إلقاء سريع ومضغوط. تحدث بنغمة حادة وقِف قليلًا لإيصال الإلحاح.", | |
| "كئيبة": "اخفض النغمة وسرعة الحديث. تحدث بإيقاع حزين مع وقفات طويلة تعكس الحزن.", | |
| "متفائلة": "ارفع النغمة في نهاية الجمل. استخدم نغمة دافئة وإلقاء معتدل لإيصال الأمل." | |
| } | |
| tempo_descriptions = { | |
| "بطيء جدًا": "انطق كل كلمة بوضوح وبتأنٍ شديد. حافظ على وتيرة بطيئة لتسهيل الاستيعاب.", | |
| "بطيء": "تحدث بسرعة أبطأ من المعتاد مع وقفات خفيفة بين الجمل لزيادة الوضوح.", | |
| "عادي": "استخدم سرعة الحديث المعتادة (حوالي 120–150 كلمة في الدقيقة). تحدث بشكل طبيعي وكأنك في محادثة يومية.", | |
| "سريع": "زد السرعة إلى حوالي 160–180 كلمة في الدقيقة، مع الحفاظ على الوضوح لنقل الحماس.", | |
| "سريع جدًا": "تحدث بسرعة تفوق 180 كلمة في الدقيقة. انطق بوضوح ولكن بسرعة مناسبة للمعلومات العاجلة.", | |
| "متغير": "غيّر السرعة بين الكلمات: أبطئ في النقاط المهمة وسرّع في العبارات المكررة لخلق تدفق طبيعي." | |
| } | |
| clarity_descriptions = { | |
| "واضح جدًا": "انطق كل صوت بوضوح تام. حافظ على سرعة معتدلة وتجنب التمتمة أو السهو.", | |
| "واضح": "استخدم وضوحًا عاليًا في النطق مع بعض الانسيابية الطبيعية في الحديث.", | |
| "متوسط": "استخدم وضوحًا تقليديًا كما في الحديث اليومي. يمكن أن تمتزج بعض الحروف بشكل طبيعي.", | |
| "غير واضح قليلًا": "استخدم نطقًا غير رسمي مع بعض الاسترخاء في الحروف أو إسقاطها بشكل بسيط.", | |
| "ناعم ولطيف": "اخفض مستوى الصوت وتحدث بلطف. انطق الكلمات بهدوء لإضفاء طابع حميمي.", | |
| "متمتم": "انطق الكلمات بصوت منخفض مع وضوح أقل. يمكن أن تمتزج الكلمات ببعضها.", | |
| "حاد وواضح": "أبرز الحروف الساكنة بقوة مع نطق دقيق. استخدم نغمة واضحة وقوية.", | |
| "بنبرة هوائية": "أضف بعض الهواء في الصوت أثناء النطق. تحدث بلطف وبهمس خفيف.", | |
| "بهمس": "تحدث بصوت منخفض جدًا مع إغلاق جزئي للأوتار الصوتية. يصلح للحديث السري أو القريب جدًا.", | |
| "مرتفع وواضح": "استخدم صوتًا قويًا وواضحًا مع نبرة بارزة. نطق كل كلمة بثقة وحزم." | |
| } | |
| style_descriptions = { | |
| "تحفيزي وغير رسمي": "تحدث بأسلوب ودي ومشجع. استخدم لغة غير رسمية مع نبرة إيجابية ملهمة.", | |
| "رسمي": "اعتمد لغة مهنية ومنظمة. تحدث بنبرة محترمة دون استخدام العامية أو الاختصارات.", | |
| "روائي": "استخدم أسلوب قصصي مع تغييرات في النغمة وتوقفات درامية لجذب المستمع.", | |
| "مهني": "تحدث بلغة عمل واضحة ومحايدة. حافظ على نغمة واثقة دون عاطفة زائدة.", | |
| "حواري": "اعتمد أسلوبًا عفويًا وغير رسمي. تحدث كما لو كنت في محادثة ودية.", | |
| "أكاديمي": "استخدم لغة دقيقة ومصطلحات واضحة. تحدث بأسلوب محاضرة هادئ ومركز.", | |
| "إقناعي": "تحدث بثقة وحماس. أبرز النقاط المهمة بنغمة صاعدة وأسلوب مقنع.", | |
| "وصفي": "استخدم نغمة توضيحية مع إبراز الصفات والكلمات الحسية.", | |
| "تفسيري": "اعتمد أسلوبًا تعليميًا واضحًا. قسم المعلومات إلى خطوات وتحدث بتأنٍ.", | |
| "نقاشي": "استخدم نغمة قوية ومتحدية. زد من سرعة الحديث أثناء الردود وشدد على النقاط الجدلية.", | |
| "شعري": "تحدث بإيقاع لحني وجمالي. أطِل في نطق الحروف وامنح الحديث طابعًا غنائيًا.", | |
| "نشرة إخبارية": "استخدم نغمة محايدة وواضحة. تحدث بوضوح وبدون عاطفة، كما في الأخبار.", | |
| "تعليمي": "تحدث بأسلوب منظم وواضح. استخدم توقفات قصيرة بين الخطوات للمساعدة في الفهم.", | |
| "سرد خارجي (شخص ثالث)": "تحدث كراوٍ خارجي. غيّر النغمة للحوار وابقَ على وتيرة متزنة.", | |
| "شهادة شخصية": "استخدم نغمة صادقة وشخصية. تحدث وكأنك تروي تجربة حقيقية.", | |
| "أسلوب مقابلة": "قلد نمط سؤال وجواب. ارفع نغمة السؤال، ثم انزلها في الجواب مع توقفات طبيعية.", | |
| "مرِح وعفوي": "استخدم نبرة مرحة ومبالغ فيها قليلًا. غير السرعة والنغمة لإضافة حس فكاهي.", | |
| "تقني ودقيق": "استخدم نبرة حيادية ومصطلحات دقيقة. تحدث بثبات وبدون تغييرات كبيرة في النغمة.", | |
| "فلسفي": "استخدم نبرة تأملية وهادئة. تحدث بإيقاع بطيء وتوقفات طويلة لإيصال العمق الفكري.", | |
| "روحي أو ديني": "استخدم نغمة مطمئنة ومحترمة. تحدث بلطف واحترام لإيصال الشعور الروحي." | |
| } | |
| # accent_descriptions = { | |
| # "العربية الفصحى": ( | |
| # "نطق رسمي وواضح، مع الالتزام الكامل بعلامات التشكيل مثل الضم والفتح والكسر. " | |
| # "الحروف المفخمة مثل ص، ط، ق تُنطق بقوة ووضوح، دون تليين أو اختصار. " | |
| # "مخارج الحروف دقيقة ومحافظة، خاصة في العين، الحاء، الغين، والخاء. " | |
| # "الإيقاع متزن ومعتدل، النبرة محايدة وجادة، تشبه أداء نشرات الأخبار أو تلاوة القرآن. " | |
| # "يُتجنب تماماً استخدام التعابير المحكية أو العامية." | |
| # ), | |
| # "المصرية": ( | |
| # "نطق الجيم ناعم ومفتوح، أقرب إلى 'zh' (كما في كلمة 'جميل'). " | |
| # "القاف تُنطق غالباً همزة، خاصة في وسط الكلمة: 'قال' تُصبح 'آل'. " | |
| # "الإيقاع مرن ومتنوع، مع نبرة صوت صاعدة قليلاً في نهاية الجمل الاستفهامية أو التعجبية. " | |
| # "نبرة الصوت ودودة وعفوية، تميل إلى الفكاهة والخفة في الأداء. " | |
| # "التلفظ سريع نسبياً، مع سلاسة ومدّ بسيط أحيانًا في النهايات." | |
| # ), | |
| # "الشامية": ( | |
| # "القاف غالبًا ما تتحول إلى همزة ناعمة: 'قلب' تُنطق 'ألب'. " | |
| # "الراء تُنطق بخفة دون تفخيم، وتظهر بوضوح في نهايات الكلمات. " | |
| # "يتم تمطيط الحروف الصوتية في كلمات مثل 'كتير'، مع مدّ خفيف يدل على اللين والهدوء. " | |
| # "نبرة الصوت هادئة، رقيقة، وتميل للانخفاض في نهاية الجملة. " | |
| # "الإيقاع متوازن وناعم، مع تسلسل موسيقي بسيط يعطي إحساسًا بالارتياح والود." | |
| # ), | |
| # "السورية": ( | |
| # "نطق القاف كهمزة واضح، خاصة في المحادثة اليومية: 'قال' تُلفظ 'آل'. " | |
| # "النبرة مستقرة ودافئة، مع بعض التمطيط اللطيف في كلمات مثل 'تمام التمام'. " | |
| # "الصوت يُستخدم بنغمة معتدلة تميل للهدوء، دون تغييرات حادة في طبقة الصوت. " | |
| # "الإيقاع سلس، مريح، ويظهر فيه الاتزان في تشكيل الجمل والنبرات. " | |
| # "المقاطع تُلفظ بشكل واضح لكن غير مشدد، ما يعطي انطباعاً بالبساطة والود." | |
| # ), | |
| # "اللبنانية": ( | |
| # "لهجة موسيقية بإيقاع صاعد وهابط، يتغير حسب العاطفة أو نوع الجملة. " | |
| # "القاف تُخفف إلى همزة، والنطق يكون ناعمًا وسلسًا. " | |
| # "الراء تُنطق بخفة، وأحيانًا بترجيع بسيط يجعلها مميزة في الأداء. " | |
| # "سرعة الكلام متوسطة إلى سريعة، مع وضوح المقاطع وإبراز نهايات الجمل بتغييرات لحنية ملحوظة. " | |
| # "نبرة الصوت ناعمة، عاطفية، ومعبّرة، ما يجعلها جذابة في الأداء الصوتي وتناسب النصوص الحوارية أو العاطفية." | |
| # ), | |
| # "الفلسطينية": ( | |
| # "نطق واضح ودقيق لمخارج الحروف، مع ميل لتخفيف القاف إلى همزة في الكلام العامّي. " | |
| # "الراء تُفخم أحيانًا بشكل طفيف، خاصة عند التأكيد أو الانفعال. " | |
| # "الإيقاع متزن وجاد نسبياً، مع نبرة مستقرة تميل إلى الثبات في نهاية الجمل. " | |
| # "النغمة الصوتية واضحة ومباشرة، وتُظهر درجة من الجدية والانضباط في الأداء. " | |
| # "الكلمات تُلفظ بطريقة كاملة مع وضوح التشكيل عند الحاجة دون مبالغة." | |
| # ), | |
| # "الأردنية": ( | |
| # "قريبة من الفلسطينية لكن بنبرة أكثر رسمية وثباتاً. " | |
| # "القاف غالبًا تُفخم وتُلفظ بوضوح، بخلاف اللهجات الشامية الأخرى. " | |
| # "نبرة الصوت مستقيمة، جدية، وفيها نوع من الوقار والهدوء، مع استخدام نغمة معتدلة في جميع الجمل. " | |
| # "الإيقاع منتظم ومتحكم به، دون مبالغة في التغيير اللحني، ويُظهر وضوحًا في النطق والحزم في الأداء. " | |
| # "مثالية للنصوص الرسمية أو الخطاب التقريري بأسلوب عامّي خفيف." | |
| # ), | |
| # "الخليجية": ( | |
| # "القاف تُنطق بوضوح ومفخمة، مما يعطي طابعًا قويًا للنبرة. " | |
| # "الذال تتحول أحيانًا إلى د حسب السياق: 'ذهب' → 'دَهَب'. " | |
| # "الإيقاع بطيء نسبياً ومستقر، مع نغمة رزينة ونبرة منخفضة. " | |
| # "الصوت يميل إلى الرسمية والاحترام، وتُلفظ الكلمات بطريقة محافظة مع استخدام تعبيرات محلية أصيلة. " | |
| # "النبرة العامة رصينة وتقليدية، تعكس شخصية هادئة وواثقة." | |
| # ), | |
| # "السعودية": ( | |
| # "تشمل لهجتين أساسيتين: نجدية (وسطى) وحجازية (غربية)، وتميل بشكل عام إلى نطق القاف بوضوح. " | |
| # "نبرة الصوت واضحة ومفهومة، وتستخدم طبقة متوسطة إلى منخفضة، مع نغمة ترحيبية مألوفة. " | |
| # "الإيقاع معتدل، لا هو سريع ولا بطيء، مع تغير طفيف في النبرة في الجمل الطويلة. " | |
| # "اللهجة تُظهر رسمية معتدلة، ويمكن استخدامها بمرونة سواء في الحديث العفوي أو النص الرسمي." | |
| # ), | |
| # "الإماراتية": ( | |
| # "لهجة محافظة وناعمة، تُستخدم فيها القاف بوضوح دون تليين. " | |
| # "الكلمات تُلفظ برتابة موسيقية خفيفة، والنبرة الصوتية ثابتة وهادئة. " | |
| # "الإيقاع بطيء إلى معتدل، مع تفخيم خفيف لبعض الحروف مثل الراء والصاد حسب السياق. " | |
| # "تُستخدم طبقة صوت متوسطة، ولا يُكثر من تغيير النغمة، مما يعطي الأداء طابعًا وقورًا وبسيطًا. " | |
| # "مناسبة لنصوص فيها خصوصية ثقافية أو طابع رسمي تقليدي." | |
| # ), | |
| # "الكويتية": ( | |
| # "نطق مميز وواضح خاصة في القاف والصاد، مع ميل طفيف للتفخيم. " | |
| # "القاف تُلفظ غالبًا بقوة في بداية الكلمة، وتُظهر جديّة في الأداء. " | |
| # "الإيقاع متوسط إلى بطيء، مع استخدام نغمة مرحة أو ودودة خصوصًا في الجمل التفاعلية. " | |
| # "الصوت يحمل مزيجًا من الرسمية والعفوية، مما يجعله مناسبًا للمواقف اليومية أو الخطابات شبه الرسمية. " | |
| # "الميل لنغمة صاعدة في نهاية الجملة يُضفي على الأداء طابعًا حيًا دون مبالغة." | |
| # ), | |
| # "القطرية": ( | |
| # "نغمة صوت أعمق قليلاً من الإماراتية، مع نطق واضح للحروف، خصوصًا الذال والثاء. " | |
| # "القاف تُلفظ مفخمة وبشكل تقليدي دون تليين. " | |
| # "الإيقاع بطيء نسبياً، والكلام يتم بنبرة هادئة ورزينة. " | |
| # "تُستخدم طبقات صوت منخفضة تعكس الوقار، ويُظهر الأداء وضوحًا في مخارج الحروف مع تجنب السرعة. " | |
| # "مثالية لنصوص تُظهر الاحترام والرسمية والبُعد الثقافي المحلي." | |
| # ), | |
| # "البحرينية": ( | |
| # "لهجة موسيقية بطابع خاص، تتغير فيها طبقة الصوت بسلاسة، مع نغمة خفيفة تُظهر الارتياح والتلقائية. " | |
| # "القاف تُلفظ أحياناً 'چ'، خاصة في اللهجة الشعبية. " | |
| # "الإيقاع متنوع، ويتراوح بين السرعة في الجمل الحماسية والبطء في العبارات التفسيرية. " | |
| # "نبرة الصوت مرنة، وتُظهر دفئاً اجتماعياً وودّياً، مناسبة للنصوص الحوارية والعاطفية. " | |
| # "الأداء يُفضّل فيه بعض التمطيط الخفيف في نهايات الكلمات للتعبير." | |
| # ), | |
| # "العمانية": ( | |
| # "نبرة محافظة ومتماسكة، تعتمد على وضوح مخارج الحروف دون مبالغة. " | |
| # "القاف والثاء تُلفظ بوضوح تام، مما يعطي اللهجة طابعاً فصيحاً نسبياً. " | |
| # "الإيقاع بطيء إلى معتدل، مع طبقة صوت منخفضة ومتوازنة. " | |
| # "الصوت يُستخدم بوقار، دون تغييرات لحنية حادة، ما يضيف هيبة واستقراراً للنبرة العامة. " | |
| # "مناسبة للحوارات الرسمية أو المواد ذات الطابع التراثي والوقور." | |
| # ), | |
| # "اليمنية": ( | |
| # "لهجة صنعانية أو تعزية بنغمة صوت مرتفعة قليلاً مقارنة بالخليجية، مع نطق واضح ومفخّم للقاف. " | |
| # "النغمة ديناميكية وتميل للتغيير السريع، مما يُضفي نشاطاً وحيوية على الأداء. " | |
| # "الإيقاع سريع نسبياً، والكلمات غالباً تُلفظ بكثافة وتتابع، مع تكرار لبعض التعابير لزيادة التأكيد. " | |
| # "الصوت يظهر فيه حماس ومباشرة، ومناسب للحوارات الحيّة أو السرد القصصي الشعبي. " | |
| # "المقاطع تُنطق كاملة دون حذف، رغم سرعة الأداء، مما يجعلها فصيحة بطريقتها الخاصة." | |
| # ), | |
| # "العراقية": ( | |
| # "القاف تُلفظ 'گ' بوضوح، وتُعطي الكلمة نغمة قوية وعميقة. " | |
| # "الأداء الصوتي غني بالتنويع، مع تغييرات نغمية واضحة حسب الانفعال والمعنى. " | |
| # "نغمة الصوت فيها دفء عاطفي عند الحديث الودي، وقوة درامية في الجمل الجادة. " | |
| # "الإيقاع متوسط السرعة، ويميل إلى استخدام تعبيرات صوتية لإيصال المشاعر. " | |
| # "اللهجة مناسبة جداً للنصوص التي تتطلب تعبيرًا غنيًا وحضورًا صوتيًا قويًا." | |
| # ), | |
| # "المغاربية": ( | |
| # "لهجة سريعة الإيقاع، تتداخل فيها عناصر من الفرنسية والأمازيغية، وتُلفظ بعض الحروف مثل القاف كـ 'گ'. " | |
| # "الجمل قصيرة وسريعة، مع نغمة صوت صاخبة ونشطة. " | |
| # "النطق يميل إلى اختزال المقاطع، ما يجعل الأداء سريعًا ومباشرًا. " | |
| # "يُستخدم الكثير من الكلمات المستعارة ونطقها بأسلوب محلي. " | |
| # "النبرة العامة قوية، ديناميكية، وغير تقليدية، ومناسبة لنصوص ترفيهية أو شبابية." | |
| # ), | |
| # "المغربية": ( | |
| # "لهجة فرعية من المغاربية، لكن أسرع إيقاعًا وأكثر حيوية. " | |
| # "القاف تُنطق 'گ' غالبًا، وتُختصر بعض الحروف أو تُدمج داخل الجملة. " | |
| # "الإيقاع سريع جداً، مع نغمة صوت قوية وتعبيرية. " | |
| # "يُكثر من الكلمات المختصرة، وتُظهر النبرة استقلالية واختزالًا في التوصيل. " | |
| # "مثالية للمواقف اليومية أو السياقات الحية، لكن تتطلب تبسيطًا في النص المكتوب كي يسهل تحويله إلى كلام مسموع بوضوح." | |
| # ), | |
| # "الجزائرية": ( | |
| # "تتضمن الكثير من الكلمات الفرنسية، مع نغمة صوتية سريعة وجدية. " | |
| # "الأداء الصوتي غالبًا مباشر وقوي، مع إيقاع متقطع. " | |
| # "الحروف تُنطق بجفاف نسبي، والنغمة تميل إلى الرسمية والحدة في بعض الأحيان. " | |
| # "النبرة العامة لا تتغير كثيراً، ما يضيف طابعًا حازمًا للأداء. " | |
| # "مناسبة للنصوص ذات الطابع الرسمي أو الخطابي، حيث يُراد إيصال الجدية والانضباط." | |
| # ), | |
| # "السودانية": ( | |
| # "نغمة صوت مريحة ومتمهلة، مع ميل واضح لتمطيط الحروف الصوتية. " | |
| # "القاف تُنطق أحياناً 'غ' في الكلام الشعبي، مما يضفي طابعاً خاصاً ومميزاً. " | |
| # "الإيقاع بطيء نسبياً، مع استخدام صوت هادئ ومنخفض النغمة. " | |
| # "الأداء الصوتي يميل إلى الهدوء والسلاسة، ما يجعله مناسباً للسرد أو التعليم أو الرسائل الودية. " | |
| # "اللهجة تحمل طابعاً دافئاً وبسيطاً، يوصل المعنى دون تعقيد أو تكلف." | |
| # ), | |
| # "الحجازية": ( | |
| # "نطق القاف واضح وصريح، دون تفخيم مبالغ فيه، ويُحافظ على فصاحته نسبياً. " | |
| # "النغمة رخيمة ومتزنة، تُستخدم طبقات صوت مريحة مع وضوح في مخارج الحروف. " | |
| # "الإيقاع معتدل، لا يميل للسرعة أو البطء، مع تغييرات خفيفة في النبرة حسب العاطفة. " | |
| # "اللهجة تتميّز بالودّ والتهذيب، مع نبرة ترحيبية مألوفة. " | |
| # "مناسبة للحوارات الاجتماعية والروايات الصوتية الهادئة." | |
| # ), | |
| # "النجدية": ( | |
| # "نغمة رزينة وواضحة، تتميز بثبات طبقة الصوت وقوة نطق القاف والمفخّمات. " | |
| # "النبرة رسمية قليلاً، وتعكس طابعًا تقليديًا محترمًا في الأداء الصوتي. " | |
| # "الإيقاع ثابت ومتوازن، دون مبالغة في التنغيم أو التمطيط. " | |
| # "تُستخدم للخطابات الجادة أو النصوص التعليمية والشرعية بأسلوب شعبي. " | |
| # "اللهجة مناسبة للنصوص التي تتطلب وضوحًا وقوة في التوصيل." | |
| # ), | |
| # "الحضرمية": ( | |
| # "نطق القاف يتحول إلى 'گ'، مع طبقة صوت منخفضة وهادئة. " | |
| # "نغمة مميزة تميل إلى البطء والتأني، وتعكس طابعًا وقورًا ومحافظًا. " | |
| # "الأداء الصوتي سلس، والكلمات تُنطق بشكل كامل دون اختزال. " | |
| # "الإيقاع بطيء نسبيًا، مما يناسب النصوص الروحية أو السردية الهادئة. " | |
| # "اللهجة تُضفي شعورًا بالطمأنينة والتواضع في النبرة." | |
| # ), | |
| # "الحسانية": ( | |
| # "لهجة مميزة تُستخدم فيها نغمة منخفضة ومتمهلة، مع تمديد واضح للأصوات الطويلة. " | |
| # "الكلمات تُنطق ببطء ووضوح، مع نبرة صوت معتدلة وثابتة. " | |
| # "القاف تُلفظ بوضوح، دون تليين، مع استخدام نبرة تقليدية فصيحة في بعض السياقات. " | |
| # "الإيقاع هادئ، يُناسب النصوص التعليمية أو الأدبية. " | |
| # "اللهجة تُحافظ على الإرث العربي الأصيل في طريقة النطق." | |
| # ), | |
| # "العربية التشادية": ( | |
| # "نطق بسيط ومباشر، يُقارب الفصحى مع ميل للوضوح والسهولة في الكلمات. " | |
| # "الأداء الصوتي مبسّط وسلس، مع غياب التعقيدات النغمية أو التمطيط. " | |
| # "الإيقاع معتدل، مناسب للمواد التوعوية أو التعليمية. " | |
| # "الحروف تُنطق بوضوح، ولا يتم اختصارها كثيرًا، مع تجنّب المفردات العامّية الثقيلة. " | |
| # "النبرة الصوتية حيادية، مما يجعلها سهلة الفهم لمجموعة واسعة من المستمعين." | |
| # ), | |
| # "عربية جوبا": ( | |
| # "لهجة مبسطة مع الكثير من الكلمات المختصرة، تتأثر بالإنجليزية واللغات المحلية. " | |
| # "نغمة مرحة وخفيفة، مع سرعة واضحة في الأداء. " | |
| # "الكلمات تُلفظ بأسلوب مباشر وغير رسمي، وغالباً تُختصر المقاطع. " | |
| # "الإيقاع سريع نسبياً، مما يعطي طابعًا نشيطًا ومناسبًا للمواقف اليومية أو الشبابية. " | |
| # "النبرة الصوتية ودودة وتلقائية، ما يُناسب النصوص الخفيفة أو الحوارية." | |
| # ), | |
| # "المالطية": ( | |
| # "مزيج فريد بين العربية القديمة والإيطالية، مع نطق متأثر بالصوت الأوروبي. " | |
| # "القاف تُخفف غالبًا، والحروف الصوتية تُلفظ بأسلوب إيطالي واضح. " | |
| # "الإيقاع سريع إلى متوسط، والنغمة تُظهر حيوية وتغيّر لحني متكرر. " | |
| # "الصوت ديناميكي، يُظهر تأثرًا بالثقافة اللاتينية، مع وضوح في نهاية الجمل. " | |
| # "مناسبة للنصوص الحركية، السياحية، أو التفاعلية." | |
| # ), | |
| # } | |
| accent_descriptions = { | |
| "العربية الفصحى": "استخدم النطق بالعربية الفصحى.", | |
| "المصرية": "استخدم اللهجة المصرية.", | |
| "الشامية": "استخدم اللهجة الشامية.", | |
| "السورية": "استخدم اللهجة السورية الشامية.", | |
| "اللبنانية": "استخدم اللهجة اللبنانية.", | |
| "الفلسطينية": "استخدم اللهجة الفلسطينية.", | |
| "الأردنية": "استخدم اللهجة الأردنية.", | |
| "الخليجية": "استخدم اللهجة الخليجية.", | |
| "السعودية": "استخدم اللهجة السعودية.", | |
| "الإماراتية": "استخدم اللهجة الإماراتية.", | |
| "الكويتية": "استخدم اللهجة الكويتية.", | |
| "القطرية": "استخدم اللهجة القطرية.", | |
| "البحرينية": "استخدم اللهجة البحرينية.", | |
| "العمانية": "استخدم اللهجة العمانية.", | |
| "اليمنية": "استخدم اللهجة اليمنية.", | |
| "العراقية": "استخدم اللهجة العراقية.", | |
| "المغاربية": "استخدم اللهجة المغاربية.", | |
| "المغربية": "استخدم اللهجة المغربية.", | |
| "الجزائرية": "استخدم اللهجة الجزائرية.", | |
| "السودانية": "استخدم اللهجة السودانية.", | |
| "الحجازية": "استخدم اللهجة الحجازية.", | |
| "النجدية": "استخدم اللهجة النجدية.", | |
| "الحضرمية": "استخدم اللهجة الحضرمية.", | |
| "الحسانية": "استخدم اللهجة الحسانية.", | |
| "العربية التشادية": "استخدم اللهجة التشادية.", | |
| "عربية جوبا": "استخدم لهجة جوبا.", | |
| "المالطية": "استخدم اللهجة المالطية." | |
| } | |
| voice_name_map = { | |
| "سارة": "Achernar", | |
| "سامي": "Achird", | |
| "كريم": "Algenib", | |
| "فهد": "Algieba", | |
| "يوسف": "Alnilam", | |
| "رنا": "Aoede", | |
| "نورا": "Autonoe", | |
| "جنى": "Callirrhoe", | |
| "بدر": "Charon", | |
| "فرح": "Despina", | |
| "حاتم": "Enceladus", | |
| "أنس": "Fenrir", | |
| "هالة": "Gacrux", | |
| "مالك": "Iapetus", | |
| "إياد": "Orus", | |
| "راكان": "Puck", | |
| "هيثم": "Sadachbia", | |
| "نادر": "Sadaltager", | |
| "وليد": "Schedar", | |
| "سمية": "Zephyr", | |
| "دعاء": "Erinome", | |
| "أميرة": "Laomedeia", | |
| "بتول": "Kore", | |
| "زينب": "Leda", | |
| "باسل": "Pulcherrima", | |
| "حسام": "Umbriel", | |
| "ياسمين": "Vindemiatrix", | |
| "طارق": "Zubenelgenubi", | |
| "لينا": "Sulafat", | |
| "مازن": "Rasalgethi" | |
| } | |
| # ─── Additional helper function ────────────────────────────────────────────── | |
| def convert_text_to_dialect(text: str, accent: str) -> str: | |
| """Uses Gemini 2.0 Flash model to rewrite the text into a specified dialect.""" | |
| prompt = f""" | |
| قم بتحويل النص التالي إلى لهجة {accent} مع الحفاظ على نفس المعنى وعدد الجمل. | |
| عدّل فقط الكلمات والتعابير لتتناسب مع اللهجة المطلوبة. | |
| الرجاء إرسال النص الناتج فقط دون أي شروحات أو تعليقات إضافية. | |
| النص: | |
| {text} | |
| """ | |
| response = client.models.generate_content( | |
| model="gemini-2.0-flash", | |
| contents=[prompt], | |
| config=types.GenerateContentConfig( | |
| temperature=0.3, | |
| max_output_tokens=1000 | |
| ) | |
| ) | |
| return response.text.strip() | |
| # ─── 5. Main TTS-generation function ───────────────────────────────────────────── | |
| def generate_audio( | |
| model_choice: str, | |
| language: str, | |
| accent: str, | |
| tone: str, | |
| speed: str, | |
| clarity: str, | |
| style: str, | |
| convert_method: str, | |
| speaker_mode: str, | |
| speaker1_name: str, | |
| speaker1_voice: str, | |
| speaker2_name: str, | |
| speaker2_voice: str, | |
| text: str, | |
| voice_name: str, | |
| premium_voice_id: str, | |
| extra_prompt: str, | |
| ) -> tuple: | |
| tone_desc = tone_descriptions.get(tone, tone) | |
| speed_desc = tempo_descriptions.get(speed, speed) | |
| clarity_desc = clarity_descriptions.get(clarity, clarity) | |
| style_desc = style_descriptions.get(style, style) | |
| accent_desc = accent_descriptions.get(accent, f"استخدم لهجة {accent} الطبيعية.") | |
| header = f""" | |
| [اللغة]: تحدث بـ {language}، وتأكد من أن جميع التعبيرات والمفردات تتماشى مع الاستخدام الطبيعي للغة. | |
| [نبرة الصوت]: {tone_desc} | |
| [سرعة الكلام]: {speed_desc} | |
| [الوضوح]: {clarity_desc} | |
| [الأسلوب]: {style_desc} | |
| [اللهجة]: {accent_desc} | |
| """.strip() | |
| conversion_instruction = "" | |
| converted_text = text | |
| if convert_method == "تحويل بسيط": | |
| conversion_instruction = ( | |
| f"[تحويل]: قم فقط بتعديل المفردات والتعابير لتتناسب مع اللهجة {accent} " | |
| "دون تغيير المعنى أو حذف/إضافة جمل." | |
| ) | |
| if convert_method == "تحويل متطور": | |
| converted_text = convert_text_to_dialect(text, accent) | |
| speaker_instruction = "" | |
| if speaker_mode == "عدة أصوات": | |
| speaker_instruction = ( | |
| "[تعليمات]: لا تنطق أسماء المتحدثين (مثل: خالد، سارة) أثناء قراءة النص. " | |
| "استخدم صوت كل متحدث حسب اسمه فقط." | |
| ) | |
| if convert_method == "تحويل بسيط": | |
| text_instruction = ( | |
| "[المهمة]: اقرأ النص التالي مع تطبيق تعليمات التحويل البسيط مع الالتزام بالسمات المذكورة أعلاه. " | |
| "لا تقرأ التعليمات. " | |
| "توقف برهة عند علامات الترقيم (مثل الفاصلة، النقطة، النقطتين)، " | |
| "وتوقف تام عند الانتقال إلى سطر جديد كما يفعل القارئ الطبيعي." | |
| ) | |
| else: | |
| text_instruction = ( | |
| "[المهمة]: اقرأ النص التالي فقط كما هو مكتوب، مع الالتزام بالسمات المذكورة أعلاه. " | |
| "لا تقرأ التعليمات، ولا تقم بتعديله أو إعادة تفسيره. " | |
| "توقف برهة عند علامات الترقيم (مثل الفاصلة، النقطة، النقطتين)، " | |
| "وتوقف تام عند الانتقال إلى سطر جديد كما يفعل القارئ الطبيعي." | |
| ) | |
| full_prompt = f"{header}" | |
| if conversion_instruction: | |
| full_prompt += f"\n\n{conversion_instruction}" | |
| if speaker_instruction: | |
| full_prompt += f"\n\n{speaker_instruction}" | |
| if extra_prompt.strip(): | |
| full_prompt += f"\n[ملاحظات إضافية]: {extra_prompt.strip()}" | |
| full_prompt += f"\n\n{text_instruction}\n\n[النص]:\n{converted_text}" | |
| if speaker_mode == "عدة أصوات": | |
| speaker1_real_voice = voice_name_map.get(speaker1_voice, speaker1_voice) | |
| speaker2_real_voice = voice_name_map.get(speaker2_voice, speaker2_voice) | |
| response = client.models.generate_content( | |
| model=model_choice, | |
| contents=full_prompt, | |
| config=types.GenerateContentConfig( | |
| response_modalities=["AUDIO"], | |
| speech_config=types.SpeechConfig( | |
| multi_speaker_voice_config=types.MultiSpeakerVoiceConfig( | |
| speaker_voice_configs=[ | |
| types.SpeakerVoiceConfig( | |
| speaker=speaker1_name.strip(), | |
| voice_config=types.VoiceConfig( | |
| prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=speaker1_real_voice) | |
| ) | |
| ), | |
| types.SpeakerVoiceConfig( | |
| speaker=speaker2_name.strip(), | |
| voice_config=types.VoiceConfig( | |
| prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=speaker2_real_voice) | |
| ) | |
| ) | |
| ] | |
| ) | |
| ), | |
| ) | |
| ) | |
| else: | |
| voice_name_real = voice_name_map.get(voice_name, voice_name) | |
| response = client.models.generate_content( | |
| model=model_choice, | |
| contents=full_prompt, | |
| config=types.GenerateContentConfig( | |
| response_modalities=["AUDIO"], | |
| speech_config=types.SpeechConfig( | |
| voice_config=types.VoiceConfig( | |
| prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=voice_name_real) | |
| ) | |
| ), | |
| ), | |
| ) | |
| pcm_data = response.candidates[0].content.parts[0].inline_data.data | |
| wav_path = wave_file(pcm_data) | |
| if premium_voice_id == "": | |
| return wav_path, converted_text if convert_method == "تحويل متطور" else "" | |
| else: | |
| url = f"https://api.elevenlabs.io/v1/speech-to-speech/{premium_voice_id}" | |
| headers = {"xi-api-key": eleven_api_key} | |
| with open(wav_path, "rb") as audio_file: | |
| files = {"audio": audio_file} | |
| data = {"model_id": "eleven_multilingual_sts_v2", "output_format": "mp3_44100_128"} | |
| response = requests.post(url, headers=headers, files=files, data=data) | |
| if response.ok: | |
| with open("output.mp3", "wb") as f: | |
| f.write(response.content) | |
| return "output.mp3", converted_text if convert_method == "تحويل متطور" else "" | |
| else: | |
| return wav_path, converted_text if convert_method == "تحويل متطور" else "" | |
| # ─── 6. Gradio UI (Arabic) ────────────────────────────────────────────────────── | |
| model_choices = ["gemini-2.5-flash-preview-tts", "gemini-2.5-pro-preview-tts"] | |
| language_choices = ["العربية", "الإنجليزية", "الفرنسية"] | |
| tone_choices = list(tone_descriptions.keys()) | |
| speed_choices = list(tempo_descriptions.keys()) | |
| clarity_choices = list(clarity_descriptions.keys()) | |
| style_choices = list(style_descriptions.keys()) | |
| voice_name_choices = list(voice_name_map.keys()) | |
| accent_choices = list(accent_descriptions.keys()) | |
| with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("## 🎤 مولد الصوت باستخدام Gemini") | |
| with gr.Row(): | |
| with gr.Column(): | |
| model_choice = gr.Dropdown(model_choices, value=model_choices[0], label="نموذج Gemini") | |
| language = gr.Dropdown(language_choices, value=language_choices[0], label="اللغة") | |
| accent = gr.Dropdown(accent_choices, value=accent_choices[0], label="اللهجة") | |
| convert_method = gr.Dropdown( | |
| label="طريقة تحويل النص إلى اللهجة", | |
| choices=["بدون تحويل", "تحويل بسيط", "تحويل متطور"], | |
| value="بدون تحويل" | |
| ) | |
| tone = gr.Dropdown(tone_choices, value=tone_choices[0], label="النبرة / الشعور") | |
| speed = gr.Dropdown(speed_choices, value=speed_choices[2], label="سرعة الكلام") | |
| clarity = gr.Dropdown(clarity_choices, value=clarity_choices[1], label="وضوح الصوت") | |
| style = gr.Dropdown(style_choices, value=style_choices[0], label="الأسلوب") | |
| speaker_mode = gr.Radio(["صوت واحد", "عدة أصوات"], value="صوت واحد", label="وضع المتحدثين") | |
| with gr.Row(visible=True) as single_speaker_input: | |
| voice_name = gr.Dropdown(voice_name_choices, value=voice_name_choices[0], label="اختر اسم المتحدث (في حالة صوت واحد)") | |
| with gr.Row(visible=False) as speaker_inputs: | |
| with gr.Column(): | |
| speaker1_name = gr.Textbox(label="اسم المتحدث الأول", value="سارة") | |
| speaker1_voice = gr.Dropdown(voice_name_choices, value=voice_name_choices[23], label="صوت المتحدث الأول") | |
| with gr.Column(): | |
| speaker2_name = gr.Textbox(label="اسم المتحدث الثاني", value="خالد") | |
| speaker2_voice = gr.Dropdown(voice_name_choices, value=voice_name_choices[24], label="صوت المتحدث الثاني") | |
| premium_voice_id = gr.Textbox(label="معرف الصوت المميز (اختياري)") | |
| extra_prompt = gr.Textbox(label="تعليمات إضافية للنموذج (اختياري)", lines=2) | |
| with gr.Column(): | |
| text = gr.Textbox( | |
| label="النص المطلوب نطقه", | |
| lines=6 | |
| ) | |
| converted_output_text = gr.Textbox( | |
| label="النص بعد تحويله للهجة المطلوبة", | |
| lines=6, | |
| visible=False | |
| ) | |
| output = gr.Audio(label="الصوت الناتج", type="filepath") | |
| generate_btn = gr.Button("🎧 توليد الصوت") | |
| def toggle_inputs(mode): | |
| if mode == "عدة أصوات": | |
| new_text = ( | |
| "خالد: مرحباً، كيف كان يومك يا سارة؟\n" | |
| "سارة: بخير الحمد لله، وأنت؟\n" | |
| "خالد: بخير, اليوم عثرت على الكتاب الذي كنت أبحث عنه منذ فترة طويلة\n" | |
| "سارة: سعيدة لسماع هذا!" | |
| ) | |
| return gr.update(visible=False), gr.update(visible=True), gr.update(value=new_text) | |
| else: | |
| new_text = ( | |
| "في يوم من الأيام، قرر سامي أن يغادر بلدته الصغيرة ليبحث عن فرصة عمل في المدينة الكبيرة. " | |
| "كان يشعر بالقلق والخوف من المجهول، لكنه كان يعلم أن عليه أن يخوض هذه التجربة ليحقق أحلامه. " | |
| "ودّع والدته التي أوصته بأن يبقى على تواصل دائم معها، وأن لا ينسى القيم التي نشأ عليها. " | |
| "عندما وصل إلى المدينة، صُدم من صخبها واختلاف نمط الحياة فيها. حاول التأقلم، لكنه واجه صعوبات كثيرة في البداية، " | |
| "خاصةً في التعامل مع الناس وفهم لهجتهم المختلفة. ومع ذلك، لم يفقد الأمل، وظل يبحث عن فرصة تُناسب مهاراته وطموحاته." | |
| ) | |
| return gr.update(visible=True), gr.update(visible=False), gr.update(value=new_text) | |
| speaker_mode.change( | |
| fn=toggle_inputs, | |
| inputs=speaker_mode, | |
| outputs=[single_speaker_input, speaker_inputs, text] | |
| ) | |
| def handle_generate_audio(*args): | |
| audio_path, converted_text = generate_audio(*args) | |
| return audio_path, gr.update(value=converted_text, visible=bool(converted_text)) | |
| text.value = ( | |
| "في يوم من الأيام، قرر سامي أن يغادر بلدته الصغيرة ليبحث عن فرصة عمل في المدينة الكبيرة. " | |
| "كان يشعر بالقلق والخوف من المجهول، لكنه كان يعلم أن عليه أن يخوض هذه التجربة ليحقق أحلامه. " | |
| "ودّع والدته التي أوصته بأن يبقى على تواصل دائم معها، وأن لا ينسى القيم التي نشأ عليها. " | |
| "عندما وصل إلى المدينة، صُدم من صخبها واختلاف نمط الحياة فيها. حاول التأقلم، لكنه واجه صعوبات كثيرة في البداية، " | |
| "خاصةً في التعامل مع الناس وفهم لهجتهم المختلفة. ومع ذلك، لم يفقد الأمل، وظل يبحث عن فرصة تُناسب مهاراته وطموحاته." | |
| ) | |
| generate_btn.click( | |
| fn=handle_generate_audio, | |
| inputs=[ | |
| model_choice, | |
| language, | |
| accent, | |
| tone, | |
| speed, | |
| clarity, | |
| style, | |
| convert_method, | |
| speaker_mode, | |
| speaker1_name, | |
| speaker1_voice, | |
| speaker2_name, | |
| speaker2_voice, | |
| text, | |
| voice_name, | |
| premium_voice_id, | |
| extra_prompt | |
| ], | |
| outputs=[output, converted_output_text] | |
| ) | |
| demo.launch() | |