kader1997 commited on
Commit
d71dcc3
·
verified ·
1 Parent(s): 640b429

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -29
app.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  os.environ["IMAGE_MAGICK_BINARY"] = "/usr/bin/convert"
3
  import gradio as gr
4
  import pandas as pd
5
- import re # نحتاجه لتنظيف الألوان
6
  from faster_whisper import WhisperModel
7
  from moviepy import VideoFileClip, TextClip, CompositeVideoClip
8
  from arabic_reshaper import reshape
@@ -11,79 +11,85 @@ from arabic_reshaper import reshape
11
  model = WhisperModel("large-v3", device="cpu", compute_type="int8")
12
 
13
  def process_arabic_text(text):
14
- return reshape(text) + "\n "
 
15
 
16
  def clean_color(color_str):
17
- """دالة لتحويل أي صيغة لون غريبة إلى صيغة يفهمها البرنامج"""
18
  if color_str.startswith('rgba'):
19
- # استخراج الأرقام فقط وتحويلها لأرقام صحيحة
20
  nums = re.findall(r"\d+\.?\d*", color_str)
21
  if len(nums) >= 3:
22
  r, g, b = int(float(nums[0])), int(float(nums[1])), int(float(nums[2]))
23
  return f'rgb({r},{g},{b})'
24
  return color_str
25
 
26
- def step_1_extract_words(video_path, progress=gr.Progress()):
27
  if not video_path: return None, "الرجاء رفع فيديو."
28
- segments, _ = model.transcribe(video_path, word_timestamps=True, language="ar")
29
- words_data = [[w.word.strip(), round(w.start, 2), round(w.end, 2)] for s in segments for w in s.words]
30
- return pd.DataFrame(words_data, columns=["الكلمة", "البداية", "النهاية"]), "تم الاستخراج!"
 
 
 
 
 
 
31
 
32
  def step_2_render_video(video_path, df_edited, font_selection, text_color, font_size, progress=gr.Progress()):
33
  if video_path is None or df_edited is None: return None, "بيانات ناقصة."
34
 
35
- # تنظيف اللون قبل استخدامه لمنع خطأ ValueError
36
  safe_color = clean_color(text_color)
37
-
38
- # التأكد من وجود ملف الخط
39
  actual_font = font_selection if os.path.exists(font_selection) else "DejaVu-Sans-Bold"
40
 
41
- output_path = "final_fixed_video.mp4"
42
  video = VideoFileClip(video_path)
43
  w, h = video.size
44
  clips = [video]
45
- words_list = df_edited.values.tolist()
46
- chunk_size = 3
 
47
 
48
- for i in range(0, len(words_list), chunk_size):
49
- chunk = words_list[i : i + chunk_size]
50
- sentence = " ".join([str(r[0]) for r in chunk])
51
- clean_sentence = process_arabic_text(sentence)
52
 
53
- t_start, t_end = float(chunk[0][1]), float(chunk[-1][2])
54
 
 
 
 
55
  txt = TextClip(
56
  text=clean_sentence,
57
  font_size=int(font_size),
58
- color=safe_color, # اللون النظيف هنا
59
  stroke_color='black',
60
  stroke_width=1.5,
61
  font=actual_font,
62
  method='caption',
63
- size=(int(w * 0.8), None),
64
  text_align='center'
65
- ).with_start(t_start).with_duration(max(0.1, t_end - t_start)).with_position(('center', int(h * 0.65)))
66
 
67
  clips.append(txt)
68
 
69
  final = CompositeVideoClip(clips, size=(w, h))
70
  final.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=video.fps, logger='bar')
71
- return output_path, f"تم بنجاح! اللون المستخدم: {safe_color}"
72
 
73
  # --- الواجهة ---
74
  with gr.Blocks() as app:
75
- gr.Markdown("## 🎬 Caption Pro: Stable Version")
76
  with gr.Row():
77
  v_in = gr.Video(); v_out = gr.Video()
78
  with gr.Row():
79
  font_opt = gr.Dropdown(choices=["arialbd.ttf"], value="arialbd.ttf", label="الخط")
80
  color_opt = gr.ColorPicker(value="#FFFF00", label="اللون")
81
- size_opt = gr.Slider(30, 150, value=70, label="الحجم")
82
 
83
- btn_1 = gr.Button("1. استخراج"); table = gr.Dataframe(interactive=True)
84
- btn_2 = gr.Button("2. إنتاج الفيديو"); status = gr.Textbox()
85
 
86
- btn_1.click(step_1_extract_words, [v_in], [table, status])
87
  btn_2.click(step_2_render_video, [v_in, table, font_opt, color_opt, size_opt], [v_out, status])
88
 
89
- app.launch()
 
2
  os.environ["IMAGE_MAGICK_BINARY"] = "/usr/bin/convert"
3
  import gradio as gr
4
  import pandas as pd
5
+ import re
6
  from faster_whisper import WhisperModel
7
  from moviepy import VideoFileClip, TextClip, CompositeVideoClip
8
  from arabic_reshaper import reshape
 
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):
 
18
  if color_str.startswith('rgba'):
 
19
  nums = re.findall(r"\d+\.?\d*", color_str)
20
  if len(nums) >= 3:
21
  r, g, b = int(float(nums[0])), int(float(nums[1])), int(float(nums[2]))
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, "بيانات ناقصة."
39
 
 
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()