kader1997 commited on
Commit
0561398
·
verified ·
1 Parent(s): c5a8cc6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -56
app.py CHANGED
@@ -12,7 +12,9 @@ model = WhisperModel("large-v3", device="cpu", compute_type="int8")
12
 
13
  def process_arabic_text(text):
14
  if not text: return ""
 
15
  reshaped = reshape(text)
 
16
  return reshaped + "\n "
17
 
18
  def clean_color(color_str):
@@ -23,32 +25,16 @@ def clean_color(color_str):
23
  return f'rgb({r},{g},{b})'
24
  return color_str
25
 
26
- def step_1_extract_with_translation(video_path, progress=gr.Progress()):
27
  if not video_path: return None, "الرجاء رفع فيديو."
 
28
 
29
- # استخراج النص العربي الأصلي مع التوقيت
30
- segments_ar, _ = model.transcribe(video_path, word_timestamps=True, language="ar")
31
-
32
- # طلب الترجمة إلى الإنجليزية من النموذج مباشرة
33
- segments_en, _ = model.transcribe(video_path, task="translate")
34
-
35
- # سنقوم بدمج الترجمة الإنجليزية مع الكلمات العربية بناءً على التوقيت تقريبياً
36
  words_data = []
37
- # لتحسين الأداء سنضع الترجمة الإنجليزية في قائمة
38
- en_texts = list(segments_en)
39
-
40
- for segment in segments_ar:
41
- # البحث عن أقرب ترجمة إنجليزية لهذا الجزء
42
- en_translation = ""
43
- for en_seg in en_texts:
44
- if (en_seg.start <= segment.start <= en_seg.end) or (segment.start <= en_seg.start <= segment.end):
45
- en_translation = en_seg.text.strip()
46
- break
47
-
48
  for word in segment.words:
49
- words_data.append([word.word.strip(), en_translation, round(word.start, 2), round(word.end, 2)])
50
 
51
- return pd.DataFrame(words_data, columns=["العربية", "الترجمة الإنجليزية", "البداية", "النهاية"]), "تم الاستخراج والترجمة!"
52
 
53
  def step_2_render_video(video_path, df_edited, font_selection, text_color, font_size, progress=gr.Progress()):
54
  if video_path is None or df_edited is None: return None, "بيانات ناقصة."
@@ -56,66 +42,53 @@ def step_2_render_video(video_path, df_edited, font_selection, text_color, font_
56
  safe_color = clean_color(text_color)
57
  actual_font = font_selection if os.path.exists(font_selection) else "DejaVu-Sans-Bold"
58
 
59
- output_path = "final_bilingual_video.mp4"
60
  video = VideoFileClip(video_path)
61
  w, h = video.size
62
  clips = [video]
63
 
64
- data_list = df_edited.values.tolist()
65
 
66
- for row in data_list:
67
- ar_text = str(row[0])
68
- en_text = str(row[1])
69
- t_start = float(row[2])
70
- t_end = float(row[3])
71
 
72
- if not ar_text.strip(): continue
73
 
74
- # 1. النص العربي (كبير)
75
- clean_ar = process_arabic_text(ar_text)
76
- ar_clip = TextClip(
77
- text=clean_ar,
78
  font_size=int(font_size),
79
  color=safe_color,
80
  stroke_color='black',
81
- stroke_width=2,
82
  font=actual_font,
83
  method='label'
84
- ).with_start(t_start).with_duration(max(0.1, t_end - t_start)).with_position(('center', int(h * 0.45)))
85
-
86
- # 2. النص الإنجليزي (صغير) في الأسفل
87
- en_clip = TextClip(
88
- text=en_text,
89
- font_size=int(font_size * 0.4), # تصغير الترجمة لـ 40% من حجم العربي
90
- color="white",
91
- stroke_color='black',
92
- stroke_width=1,
93
- font="Arial", # خط بسيط للإنجليزي
94
- method='caption',
95
- size=(int(w * 0.8), None)
96
- ).with_start(t_start).with_duration(max(0.1, t_end - t_start)).with_position(('center', int(h * 0.6)))
97
 
98
- clips.append(ar_clip)
99
- clips.append(en_clip)
100
 
101
  final = CompositeVideoClip(clips, size=(w, h))
102
  final.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=video.fps, logger='bar')
103
- return output_path, "تم إنتاج الفيديو المترجم بنجاح!"
104
 
105
  # --- الواجهة ---
106
  with gr.Blocks() as app:
107
- gr.Markdown("## 🎬 محرر الفيديو المزدوج (عربي + إنجليزي)")
108
  with gr.Row():
109
  v_in = gr.Video(); v_out = gr.Video()
110
  with gr.Row():
111
- font_opt = gr.Dropdown(choices=["arialbd.ttf"], value="arialbd.ttf", label="الخط العربي")
112
- color_opt = gr.ColorPicker(value="#FF8C00", label="لون العربي")
113
- size_opt = gr.Slider(30, 200, value=90, label="حجم الخط العربي")
 
114
 
115
- btn_1 = gr.Button("1. تحليل وترجمة"); table = gr.Dataframe(interactive=True)
116
  btn_2 = gr.Button("2. إنتاج الفيديو"); status = gr.Textbox()
117
 
118
- btn_1.click(step_1_extract_with_translation, [v_in], [table, status])
119
  btn_2.click(step_2_render_video, [v_in, table, font_opt, color_opt, size_opt], [v_out, status])
120
 
121
  app.launch()
 
12
 
13
  def process_arabic_text(text):
14
  if not text: return ""
15
+ # 1. إعادة تشكيل الحروف العربية لتظهر متصلة وصحيحة (بدون النقاط الإضافية •)
16
  reshaped = reshape(text)
17
+ # 2. إضافة سطر فارغ في الأسفل لمنع قص النقاط السفلية للأحرف
18
  return reshaped + "\n "
19
 
20
  def clean_color(color_str):
 
25
  return f'rgb({r},{g},{b})'
26
  return color_str
27
 
28
+ def step_1_extract_words(video_path, progress=gr.Progress()):
29
  if not video_path: return None, "الرجاء رفع فيديو."
30
+ segments, _ = model.transcribe(video_path, word_timestamps=True, language="ar")
31
 
 
 
 
 
 
 
 
32
  words_data = []
33
+ for segment in segments:
 
 
 
 
 
 
 
 
 
 
34
  for word in segment.words:
35
+ words_data.append([word.word.strip(), round(word.start, 2), round(word.end, 2)])
36
 
37
+ return pd.DataFrame(words_data, columns=["الكلمة", "البداية", "النهاية"]), "تم استخراج الكلمات!"
38
 
39
  def step_2_render_video(video_path, df_edited, font_selection, text_color, font_size, progress=gr.Progress()):
40
  if video_path is None or df_edited is None: return None, "بيانات ناقصة."
 
42
  safe_color = clean_color(text_color)
43
  actual_font = font_selection if os.path.exists(font_selection) else "DejaVu-Sans-Bold"
44
 
45
+ output_path = "final_clean_text_video.mp4"
46
  video = VideoFileClip(video_path)
47
  w, h = video.size
48
  clips = [video]
49
 
50
+ words_list = df_edited.values.tolist()
51
 
52
+ for row in words_list:
53
+ word_text = str(row[0])
54
+ t_start = float(row[1])
55
+ t_end = float(row[2])
 
56
 
57
+ if not word_text.strip(): continue
58
 
59
+ clean_word = process_arabic_text(word_text)
60
+
61
+ txt = TextClip(
62
+ text=clean_word,
63
  font_size=int(font_size),
64
  color=safe_color,
65
  stroke_color='black',
66
+ stroke_width=2.0, # تقليل سمك التحديد قليلاً ليتناسب مع النص الأصغر
67
  font=actual_font,
68
  method='label'
69
+ ).with_start(t_start).with_duration(max(0.1, t_end - t_start)).with_position(('center', int(h * 0.5)))
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ clips.append(txt)
 
72
 
73
  final = CompositeVideoClip(clips, size=(w, h))
74
  final.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=video.fps, logger='bar')
75
+ return output_path, "تم إنتاج الفيديو بنجاح!"
76
 
77
  # --- الواجهة ---
78
  with gr.Blocks() as app:
79
+ gr.Markdown("## 🎬 محرر الفيديو: نصوص نظيفة")
80
  with gr.Row():
81
  v_in = gr.Video(); v_out = gr.Video()
82
  with gr.Row():
83
+ font_opt = gr.Dropdown(choices=["arialbd.ttf"], value="arialbd.ttf", label="الخط")
84
+ color_opt = gr.ColorPicker(value="#FF8C00", label="لون ذهبي برتقالي")
85
+ # تم تصغير الحجم الافتراضي من 130 إلى 90
86
+ size_opt = gr.Slider(30, 200, value=90, label="حجم النص")
87
 
88
+ btn_1 = gr.Button("1. تحليل الكلمات"); table = gr.Dataframe(interactive=True)
89
  btn_2 = gr.Button("2. إنتاج الفيديو"); status = gr.Textbox()
90
 
91
+ btn_1.click(step_1_extract_words, [v_in], [table, status])
92
  btn_2.click(step_2_render_video, [v_in, table, font_opt, color_opt, size_opt], [v_out, status])
93
 
94
  app.launch()