kader1997 commited on
Commit
3d500a1
·
verified ·
1 Parent(s): d71dcc3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -28
app.py CHANGED
@@ -8,10 +8,12 @@ from moviepy import VideoFileClip, TextClip, CompositeVideoClip
8
  from arabic_reshaper import reshape
9
 
10
  # --- الإعدادات ---
 
11
  model = WhisperModel("large-v3", device="cpu", compute_type="int8")
12
 
13
  def process_arabic_text(text):
14
  if not text: return ""
 
15
  return reshape(text)
16
 
17
  def clean_color(color_str):
@@ -22,17 +24,18 @@ def clean_color(color_str):
22
  return f'rgb({r},{g},{b})'
23
  return color_str
24
 
25
- def step_1_extract_segments(video_path, progress=gr.Progress()):
26
  if not video_path: return None, "الرجاء رفع فيديو."
27
 
28
- # قمنا بتغيير الاستخراج ليعتمد على السجمنت (الجملة المنطوقة كاملة)
29
- segments, _ = model.transcribe(video_path, language="ar")
30
 
31
- segments_data = []
32
- for s in segments:
33
- segments_data.append([s.text.strip(), round(s.start, 2), round(s.end, 2)])
 
34
 
35
- return pd.DataFrame(segments_data, columns=["النص المنطوق", "البداية", "النهاية"]), "تم استخراج النصوص بنجاح!"
36
 
37
  def step_2_render_video(video_path, df_edited, font_selection, text_color, font_size, progress=gr.Progress()):
38
  if video_path is None or df_edited is None: return None, "بيانات ناقصة."
@@ -40,56 +43,55 @@ def step_2_render_video(video_path, df_edited, font_selection, text_color, font_
40
  safe_color = clean_color(text_color)
41
  actual_font = font_selection if os.path.exists(font_selection) else "DejaVu-Sans-Bold"
42
 
43
- output_path = "final_full_text_video.mp4"
44
  video = VideoFileClip(video_path)
45
  w, h = video.size
46
  clips = [video]
47
 
48
- # تحويل البيانات من الجدول
49
- segments_list = df_edited.values.tolist()
50
 
51
- for row in segments_list:
52
- sentence = str(row[0])
 
53
  t_start = float(row[1])
54
  t_end = float(row[2])
55
 
56
- if not sentence.strip(): continue
57
 
58
- clean_sentence = process_arabic_text(sentence)
59
 
60
- # إنشاء نص يظهر بالكامل خلال فترة النطق
61
  txt = TextClip(
62
- text=clean_sentence,
63
  font_size=int(font_size),
64
  color=safe_color,
65
  stroke_color='black',
66
- stroke_width=1.5,
67
  font=actual_font,
68
- method='caption',
69
- size=(int(w * 0.9), None), # عرض النص يأخذ 90% من الشاشة ليتسع للجمل
70
- text_align='center'
71
- ).with_start(t_start).with_duration(max(0.1, t_end - t_start)).with_position(('center', int(h * 0.75)))
72
 
73
  clips.append(txt)
74
 
 
75
  final = CompositeVideoClip(clips, size=(w, h))
76
  final.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=video.fps, logger='bar')
77
- return output_path, "تم إنتاج الفيديو بنجاح!"
78
 
79
  # --- الواجهة ---
80
  with gr.Blocks() as app:
81
- gr.Markdown("## 🎬 محرر الفيديو بالنصوص الكاملة")
82
  with gr.Row():
83
  v_in = gr.Video(); v_out = gr.Video()
84
  with gr.Row():
85
  font_opt = gr.Dropdown(choices=["arialbd.ttf"], value="arialbd.ttf", label="الخط")
86
- color_opt = gr.ColorPicker(value="#FFFF00", label="اللون")
87
- size_opt = gr.Slider(30, 150, value=60, label="حجم الخط")
88
 
89
- btn_1 = gr.Button("1. استخراج النصوص الكاملة"); table = gr.Dataframe(interactive=True)
90
- btn_2 = gr.Button("2. دمج النصوص مع الفيديو"); status = gr.Textbox()
91
 
92
- btn_1.click(step_1_extract_segments, [v_in], [table, status])
93
  btn_2.click(step_2_render_video, [v_in, table, font_opt, color_opt, size_opt], [v_out, status])
94
 
95
  app.launch()
 
8
  from arabic_reshaper import reshape
9
 
10
  # --- الإعدادات ---
11
+ # استخدمنا cpu و int8 لضمان العمل على أغلب الأجهزة، يمكن تغييره لـ cuda إذا توفر GPU
12
  model = WhisperModel("large-v3", device="cpu", compute_type="int8")
13
 
14
  def process_arabic_text(text):
15
  if not text: return ""
16
+ # معالجة النصوص العربية لتعرض بشكل صحيح (من اليمين لليسار وبدون حروف مقطعة)
17
  return reshape(text)
18
 
19
  def clean_color(color_str):
 
24
  return f'rgb({r},{g},{b})'
25
  return color_str
26
 
27
+ def step_1_extract_words(video_path, progress=gr.Progress()):
28
  if not video_path: return None, "الرجاء رفع فيديو."
29
 
30
+ # تفعيل word_timestamps=True هو السر لاستخراج توقيت كل كلمة
31
+ segments, _ = model.transcribe(video_path, word_timestamps=True, language="ar")
32
 
33
+ words_data = []
34
+ for segment in segments:
35
+ for word in segment.words:
36
+ words_data.append([word.word.strip(), round(word.start, 2), round(word.end, 2)])
37
 
38
+ return pd.DataFrame(words_data, columns=["الكلمة", "البداية", "النهاية"]), "تم استخراج الكلمات بدقة!"
39
 
40
  def step_2_render_video(video_path, df_edited, font_selection, text_color, font_size, progress=gr.Progress()):
41
  if video_path is None or df_edited is None: return None, "بيانات ناقصة."
 
43
  safe_color = clean_color(text_color)
44
  actual_font = font_selection if os.path.exists(font_selection) else "DejaVu-Sans-Bold"
45
 
46
+ output_path = "final_word_by_word.mp4"
47
  video = VideoFileClip(video_path)
48
  w, h = video.size
49
  clips = [video]
50
 
51
+ words_list = df_edited.values.tolist()
 
52
 
53
+ # تحويل كل صف في الجدول (كلمة) إلى Clip مستقل يظهر في وقته
54
+ for row in words_list:
55
+ word_text = str(row[0])
56
  t_start = float(row[1])
57
  t_end = float(row[2])
58
 
59
+ if not word_text.strip(): continue
60
 
61
+ clean_word = process_arabic_text(word_text)
62
 
63
+ # إنشاء كليب للكلمة الواحدة
64
  txt = TextClip(
65
+ text=clean_word,
66
  font_size=int(font_size),
67
  color=safe_color,
68
  stroke_color='black',
69
+ stroke_width=2,
70
  font=actual_font,
71
+ method='label', # 'label' أفضل للكلمات المنفردة للحفاظ على جودتها
72
+ ).with_start(t_start).with_duration(max(0.1, t_end - t_start)).with_position(('center', int(h * 0.5))) # وضعها في منتصف الشاشة تقريباً
 
 
73
 
74
  clips.append(txt)
75
 
76
+ # دمج كل الكلمات فوق الفيديو الأصلي
77
  final = CompositeVideoClip(clips, size=(w, h))
78
  final.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=video.fps, logger='bar')
79
+ return output_path, "تم إنتاج الفيديو بنظام كلمة بكلمة!"
80
 
81
  # --- الواجهة ---
82
  with gr.Blocks() as app:
83
+ gr.Markdown("## 🎬 Word-by-Word Captioner (Like Pro Apps)")
84
  with gr.Row():
85
  v_in = gr.Video(); v_out = gr.Video()
86
  with gr.Row():
87
  font_opt = gr.Dropdown(choices=["arialbd.ttf"], value="arialbd.ttf", label="الخط")
88
+ color_opt = gr.ColorPicker(value="#00FF00", label="لون الكلمة (مثلاً أخضر)")
89
+ size_opt = gr.Slider(50, 250, value=120, label="حجم الكلمة")
90
 
91
+ btn_1 = gr.Button("1. تحليل الكلمات المنطوقة"); table = gr.Dataframe(interactive=True)
92
+ btn_2 = gr.Button("2. إنشاء الفيديو النهائي"); status = gr.Textbox()
93
 
94
+ btn_1.click(step_1_extract_words, [v_in], [table, status])
95
  btn_2.click(step_2_render_video, [v_in, table, font_opt, color_opt, size_opt], [v_out, status])
96
 
97
  app.launch()