Update core/visual_engine.py
Browse files- core/visual_engine.py +55 -0
core/visual_engine.py
CHANGED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# core/visual_engine.py
|
2 |
+
from PIL import Image, ImageDraw, ImageFont
|
3 |
+
from moviepy.editor import ImageClip, concatenate_videoclips
|
4 |
+
import os
|
5 |
+
|
6 |
+
class VisualEngine:
|
7 |
+
def __init__(self, output_dir="generated_media"):
|
8 |
+
self.output_dir = output_dir
|
9 |
+
os.makedirs(self.output_dir, exist_ok=True)
|
10 |
+
try:
|
11 |
+
# Try to load a common font, adjust path or font name if needed
|
12 |
+
self.font = ImageFont.truetype("arial.ttf", 24)
|
13 |
+
except IOError:
|
14 |
+
self.font = ImageFont.load_default() # Fallback
|
15 |
+
|
16 |
+
def create_placeholder_image(self, text_description, filename, size=(1280, 720)):
|
17 |
+
img = Image.new('RGB', size, color = (73, 109, 137)) # Blueish background
|
18 |
+
d = ImageDraw.Draw(img)
|
19 |
+
|
20 |
+
# Simple text wrapping
|
21 |
+
lines = []
|
22 |
+
words = text_description.split()
|
23 |
+
current_line = ""
|
24 |
+
for word in words:
|
25 |
+
if d.textlength(current_line + word + " ", font=self.font) <= size[0] - 40: # 20px padding
|
26 |
+
current_line += word + " "
|
27 |
+
else:
|
28 |
+
lines.append(current_line)
|
29 |
+
current_line = word + " "
|
30 |
+
lines.append(current_line)
|
31 |
+
|
32 |
+
y_text = (size[1] - len(lines) * (self.font.size + 5)) / 2 # Center text block vertically
|
33 |
+
for line in lines:
|
34 |
+
text_width = d.textlength(line, font=self.font)
|
35 |
+
d.text((size[0]-text_width)/2, y_text, line, fill=(255,255,0), font=self.font)
|
36 |
+
y_text += self.font.size + 5 # Line spacing
|
37 |
+
|
38 |
+
filepath = os.path.join(self.output_dir, filename)
|
39 |
+
img.save(filepath)
|
40 |
+
return filepath
|
41 |
+
|
42 |
+
def create_video_from_images(self, image_paths, output_filename="final_video.mp4", fps=1, duration_per_image=3):
|
43 |
+
if not image_paths:
|
44 |
+
print("No images provided to create video.")
|
45 |
+
return None
|
46 |
+
|
47 |
+
clips = [ImageClip(m).set_duration(duration_per_image) for m in image_paths]
|
48 |
+
if not clips:
|
49 |
+
print("Could not create ImageClips.")
|
50 |
+
return None
|
51 |
+
|
52 |
+
video_clip = concatenate_videoclips(clips, method="compose")
|
53 |
+
output_path = os.path.join(self.output_dir, output_filename)
|
54 |
+
video_clip.write_videofile(output_path, fps=fps)
|
55 |
+
return output_path
|