AutoCaptionPro / app.py
kader1997's picture
Update app.py
0561398 verified
import os
os.environ["IMAGE_MAGICK_BINARY"] = "/usr/bin/convert"
import gradio as gr
import pandas as pd
import re
from faster_whisper import WhisperModel
from moviepy import VideoFileClip, TextClip, CompositeVideoClip
from arabic_reshaper import reshape
# --- الإعدادات ---
model = WhisperModel("large-v3", device="cpu", compute_type="int8")
def process_arabic_text(text):
if not text: return ""
# 1. إعادة تشكيل الحروف العربية لتظهر متصلة وصحيحة (بدون النقاط الإضافية •)
reshaped = reshape(text)
# 2. إضافة سطر فارغ في الأسفل لمنع قص النقاط السفلية للأحرف
return reshaped + "\n "
def clean_color(color_str):
if color_str.startswith('rgba'):
nums = re.findall(r"\d+\.?\d*", color_str)
if len(nums) >= 3:
r, g, b = int(float(nums[0])), int(float(nums[1])), int(float(nums[2]))
return f'rgb({r},{g},{b})'
return color_str
def step_1_extract_words(video_path, progress=gr.Progress()):
if not video_path: return None, "الرجاء رفع فيديو."
segments, _ = model.transcribe(video_path, word_timestamps=True, language="ar")
words_data = []
for segment in segments:
for word in segment.words:
words_data.append([word.word.strip(), round(word.start, 2), round(word.end, 2)])
return pd.DataFrame(words_data, columns=["الكلمة", "البداية", "النهاية"]), "تم استخراج الكلمات!"
def step_2_render_video(video_path, df_edited, font_selection, text_color, font_size, progress=gr.Progress()):
if video_path is None or df_edited is None: return None, "بيانات ناقصة."
safe_color = clean_color(text_color)
actual_font = font_selection if os.path.exists(font_selection) else "DejaVu-Sans-Bold"
output_path = "final_clean_text_video.mp4"
video = VideoFileClip(video_path)
w, h = video.size
clips = [video]
words_list = df_edited.values.tolist()
for row in words_list:
word_text = str(row[0])
t_start = float(row[1])
t_end = float(row[2])
if not word_text.strip(): continue
clean_word = process_arabic_text(word_text)
txt = TextClip(
text=clean_word,
font_size=int(font_size),
color=safe_color,
stroke_color='black',
stroke_width=2.0, # تقليل سمك التحديد قليلاً ليتناسب مع النص الأصغر
font=actual_font,
method='label'
).with_start(t_start).with_duration(max(0.1, t_end - t_start)).with_position(('center', int(h * 0.5)))
clips.append(txt)
final = CompositeVideoClip(clips, size=(w, h))
final.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=video.fps, logger='bar')
return output_path, "تم إنتاج الفيديو بنجاح!"
# --- الواجهة ---
with gr.Blocks() as app:
gr.Markdown("## 🎬 محرر الفيديو: نصوص نظيفة")
with gr.Row():
v_in = gr.Video(); v_out = gr.Video()
with gr.Row():
font_opt = gr.Dropdown(choices=["arialbd.ttf"], value="arialbd.ttf", label="الخط")
color_opt = gr.ColorPicker(value="#FF8C00", label="لون ذهبي برتقالي")
# تم تصغير الحجم الافتراضي من 130 إلى 90
size_opt = gr.Slider(30, 200, value=90, label="حجم النص")
btn_1 = gr.Button("1. تحليل الكلمات"); table = gr.Dataframe(interactive=True)
btn_2 = gr.Button("2. إنتاج الفيديو"); status = gr.Textbox()
btn_1.click(step_1_extract_words, [v_in], [table, status])
btn_2.click(step_2_render_video, [v_in, table, font_opt, color_opt, size_opt], [v_out, status])
app.launch()