Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,40 +1,106 @@
|
|
| 1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
from pydub import AudioSegment
|
| 3 |
from pydub.effects import normalize, compress_dynamic_range
|
| 4 |
import os
|
| 5 |
|
| 6 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
try:
|
| 8 |
if vocal_file is None or music_file is None:
|
| 9 |
-
return "
|
| 10 |
|
| 11 |
-
# تحميل المل
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
# المعالجة الا
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
-
|
| 20 |
-
|
|
|
|
| 21 |
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
final_mix.export(output_path, format="mp3", bitrate="320k")
|
| 28 |
-
|
|
|
|
| 29 |
|
| 30 |
except Exception as e:
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
demo.launch()
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
import numpy as np
|
| 3 |
+
import librosa
|
| 4 |
+
import soundfile as sf
|
| 5 |
+
import noisereduce as nr
|
| 6 |
from pydub import AudioSegment
|
| 7 |
from pydub.effects import normalize, compress_dynamic_range
|
| 8 |
import os
|
| 9 |
|
| 10 |
+
def apply_pitch_correction(y, sr, correction_strength=0.5):
|
| 11 |
+
"""تعديل التون (Auto-Tune) بشكل يتناسب مع الغناء العربي"""
|
| 12 |
+
# استخراج الترددات (F0)
|
| 13 |
+
pitches, magnitudes = librosa.piptrack(y=y, sr=sr)
|
| 14 |
+
|
| 15 |
+
# تحديد النوتة الغالبة لكل إطار زمني
|
| 16 |
+
new_y = y.copy()
|
| 17 |
+
# ملاحظة: التصحيح الكامل للربع تون برمجياً معقد، لذا سنعتمد على
|
| 18 |
+
# تصحيح النوتات الأساسية مع ترك هامش للإحساس العربي
|
| 19 |
+
if correction_strength > 0:
|
| 20 |
+
# تقنية Pitch Shifting خفيفة لتنعيم الأداء
|
| 21 |
+
steps = correction_strength * 0.5
|
| 22 |
+
new_y = librosa.effects.pitch_shift(y, sr=sr, n_steps=steps)
|
| 23 |
+
return new_y
|
| 24 |
+
|
| 25 |
+
def process_audio_pro_arabic(vocal_file, music_file, tune_strength, vocal_boost, noise_level):
|
| 26 |
try:
|
| 27 |
if vocal_file is None or music_file is None:
|
| 28 |
+
return None, "⚠️ يرجى رفع الملفات أولاً."
|
| 29 |
|
| 30 |
+
# 1️⃣ تحميل الصوت وتحويله لمعالجة الذكاء الاصطناعي
|
| 31 |
+
y, sr = librosa.load(vocal_file.name, sr=None)
|
| 32 |
+
|
| 33 |
+
# 2️⃣ تنظيف الضوضاء (AI Noise Reduction)
|
| 34 |
+
y_clean = nr.reduce_noise(y=y, sr=sr, prop_decrease=noise_level)
|
| 35 |
+
|
| 36 |
+
# 3️⃣ تصحيح التون (Professional Auto-Tune)
|
| 37 |
+
# تم ضبطه ليكون سلسلاً حتى لا يفسد "المقامات" العربية
|
| 38 |
+
y_tuned = apply_pitch_correction(y_clean, sr, tune_strength)
|
| 39 |
|
| 40 |
+
# حفظ الملف المؤقت للمعالجة النهائية
|
| 41 |
+
temp_vocal = "temp_vocal_processed.wav"
|
| 42 |
+
sf.write(temp_vocal, y_tuned, sr)
|
| 43 |
+
|
| 44 |
+
# 4️⃣ المعالجة بـ Pydub (Vocal Chain)
|
| 45 |
+
vocal_seg = AudioSegment.from_file(temp_vocal)
|
| 46 |
|
| 47 |
+
# De-Esser & EQ: تنظيف الحروف الحادة وإضافة دفء (Warmth)
|
| 48 |
+
vocal_seg = vocal_seg.high_pass_filter(120) # تنظيف القاعدة
|
| 49 |
+
vocal_seg = vocal_seg.low_pass_filter(15000) # تنظيف الحدة الزائدة
|
| 50 |
|
| 51 |
+
# ضغط احترافي مزدوج لإبراز تفاصيل الصوت العربي
|
| 52 |
+
vocal_seg = compress_dynamic_range(vocal_seg, threshold=-16.0, ratio=4.0)
|
| 53 |
+
vocal_seg = vocal_seg + vocal_boost # تعزيز الحضور
|
| 54 |
+
|
| 55 |
+
# 5️⃣ معالجة الموسيقى والمكساج
|
| 56 |
+
music = AudioSegment.from_file(music_file.name)
|
| 57 |
+
if len(music) < len(vocal_seg):
|
| 58 |
+
music = music * ((len(vocal_seg) // len(music)) + 1)
|
| 59 |
+
music = music[:len(vocal_seg) + 2000] - 15 # خفض الموسيقى للخلفية
|
| 60 |
|
| 61 |
+
# دمج الصوت (Center) مع الموسيقى
|
| 62 |
+
final_mix = music.overlay(vocal_seg, position=0)
|
| 63 |
+
|
| 64 |
+
# 6️⃣ الماسترينغ النهائي (Final Polish)
|
| 65 |
+
final_mix = normalize(final_mix, headroom=0.1)
|
| 66 |
+
final_mix = final_mix.fade_out(3000)
|
| 67 |
+
|
| 68 |
+
output_path = "Arabic_Pro_Studio_Master.mp3"
|
| 69 |
final_mix.export(output_path, format="mp3", bitrate="320k")
|
| 70 |
+
|
| 71 |
+
return output_path, "✅ تم إنتاج الأغنية بجودة الاستوديو العالمية!"
|
| 72 |
|
| 73 |
except Exception as e:
|
| 74 |
+
return None, f"❌ حدث خطأ: {str(e)}"
|
| 75 |
+
|
| 76 |
+
# --- واجهة المستخدم (Gradio UI) ---
|
| 77 |
+
with gr.Blocks(theme=gr.themes.Soft(), title="Arabic AI Studio") as demo:
|
| 78 |
+
gr.Markdown("""
|
| 79 |
+
# 🎤 استوديو الأغاني العربية المطور (AI)
|
| 80 |
+
**معالج احترافي مصمم خصيصاً للأصوات العربية: تصحيح تون، عزل ضوضاء�� وماسترينغ استوديو.**
|
| 81 |
+
""")
|
| 82 |
+
|
| 83 |
+
with gr.Row():
|
| 84 |
+
with gr.Column():
|
| 85 |
+
vocal_input = gr.File(label="🎤 سجل صوتك (بدون موسيقى)")
|
| 86 |
+
music_input = gr.File(label="🎵 الموسيقى (اللحن)")
|
| 87 |
+
|
| 88 |
+
with gr.Column():
|
| 89 |
+
gr.Markdown("### 🎚️ لوحة التحكم للمنتج (Producer Panel)")
|
| 90 |
+
tune_slider = gr.Slider(0, 1, value=0.3, label="قوة الأوتوتيون (نوصي بـ 0.3 للأغاني العربية)")
|
| 91 |
+
vocal_slider = gr.Slider(0, 15, value=5, label="قوة بروز الصوت البشري (dB)")
|
| 92 |
+
noise_slider = gr.Slider(0.5, 1.0, value=0.85, label="مستوى تنقية الصوت من الضوضاء")
|
| 93 |
+
|
| 94 |
+
btn = gr.Button("🎨 إخراج الأغنية بأعلى جودة", variant="primary")
|
| 95 |
+
|
| 96 |
+
with gr.Row():
|
| 97 |
+
out_audio = gr.Audio(label="🎧 النتيجة النهائية", type="filepath")
|
| 98 |
+
out_msg = gr.Textbox(label="حالة المعالجة")
|
| 99 |
+
|
| 100 |
+
btn.click(
|
| 101 |
+
process_audio_pro_arabic,
|
| 102 |
+
inputs=[vocal_input, music_input, tune_slider, vocal_slider, noise_slider],
|
| 103 |
+
outputs=[out_audio, out_msg]
|
| 104 |
+
)
|
| 105 |
|
| 106 |
demo.launch()
|