File size: 3,963 Bytes
689befd
 
f43bda0
 
689befd
 
f0e5db9
 
 
 
f43bda0
f0e5db9
f43bda0
f0e5db9
 
 
 
 
 
 
 
 
689befd
02b06fb
f0e5db9
22dab7d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b3d99fe
f0e5db9
 
f43bda0
f0e5db9
 
f43bda0
f0e5db9
689befd
 
f0e5db9
 
 
 
 
 
 
e15af47
689befd
f0e5db9
 
f6b0d3a
f43bda0
f0e5db9
 
 
f43bda0
689befd
 
f0e5db9
 
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
import os
import time
import numpy as np
import librosa
import gradio as gr

# ضبط مسار ImageMagick - تأكد من صحة هذا المسار في جهازك
os.environ["IMAGEMAGICK_BINARY"] = r"C:\Program Files\ImageMagick-7.1.2-Q16-HDRI\magick.exe"

# استيراد مرن يتوافق مع كل النسخ (1.0, 2.0, 2.1+)
try:
    from moviepy.editor import VideoFileClip, concatenate_videoclips
except ImportError:
    from moviepy import VideoFileClip, concatenate_videoclips


def safe_subclip(clip, start, end):
    """دالة ذكية تكتشف اسم الدالة الصحيح بناءً على إصدار المكتبة"""
    if hasattr(clip, 'subclipped'):
        return clip.subclipped(start, end)
    return clip.subclip(start, end)



def remove_silence(video_path, threshold=-30, progress=gr.Progress()):
    if not video_path:
        return None, "يرجى رفع فيديو أولاً."

    output_filename = f"final_result_{int(time.time())}.mp4"
    video = None
    final_video = None

    try:
        progress(0, desc="تحميل الفيديو...")
        video = VideoFileClip(video_path)

        progress(0.2, desc="تحليل موجات الصوت...")
        fps_audio = 22050
        audio_array = video.audio.to_soundarray(fps=fps_audio)

        if len(audio_array.shape) > 1:
            audio_array = np.mean(audio_array, axis=1)

        progress(0.4, desc="اكتشاف مناطق الصمت...")
        intervals = librosa.effects.split(audio_array, top_db=abs(threshold))

        if len(intervals) == 0:
            return None, "تنبيه: الفيديو صامت تماماً بناءً على الإعدادات الحالية."

        progress(0.5, desc="تجميع المقاطع الصوتية...")
        keep_clips = []
        for start_idx, end_idx in intervals:
            t_start = start_idx / fps_audio
            t_end = end_idx / fps_audio
            keep_clips.append(safe_subclip(video, t_start, t_end))

        progress(0.7, desc="بدء التصدير النهائي (قد يستغرق وقتاً)...")
        final_video = concatenate_videoclips(keep_clips)

        final_video.write_videofile(
            output_filename,
            fps=video.fps,
            codec="libx264",
            audio_codec="aac",
            threads=4,
            preset="ultrafast",
            logger=None
        )

        progress(1.0, desc="اكتملت العملية!")

        video.close()
        final_video.close()

        return output_filename, "تمت المعالجة بنجاح! يمكنك تحميل الفيديو الآن."

    except Exception as e:
        if video:
            video.close()
        return None, f"خطأ تقني: {str(e)}"

# واجهة المستخدم الاحترافية
with gr.Blocks(theme=gr.themes.Soft(), title="SilentCut Pro") as demo:
    gr.Markdown("""
    # 🎬 SilentCut Pro
    ### حذف الصمت آلياً | سرعة عالية | جودة فائقة
    """)

    with gr.Row():
        with gr.Column():
            v_in = gr.Video(label="ارفع الفيديو (MP4, AVI, MOV)")
            slider = gr.Slider(
                minimum=-60, maximum=-10, value=-30,
                label="حساسية الصمت (ديسيبل)",
                info="قلل الرقم (مثلاً -40) إذا كان البرنامج يقص أجزاء من كلامك."
            )
            btn = gr.Button("🚀 بدء حذف الصمت", variant="primary")

        with gr.Column():
            v_out = gr.Video(label="الفيديو الناتج")
            status = gr.Textbox(label="الحالة والتقدم", interactive=False)

    btn.click(
        fn=remove_silence,
        inputs=[v_in, slider],
        outputs=[v_out, status]
    )

if __name__ == "__main__":
    # تم تفعيل share=True ليعطيك رابطاً خارجياً إذا أردت استخدامه من جهاز آخر
    demo.launch(share=False)