kader1997 commited on
Commit
b3d99fe
·
verified ·
1 Parent(s): f6b0d3a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -47
app.py CHANGED
@@ -9,26 +9,25 @@ os.environ["IMAGEMAGICK_BINARY"] = r"C:\Program Files\ImageMagick-7.1.2-Q16-HDRI
9
 
10
  try:
11
  from moviepy.editor import VideoFileClip, concatenate_videoclips
 
 
12
  except ImportError:
13
  from moviepy import VideoFileClip, concatenate_videoclips
 
 
14
 
15
- def safe_subclip(clip, start, end):
16
- if hasattr(clip, 'subclipped'):
17
- return clip.subclipped(start, end)
18
- return clip.subclip(start, end)
19
-
20
- def remove_silence(video_path, threshold=-30, padding=0.15, fade_duration=0.1, progress=gr.Progress()):
21
  if not video_path:
22
  return None, "يرجى رفع فيديو أولاً."
23
 
24
- output_filename = f"pro_result_{int(time.time())}.mp4"
25
  video = None
26
 
27
  try:
28
- progress(0.1, desc="تحليل المسار الصوتي بدقة...")
29
  video = VideoFileClip(video_path)
30
 
31
- # استخراج الصوت بدقة عالية للمزامنة
32
  fps_audio = 44100
33
  audio_array = video.audio.to_soundarray(fps=fps_audio)
34
  if len(audio_array.shape) > 1:
@@ -41,75 +40,71 @@ def remove_silence(video_path, threshold=-30, padding=0.15, fade_duration=0.1, p
41
  return None, "تنبيه: لم يتم اكتشاف صوت مسموع."
42
 
43
  keep_clips = []
44
- video_duration = video.duration
45
 
46
- progress(0.4, desc="تجهيز المقاطع وتنعيم الحواف...")
47
- for i, (start_idx, end_idx) in enumerate(intervals):
48
  t_start = max(0, (start_idx / fps_audio) - padding)
49
- t_end = min(video_duration, (end_idx / fps_audio) + padding)
50
 
51
  if t_end - t_start > 0.1:
52
- clip = safe_subclip(video, t_start, t_end)
 
 
 
 
 
 
 
 
 
 
53
 
54
- # إضافة تلاشي صوتي (Audio Fade) لمنع الفرقعة عند القص
55
- clip = clip.audio_fadein(fade_duration).audio_fadeout(fade_duration)
56
  keep_clips.append(clip)
57
 
58
  if not keep_clips:
59
  return None, "لم يتم العثور على مقاطع صالحة."
60
 
61
- progress(0.7, desc="دمج احترافي مع Crossfade...")
62
-
63
- # دمج المقاطع مع تداخل بسيط (padding/2) لجعل الانتقال ناعماً
64
- # تم استخدام method="compose" لضمان أفضل مزامنة للصوت والصورة
65
- final_video = concatenate_videoclips(keep_clips, method="compose", padding=-0.05)
66
 
67
- progress(0.85, desc="تصدير بجودة عالية (H.264)...")
68
  final_video.write_videofile(
69
  output_filename,
70
  fps=video.fps,
71
  codec="libx264",
72
  audio_codec="aac",
73
- bitrate="5000k", # رفع البت ريت لتحسين جودة الصورة
 
74
  threads=4,
75
- preset="medium", # تغيير من ultrafast إلى medium لتحسين جودة الضغط
76
  logger=None
77
  )
78
 
79
- # تنظيف الذاكرة
80
  video.close()
81
  for c in keep_clips: c.close()
82
 
83
- return output_filename, "تم إنتاج فيديو احترافي بنجاح!"
84
 
85
  except Exception as e:
86
  if video: video.close()
87
- return None, f"خطأ: {str(e)}"
88
-
89
- # واجهة المستخدم المطورة
90
- with gr.Blocks(theme=gr.themes.Soft(), title="SilentCut Pro v2") as demo:
91
- gr.Markdown("""
92
- # 🎬 SilentCut Pro v2
93
- ### حذف الصمت مع انتقال ناعم (Crossfade) ومزامنة محسنة
94
- """)
95
-
96
  with gr.Row():
97
  with gr.Column():
98
- v_in = gr.Video(label="الفيديو الأصلي")
99
- with gr.Row():
100
- slider = gr.Slider(minimum=-60, maximum=-10, value=-35, label="حساسية الصمت")
101
- pad_slider = gr.Slider(minimum=0.0, maximum=0.5, value=0.15, label="هامش الأمان انية)")
102
- btn = gr.Button("🚀 معالجة الفيديو بجودة احترافية", variant="primary")
103
-
104
  with gr.Column():
105
- v_out = gr.Video(label="الفيديو المحسن")
106
  status = gr.Textbox(label="الحالة")
107
 
108
- btn.click(
109
- fn=remove_silence,
110
- inputs=[v_in, slider, pad_slider],
111
- outputs=[v_out, status]
112
- )
113
 
114
  if __name__ == "__main__":
115
  demo.launch()
 
9
 
10
  try:
11
  from moviepy.editor import VideoFileClip, concatenate_videoclips
12
+ import moviepy.video.fx.all as vfx
13
+ import moviepy.audio.fx.all as afx
14
  except ImportError:
15
  from moviepy import VideoFileClip, concatenate_videoclips
16
+ # في الإصدارات الأحدث يتم استيرادها هكذا
17
+ from moviepy.video.fx import fadein, fadeout
18
 
19
+ def remove_silence(video_path, threshold=-30, padding=0.15, progress=gr.Progress()):
 
 
 
 
 
20
  if not video_path:
21
  return None, "يرجى رفع فيديو أولاً."
22
 
23
+ output_filename = f"pro_v3_{int(time.time())}.mp4"
24
  video = None
25
 
26
  try:
27
+ progress(0.1, desc="جاري فحص الفيديو...")
28
  video = VideoFileClip(video_path)
29
 
30
+ # تحليل الصوت
31
  fps_audio = 44100
32
  audio_array = video.audio.to_soundarray(fps=fps_audio)
33
  if len(audio_array.shape) > 1:
 
40
  return None, "تنبيه: لم يتم اكتشاف صوت مسموع."
41
 
42
  keep_clips = []
43
+ v_dur = video.duration
44
 
45
+ progress(0.4, desc="تجميع اللقطات وتصحيح الصوت...")
46
+ for start_idx, end_idx in intervals:
47
  t_start = max(0, (start_idx / fps_audio) - padding)
48
+ t_end = min(v_dur, (end_idx / fps_audio) + padding)
49
 
50
  if t_end - t_start > 0.1:
51
+ # قص المقطع
52
+ if hasattr(video, 'subclipped'):
53
+ clip = video.subclipped(t_start, t_end)
54
+ else:
55
+ clip = video.subclip(t_start, t_end)
56
+
57
+ # تنعيم الصوت لتجنب الـ Pop Noise (طريقة متوافقة مع كل النسخ)
58
+ try:
59
+ clip.audio = clip.audio.fx(afx.audio_fadein, 0.05).fx(afx.audio_fadeout, 0.05)
60
+ except:
61
+ pass # إذا فشل التنعيم يستمر البرنامج لضمان إنتاج الفيديو
62
 
 
 
63
  keep_clips.append(clip)
64
 
65
  if not keep_clips:
66
  return None, "لم يتم العثور على مقاطع صالحة."
67
 
68
+ progress(0.7, desc="دمج نهائي ومزامنة...")
69
+ # استخدام method="compose" هو السر في الحفاظ على تزامن الصوت والصورة
70
+ final_video = concatenate_videoclips(keep_clips, method="compose")
 
 
71
 
72
+ progress(0.85, desc="تصدير الفيديو النهائي...")
73
  final_video.write_videofile(
74
  output_filename,
75
  fps=video.fps,
76
  codec="libx264",
77
  audio_codec="aac",
78
+ temp_audiofile="temp-audio.m4a",
79
+ remove_temp=True,
80
  threads=4,
81
+ preset="ultrafast", # سرعة عالية
82
  logger=None
83
  )
84
 
 
85
  video.close()
86
  for c in keep_clips: c.close()
87
 
88
+ return output_filename, "تمت المعالجة بنجاح مع إصلاح الأخطاء!"
89
 
90
  except Exception as e:
91
  if video: video.close()
92
+ return None, f"خطأ تقني: {str(e)}"
93
+
94
+ # واجهة Gradio
95
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
96
+ gr.Markdown("# 🎬 SilentCut Pro (الإصدار المستقر)")
 
 
 
 
97
  with gr.Row():
98
  with gr.Column():
99
+ v_in = gr.Video(label="رفع الفيديو")
100
+ slider = gr.Slider(minimum=-60, maximum=-10, value=-35, label="حساسية الصمت")
101
+ pad_slider = gr.Slider(minimum=0.0, maximum=0.5, value=0.15, label="هامش الأمان")
102
+ btn = gr.Button("🚀 معالجة الآن", variant="primary")
 
 
103
  with gr.Column():
104
+ v_out = gr.Video(label="النتيجة")
105
  status = gr.Textbox(label="الحالة")
106
 
107
+ btn.click(fn=remove_silence, inputs=[v_in, slider, pad_slider], outputs=[v_out, status])
 
 
 
 
108
 
109
  if __name__ == "__main__":
110
  demo.launch()