dream2589632147 commited on
Commit
fd6068a
·
verified ·
1 Parent(s): b4aa6ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -58
app.py CHANGED
@@ -3,48 +3,71 @@ import torch
3
  import cv2
4
  import numpy as np
5
  from PIL import Image
6
- from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, DDIMScheduler
7
  from controlnet_aux import CannyDetector
8
- from diffusers.utils import load_image
9
  import os
10
  import shutil
11
  import tempfile
12
  import datetime
13
  import ffmpeg
14
 
15
- # 1. تهيئة النموذج
 
 
16
  device = "cuda" if torch.cuda.is_available() else "cpu"
17
  torch_dtype = torch.float16 if device == "cuda" else torch.float32
18
 
 
 
 
 
19
  try:
20
- print(f"Loading models on: {device}...")
 
 
21
  controlnet_model = ControlNetModel.from_pretrained(
22
  "lllyasviel/sd-controlnet-canny", torch_dtype=torch_dtype
23
  )
 
 
24
  model_id = "runwayml/stable-diffusion-v1-5"
25
  pipe = StableDiffusionControlNetPipeline.from_pretrained(
26
  model_id, controlnet=controlnet_model, torch_dtype=torch_dtype
27
  )
28
- pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config)
 
 
 
 
 
 
29
  pipe.to(device)
30
- print("Models loaded successfully.")
 
 
 
 
 
31
  except Exception as e:
32
- print(f"Error loading models on CUDA: {e}. Switching to CPU.")
33
- controlnet_model = ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-canny")
34
- pipe = StableDiffusionControlNetPipeline.from_pretrained(model_id, controlnet=controlnet_model)
35
- pipe.to("cpu")
36
 
37
  canny_processor = CannyDetector()
38
 
39
- # 2. دالة معالجة الفيديو والنموذج
40
- def colorize_video_multistyle(video_file, reference_image_path, prompt, style_choice, steps=25):
 
 
 
 
 
41
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
42
- output_temp_video_no_audio = os.path.join(tempfile.gettempdir(), f"temp_colored_{timestamp}_no_audio.mp4")
43
- final_output_name = f"colored_output_{timestamp}.mp4"
44
 
45
- # === 1. استخراج الإطارات والصوت ===
46
- # 1.1 استخراج الصوت
47
  audio_path = os.path.join(tempfile.gettempdir(), f"temp_audio_{timestamp}.aac")
 
48
  try:
49
  (
50
  ffmpeg
@@ -54,57 +77,76 @@ def colorize_video_multistyle(video_file, reference_image_path, prompt, style_ch
54
  )
55
  audio_exists = True
56
  except ffmpeg.Error:
57
- audio_exists = False
58
- print("No audio found or extraction failed. Proceeding without audio.")
59
 
60
- # 1.2 قراءة الفيديو للإطارات
61
  cap = cv2.VideoCapture(video_file)
 
 
 
62
  fps = cap.get(cv2.CAP_PROP_FPS)
63
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
64
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
65
 
66
- # 2. تجهيز المدخلات للنموذج
 
 
 
67
  style_prompts = {
68
- "Auto Color": "photorealistic color photo, cinematic, detailed, masterpiece",
69
- "Vivid": "highly saturated, vibrant color photo, pop art colors",
70
- "Vintage": "sepia tone, old film grain, 1940s vintage look",
 
71
  }
72
- final_prompt = f"{prompt}, {style_prompts.get(style_choice, '')}"
73
- negative_prompt = "lowres, bad anatomy, bad hands, blurry, distorted, nsfw, frame, border, changed details, monochrome"
 
 
 
 
74
 
75
  colored_frames = []
76
 
77
- # 3. معالجة الإطارات (التلوين)
78
- while cap.isOpened():
 
79
  ret, frame = cap.read()
80
  if not ret:
81
  break
82
 
 
83
  pil_image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
 
 
84
  canny_image = canny_processor(pil_image)
85
 
86
- image_out = pipe(
87
- prompt=final_prompt,
88
- negative_prompt=negative_prompt,
89
- image=canny_image,
90
- num_inference_steps=steps,
91
- guidance_scale=7.5
92
- ).images[0]
 
 
 
93
 
 
94
  colored_frames.append(np.array(image_out))
95
 
96
  cap.release()
97
 
98
- # 4. تجميع الإطارات في فيديو مؤقت (MP4) باستخدام OpenCV
99
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
100
  out = cv2.VideoWriter(output_temp_video_no_audio, fourcc, fps, (width, height))
101
 
102
  for frame in colored_frames:
 
103
  out.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
104
 
105
  out.release()
106
 
107
- # 5. دمج الفيديو الملون مع الصوت الأصلي باستخدام FFMPEG-Python
108
  if audio_exists:
109
  try:
110
  (
@@ -113,32 +155,49 @@ def colorize_video_multistyle(video_file, reference_image_path, prompt, style_ch
113
  .output(ffmpeg.input(audio_path).audio, final_output_name, vcodec='copy', acodec='copy')
114
  .run(overwrite_output=True, quiet=True)
115
  )
116
- except ffmpeg.Error as e:
117
- print(f"FFMPEG merge failed: {e.stderr.decode('utf8')}")
118
- shutil.copy(output_temp_video_no_audio, final_output_name) # العودة إلى الفيديو بدون صوت
119
  else:
120
  shutil.copy(output_temp_video_no_audio, final_output_name)
121
 
122
- # 6. تنظيف الملفات المؤقتة
123
- if os.path.exists(audio_path):
124
- os.remove(audio_path)
125
-
126
  return final_output_name
127
 
128
- # 3. واجهة Gradio النهائية
129
- iface = gr.Interface(
130
- fn=colorize_video_multistyle,
131
- inputs=[
132
- gr.Video(label="ملف الفيديو (إلزامي)"),
133
- gr.Image(label="الصورة المرجعية (لنقل الألوان)", type="filepath"),
134
- gr.Textbox(label="المطالبة النصية (لتوجيه التلوين)", value=""),
135
- gr.Dropdown(["Auto Color", "Vivid", "Vintage"], label="اختيار النمط المسبق", value="Auto Color"),
136
- gr.Slider(minimum=10, maximum=50, step=5, value=25, label="خطوات التوليد")
137
- ],
138
- outputs=gr.Video(label="الفيديو الملون (MP4)"),
139
- title="🎨 Multi-Style Video Colorizer",
140
- description="تلوين احترافي للفيديو باستخدام ControlNet."
141
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  if __name__ == "__main__":
144
- iface.launch(server_name="0.0.0.0", server_port=7860)
 
3
  import cv2
4
  import numpy as np
5
  from PIL import Image
6
+ from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, LCMScheduler
7
  from controlnet_aux import CannyDetector
 
8
  import os
9
  import shutil
10
  import tempfile
11
  import datetime
12
  import ffmpeg
13
 
14
+ # ==========================================
15
+ # 1. إعدادات الجهاز والنموذج (مع تسريع LCM)
16
+ # ==========================================
17
  device = "cuda" if torch.cuda.is_available() else "cpu"
18
  torch_dtype = torch.float16 if device == "cuda" else torch.float32
19
 
20
+ print(f"🚀 Running on: {device}")
21
+ if device == "cpu":
22
+ print("⚠️ تحذير: المعالجة ستكون بطيئة جداً على CPU. يرجى تفعيل GPU من إعدادات Hugging Face.")
23
+
24
  try:
25
+ print("Loading ControlNet & SD Models...")
26
+
27
+ # تحميل ControlNet
28
  controlnet_model = ControlNetModel.from_pretrained(
29
  "lllyasviel/sd-controlnet-canny", torch_dtype=torch_dtype
30
  )
31
+
32
+ # تحميل Stable Diffusion 1.5
33
  model_id = "runwayml/stable-diffusion-v1-5"
34
  pipe = StableDiffusionControlNetPipeline.from_pretrained(
35
  model_id, controlnet=controlnet_model, torch_dtype=torch_dtype
36
  )
37
+
38
+ # === الخطوة السحرية للسرعة (LCM-LoRA) ===
39
+ print("⚡ Injecting LCM-LoRA for speed...")
40
+ pipe.load_lora_weights("latent-consistency/lcm-lora-sdv1-5")
41
+ pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
42
+ # =========================================
43
+
44
  pipe.to(device)
45
+ # تفعيل تحسينات الذاكرة إذا كنا على GPU
46
+ if device == "cuda":
47
+ pipe.enable_attention_slicing()
48
+
49
+ print("✅ Models loaded successfully with LCM Acceleration.")
50
+
51
  except Exception as e:
52
+ print(f"Error loading models: {e}")
53
+ raise e
 
 
54
 
55
  canny_processor = CannyDetector()
56
 
57
+ # ==========================================
58
+ # 2. دالة المعالجة الأساسية
59
+ # ==========================================
60
+ def colorize_video_multistyle(video_file, prompt, style_choice, steps=5):
61
+ if not video_file:
62
+ return None
63
+
64
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
65
+ output_temp_video_no_audio = os.path.join(tempfile.gettempdir(), f"temp_vis_{timestamp}.mp4")
66
+ final_output_name = f"colored_lcm_{timestamp}.mp4"
67
 
68
+ # --- استخراج الصوت ---
 
69
  audio_path = os.path.join(tempfile.gettempdir(), f"temp_audio_{timestamp}.aac")
70
+ audio_exists = False
71
  try:
72
  (
73
  ffmpeg
 
77
  )
78
  audio_exists = True
79
  except ffmpeg.Error:
80
+ print("⚠️ Warning: No audio found or extraction failed.")
 
81
 
82
+ # --- قراءة الفيديو ---
83
  cap = cv2.VideoCapture(video_file)
84
+ if not cap.isOpened():
85
+ return None
86
+
87
  fps = cap.get(cv2.CAP_PROP_FPS)
88
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
89
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
90
 
91
+ # تحديد عدد الإطارات للمعالجة (لتجنب التوقف في الفيديوهات الطويلة جداً في النسخة التجريبية)
92
+ # total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
93
+
94
+ # تجهيز البرومبت
95
  style_prompts = {
96
+ "Auto Color": "photorealistic, 8k, masterpiece, cinematic lighting",
97
+ "Vivid": "vibrant colors, high saturation, pop art style, colorful",
98
+ "Vintage": "sepia, 1950s film look, grain, nostalgia",
99
+ "Cyberpunk": "neon lights, cyberpunk, blue and pink hues, futuristic"
100
  }
101
+
102
+ # إضافة "colorized" للبرومبت لتعزيز التلوين
103
+ full_prompt = f"{prompt}, {style_prompts.get(style_choice, '')}, colorized video"
104
+
105
+ # البرومبت السلبي (مهم جداً)
106
+ negative_prompt = "black and white, monochrome, greyscale, low quality, blurry, distorted, nsfw, watermark"
107
 
108
  colored_frames = []
109
 
110
+ print("🎬 Starting Frame Processing...")
111
+
112
+ while True:
113
  ret, frame = cap.read()
114
  if not ret:
115
  break
116
 
117
+ # تحويل من BGR (OpenCV) إلى RGB (PIL)
118
  pil_image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
119
+
120
+ # استخراج الحواف (Canny)
121
  canny_image = canny_processor(pil_image)
122
 
123
+ # المعالجة باستخدام LCM (لاحظ guidance_scale المنخفض)
124
+ with torch.inference_mode():
125
+ image_out = pipe(
126
+ prompt=full_prompt,
127
+ negative_prompt=negative_prompt,
128
+ image=canny_image,
129
+ num_inference_steps=steps, # LCM يحتاج خطوات قليلة (4-8)
130
+ guidance_scale=1.5, # LCM يحتاج قيمة منخفضة (بين 1.0 و 2.0)
131
+ controlnet_conditioning_scale=1.0
132
+ ).images[0]
133
 
134
+ # تحويل النتيجة لـ NumPy
135
  colored_frames.append(np.array(image_out))
136
 
137
  cap.release()
138
 
139
+ # --- تجميع الفيديو ---
140
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
141
  out = cv2.VideoWriter(output_temp_video_no_audio, fourcc, fps, (width, height))
142
 
143
  for frame in colored_frames:
144
+ # تحويل من RGB إلى BGR للكتابة
145
  out.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
146
 
147
  out.release()
148
 
149
+ # --- دمج الصوت (إن وجد) ---
150
  if audio_exists:
151
  try:
152
  (
 
155
  .output(ffmpeg.input(audio_path).audio, final_output_name, vcodec='copy', acodec='copy')
156
  .run(overwrite_output=True, quiet=True)
157
  )
158
+ except ffmpeg.Error:
159
+ shutil.copy(output_temp_video_no_audio, final_output_name)
 
160
  else:
161
  shutil.copy(output_temp_video_no_audio, final_output_name)
162
 
163
+ # تنظيف
164
+ if os.path.exists(audio_path): os.remove(audio_path)
165
+
 
166
  return final_output_name
167
 
168
+ # ==========================================
169
+ # 3. واجهة Gradio
170
+ # ==========================================
171
+ custom_css = """
172
+ #col-container {max-width: 700px; margin-left: auto; margin-right: auto;}
173
+ """
174
+
175
+ with gr.Blocks(css=custom_css, title="Turbo Video Colorizer") as demo:
176
+ with gr.Column(elem_id="col-container"):
177
+ gr.Markdown("# ⚡ Turbo Video Colorizer (LCM Accelerated)")
178
+ gr.Markdown("تلوين الفيديو بسرعة عالية باستخدام تقنية LCM-LoRA.")
179
+
180
+ with gr.Row():
181
+ video_input = gr.Video(label="رفع الف��ديو (يفضل فيديو قصير)")
182
+
183
+ with gr.Row():
184
+ prompt_input = gr.Textbox(label="وصف المشهد (اختياري)", placeholder="مثال: A man walking in the street")
185
+ style_dropdown = gr.Dropdown(
186
+ ["Auto Color", "Vivid", "Vintage", "Cyberpunk"],
187
+ label="النمط", value="Auto Color"
188
+ )
189
+
190
+ # LCM يحتاج خطوات قليلة، لذا قللنا الحد الأقصى
191
+ steps_slider = gr.Slider(minimum=4, maximum=12, step=1, value=5, label="الخطوات (Steps) - 5 هي الأفضل للسرعة")
192
+
193
+ submit_btn = gr.Button("🎨 تلوين الفيديو الآن", variant="primary")
194
+ video_output = gr.Video(label="النتيجة")
195
+
196
+ submit_btn.click(
197
+ fn=colorize_video_multistyle,
198
+ inputs=[video_input, prompt_input, style_dropdown, steps_slider],
199
+ outputs=video_output
200
+ )
201
 
202
  if __name__ == "__main__":
203
+ demo.launch(server_name="0.0.0.0", server_port=7860)