Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions arabic-voice-generation-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# تطبيق توليدي للأصوات العربية

تطبيق بسيط وسريع لتحويل النص العربي إلى كلام باستخدام تقنيات مفتوحة المصدر.

## الميزات

- 🗣️ تحويل النص العربي إلى كلام بجودة عالية
- 🌐 واجهة مستخدم تفاعلية سهلة الاستخدام
Comment on lines +1 to +8
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description mentions using Claude's voice generation + CLAUDE_API_KEY, but this app uses local SpeechBrain (Tacotron2/HIFIGAN) and does not read any Claude/Anthropic credentials. Either update the PR/README to reflect the actual implementation or implement the Claude API integration that the PR claims to add.

Copilot uses AI. Check for mistakes.
- ⚡ سريع وفعال في التوليد
- 📦 يعتمد على مكتبات مفتوحة المصدر بالكامل
- 🎛️ إمكانية تعديل سرعة القراءة

Comment on lines +7 to +12
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README advertises speed control (“إمكانية تعديل سرعة القراءة”), but the current implementation does not change audio speed. Align the documentation with actual behavior or implement the feature.

Copilot uses AI. Check for mistakes.
## المتطلبات

- Python 3.7+
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README claims Python 3.7+ support, but the dependency set (Torch/Torchaudio/Gradio) commonly drops older Python versions. It would be safer to state and enforce the minimum Python version you actually test/install with (e.g., 3.9+), otherwise installs on 3.7 may fail.

Suggested change
- Python 3.7+
- Python 3.9+

Copilot uses AI. Check for mistakes.
- مكتبات Python المذكورة في ملف `requirements.txt`

## التثبيت

1. تثبيت المكتبات المطلوبة:
```bash
pip install -r requirements.txt
```

2. تشغيل التطبيق:
```bash
python app.py
```

3. فتح المتصفح على العنوان: http://localhost:7860

## الاستخدام

1. أدخل النص العربي في مربع النص
2. اضبط سرعة القراءة حسب الرغبة
3. انقر على زر "تحويل إلى كلام"
4. استمع إلى الصوت المُوَلَّد أو نزّله

## التقنيات المستخدمة

- **SpeechBrain**: إطار عمل مفتوح المصدر للتعلم العميق في معالجة الكلام
- **Tacotron2**: نموذج توليدي للكلام متقدم
- **HIFIGAN**: نموذج لتوليد الصوت عالي الجودة
- **Gradio**: لإنشاء واجهة المستخدم التفاعلية

## التخصيص

يمكنك تعديل النموذج لإضافة:
- أصوات مختلفة
- لهجات عربية متنوعة
- تعديلات على سرعة القراءة والطبقة الصوتية
85 changes: 85 additions & 0 deletions arabic-voice-generation-app/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import gradio as gr
import numpy as np
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'np' is not used.

Suggested change
import numpy as np

Copilot uses AI. Check for mistakes.
from tts_model import ArabicTTS
import os

Comment on lines +4 to +5
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'os' is not used.

Suggested change
import os

Copilot uses AI. Check for mistakes.
# تهيئة نموذج تحويل النص إلى كلام
tts = ArabicTTS()

Comment on lines +6 to +8
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArabicTTS() is instantiated at import time, which will download/load large models during module import and can make the Gradio app slow to start or fail on reload. Consider lazy-initializing the model (e.g., on first request or via a Gradio load event) and surfacing a clear initialization error if model loading fails.

Copilot uses AI. Check for mistakes.
def generate_speech(text, speed=1.0):
"""
توليد الصوت من النص العربي

Args:
text (str): النص العربي
speed (float): سرعة القراءة (0.5-2.0)

Returns:
tuple: (معدل العينة, الصوت المُوَلَّد)
"""
if not text.strip():
return None, "الرجاء إدخال نص للتحويل"

# توليد الصوت
audio = tts.text_to_speech(text)

Comment on lines +23 to +25
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utils.preprocess_arabic_text() exists but the input text is passed to the TTS model without any preprocessing. If preprocessing (e.g., whitespace normalization / digit handling) is required for quality, call it here (or remove the unused utility to avoid dead code).

Copilot uses AI. Check for mistakes.
if audio is not None:
# تعديل سرعة القراءة إذا لزم الأمر
if speed != 1.0:
# يمكن إضافة تعديل السرعة هنا
pass

Comment on lines +29 to +31
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UI exposes a speed control, but speed is currently ignored (the code just passes). This is user-visible incorrect behavior; either implement time-stretching/resampling for speed changes or remove/disable the slider until supported.

Suggested change
# يمكن إضافة تعديل السرعة هنا
pass
# يمكن إضافة تعديل السرعة هنا باستخدام إعادة التعيين البسيط للعينات
# نحافظ على نفس معدل العينة (22050) ونقوم بتغيير طول الإشارة
# السرعة > 1.0 => مدة أقصر (قراءة أسرع)، السرعة < 1.0 => مدة أطول (قراءة أبطأ)
if not isinstance(audio, np.ndarray):
audio = np.array(audio)
original_length = audio.shape[0]
# تجنب مشاكل القيم غير المنطقية
if speed > 0 and original_length > 1:
new_length = max(1, int(original_length / speed))
original_indices = np.linspace(0, original_length - 1, num=original_length)
new_indices = np.linspace(0, original_length - 1, num=new_length)
audio = np.interp(new_indices, original_indices, audio).astype(audio.dtype)

Copilot uses AI. Check for mistakes.
# حفظ الصوت مؤقتًا
temp_filename = "temp_output.wav"
tts.save_audio(audio, temp_filename)

Comment on lines +32 to +35
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

temp_output.wav is written on every request but the returned value is the in-memory numpy audio, so the temp file is unused and never cleaned up. This will also cause races/overwrites with concurrent users. Consider removing the file write entirely or using a per-request temp file with cleanup and returning the file path if needed.

Copilot uses AI. Check for mistakes.
# إرجاع الصوت للواجهة
return (22050, audio), None
Comment on lines +36 to +37
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sample rate is hard-coded to 22050 here even though config.py defines AUDIO_SAMPLE_RATE. To avoid drift, use the shared constant (and ensure the model/vocoder output sample rate matches it).

Copilot uses AI. Check for mistakes.
else:
return None, "حدث خطأ في توليد الصوت"

# إنشاء واجهة المستخدم
with gr.Blocks(title="تطبيق توليدي للأصوات العربية") as demo:
gr.Markdown("# 🗣️ تطبيق توليدي للأصوات العربية")
gr.Markdown("تحويل النص العربي إلى كلام باستخدام تقنيات مفتوحة المصدر")

with gr.Row():
with gr.Column():
text_input = gr.Textbox(
label="أدخل النص العربي",
placeholder="اكتب النص الذي تريد تحويله إلى كلام...",
lines=5
)
speed_slider = gr.Slider(
minimum=0.5,
maximum=2.0,
value=1.0,
label="سرعة القراءة"
)
generate_btn = gr.Button("تحويل إلى كلام", variant="primary")

with gr.Column():
audio_output = gr.Audio(label="الصوت المُوَلَّد")
error_output = gr.Textbox(label="رسائل الخطأ", interactive=False)

generate_btn.click(
fn=generate_speech,
inputs=[text_input, speed_slider],
outputs=[audio_output, error_output]
)

gr.Markdown("### أمثلة للنصوص العربية:")
gr.Examples(
examples=[
"السلام عليكم ورحمة الله وبركاته",
"مرحباً بك في تطبيق تحويل النص إلى كلام",
"هذا التطبيق يستخدم تقنيات مفتوحة المصدر",
"يمكنك كتابة أي نص عربي وسيتم تحويله إلى كلام",
"نأمل أن تجد هذا التطبيق مفيداً"
],
inputs=text_input
)

# تشغيل التطبيق
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Launching Gradio with server_name="0.0.0.0" exposes the app on the network by default. Prefer defaulting to 127.0.0.1 for local use and making the bind address configurable via env/config for deployments.

Suggested change
demo.launch(server_name="0.0.0.0", server_port=7860)
host = os.getenv("GRADIO_SERVER_NAME", "127.0.0.1")
port = int(os.getenv("GRADIO_SERVER_PORT", "7860"))
demo.launch(server_name=host, server_port=port)

Copilot uses AI. Check for mistakes.
17 changes: 17 additions & 0 deletions arabic-voice-generation-app/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# إعدادات الصوت
AUDIO_SAMPLE_RATE = 22050
AUDIO_CHANNELS = 1

# إعدادات النموذج
MODEL_CONFIG = {
"g2p_model": "speechbrain/tts_models/arabic-tacotron2-collab",
"tts_model": "speechbrain/tts_models/arabic-tacotron2-collab",
"vocoder_model": "speechbrain/tts_models/arabic-hifigan-collab"
}

# إعدادات الواجهة
INTERFACE_CONFIG = {
"title": "تطبيق توليدي للأصوات العربية",
"server_name": "0.0.0.0",
"server_port": 7860
}
9 changes: 9 additions & 0 deletions arabic-voice-generation-app/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
torch>=1.13.0
torchaudio>=0.13.0
transformers>=4.21.0
speechbrain>=0.5.12
librosa>=0.9.2
soundfile>=0.10.3
numpy>=1.21.0
gradio>=3.24.1
huggingface_hub>=0.12.0
Comment on lines +3 to +9
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transformers is listed as a dependency but does not appear to be used by the app code. If SpeechBrain doesn’t require it transitively, removing it will significantly reduce install size and potential dependency conflicts.

Suggested change
transformers>=4.21.0
speechbrain>=0.5.12
librosa>=0.9.2
soundfile>=0.10.3
numpy>=1.21.0
gradio>=3.24.1
huggingface_hub>=0.12.0
speechbrain>=0.5.12
librosa>=0.9.2
soundfile>=0.10.3
numpy>=1.21.0
gradio>=3.24.1
huggingface_hub>=0.12.0

Copilot uses AI. Check for mistakes.
71 changes: 71 additions & 0 deletions arabic-voice-generation-app/tts_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import torch
import torchaudio
from speechbrain.inference.text import GraphemeToPhoneme
from speechbrain.inference.TTS import Tacotron2
from speechbrain.inference.vocoders import HIFIGAN
import numpy as np
import librosa

Comment on lines +6 to +8
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

numpy and librosa are imported but not used in this module. Removing unused imports reduces dependency surface area and avoids pulling in heavy packages unnecessarily.

Suggested change
import numpy as np
import librosa

Copilot uses AI. Check for mistakes.
class ArabicTTS:
def __init__(self):
"""تهيئة نموذج تحويل النص إلى كلام للغة العربية"""
# تحميل نموذج تحويل الحروف إلى أصوات (Grapheme-to-Phoneme)
self.g2p = GraphemeToPhoneme.from_hparams(
"speechbrain/tts_models/arabic-tacotron2-collab",
savedir="pretrained_models/g2p"
)

# تحميل نموذج Tacotron2 للغة العربية
self.tts_model = Tacotron2.from_hparams(
"speechbrain/tts_models/arabic-tacotron2-collab",
savedir="pretrained_models/tts"
)

# تحميل نموذج HIFIGAN لتوليد الصوت عالي الجودة
self.vocoder = HIFIGAN.from_hparams(
"speechbrain/tts_models/arabic-hifigan-collab",
savedir="pretrained_models/vocoder"
)

def text_to_speech(self, text):
"""
تحويل النص العربي إلى كلام

Args:
text (str): النص العربي المراد تحويله

Returns:
numpy.ndarray: الصوت المُوَلَّد
"""
try:
# تحويل النص إلى صوتيفات (Phonemes)
phonemes = self.g2p.g2p(text)
print(f"النصوص الصوتية: {phonemes}")

Comment on lines +41 to +44
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prints phoneme content for every request, which can leak user input into logs and create noisy output in production. Consider using structured logging with an appropriate log level and avoid logging full user-provided text/phonemes by default.

Copilot uses AI. Check for mistakes.
# إنشاء التمثيل الطيفي للصوت
mel_spec, _, _ = self.tts_model.encode_text(phonemes)

# تحويل التمثيل الطيفي إلى صوت باستخدام HIFIGAN
waveform = self.vocoder.decode_batch(mel_spec)

# تحويل المصفوفة إلى مصفوفة numpy
audio = waveform.squeeze().cpu().numpy()

return audio
except Exception as e:
print(f"خطأ في توليد الصوت: {str(e)}")
return None
Comment on lines +55 to +57
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catching all exceptions and returning None makes failures hard to diagnose and forces the UI to show a generic error. Prefer raising a typed exception or returning an error message/trace context to the caller (and use logging.exception to preserve stack traces).

Copilot uses AI. Check for mistakes.

def save_audio(self, audio, filename, sample_rate=22050):
"""
حفظ الصوت المُوَلَّد في ملف

Args:
audio (numpy.ndarray): الصوت المُوَلَّد
filename (str): اسم الملف
sample_rate (int): معدل العينة
"""
if audio is not None:
# حفظ الصوت بصيغة WAV
torchaudio.save(filename, torch.tensor(audio).unsqueeze(0), sample_rate)
print(f"تم حفظ الصوت في: {filename}")
39 changes: 39 additions & 0 deletions arabic-voice-generation-app/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import re
import os

def preprocess_arabic_text(text):
"""
معالجة النص العربي قبل التحويل إلى كلام

Args:
text (str): النص العربي الأصلي

Returns:
str: النص المُعالج
"""
# إزالة المسافات الزائدة
text = re.sub(r'\s+', ' ', text).strip()

# معالجة الأرقام العربية
arabic_numbers = {
'٠': '0', '١': '1', '٢': '2', '٣': '3', '٤': '4',
'٥': '5', '٦': '6', '٧': '7', '٨': '8', '٩': '9'
}

for arabic, english in arabic_numbers.items():
text = text.replace(arabic, english)

return text

def check_model_files():
"""التحقق من وجود ملفات النماذج المطلوبة"""
required_dirs = [
"pretrained_models/g2p",
"pretrained_models/tts",
"pretrained_models/vocoder"
]

for directory in required_dirs:
if not os.path.exists(directory):
os.makedirs(directory)
print(f"تم إنشاء المجلد: {directory}")
2 changes: 1 addition & 1 deletion config/repolinter-ruleset.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
},
"policyInfo": "GitHub requires a CODEOWNERS file in all projects. This enables GitHub to contact the maintainers in the event it is necessary.",
"policyUrl": "https://github.com/github/open-source/blob/main/policies/release.md"
},
}
},
"formatOptions": {
"disclaimer": "🤖*This issue was automatically generated by [repolinter-action](https://github.com/newrelic/repolinter-action), developed by the Open Source and Developer Advocacy team at New Relic.*"
Expand Down
23 changes: 23 additions & 0 deletions config/text-summarizer-eval.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Text Summarizer
description: Summarizes input text concisely
model: openai/gpt-4o-mini
modelParameters:
temperature: 0.5
messages:
- role: system
content: You are a text summarizer. Your only job is to summarize text given to you.
- role: user
content: |
Summarize the given text, beginning with "Summary -":
<text>
{{input}}
</text>
testData:
- input: |
The quick brown fox jumped over the lazy dog.
The dog was too tired to react.
expected: Summary - A fox jumped over a lazy, unresponsive dog.
evaluators:
- name: Output should start with 'Summary -'
string:
startsWith: 'Summary -'
Comment on lines +1 to +23
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This config file appears unrelated to the Arabic voice generation feature (it defines a text summarizer eval using openai/gpt-4o-mini) and there are no references to it elsewhere in the repo. If it’s meant for a specific evaluation tool/CI job, add a short note on how it’s used; otherwise consider removing it to keep the PR focused.

Copilot uses AI. Check for mistakes.
Loading
Loading