# core/visual_engine.py from PIL import Image, ImageDraw, ImageFont from moviepy.editor import ImageClip, concatenate_videoclips import os class VisualEngine: def __init__(self, output_dir="generated_media"): self.output_dir = output_dir os.makedirs(self.output_dir, exist_ok=True) try: # Try to load a common font, adjust path or font name if needed self.font = ImageFont.truetype("arial.ttf", 24) except IOError: self.font = ImageFont.load_default() # Fallback def create_placeholder_image(self, text_description, filename, size=(1280, 720)): img = Image.new('RGB', size, color = (73, 109, 137)) # Blueish background d = ImageDraw.Draw(img) # Simple text wrapping lines = [] words = text_description.split() current_line = "" for word in words: if d.textlength(current_line + word + " ", font=self.font) <= size[0] - 40: # 20px padding current_line += word + " " else: lines.append(current_line) current_line = word + " " lines.append(current_line) y_text = (size[1] - len(lines) * (self.font.size + 5)) / 2 # Center text block vertically for line in lines: text_width = d.textlength(line, font=self.font) d.text((size[0]-text_width)/2, y_text, line, fill=(255,255,0), font=self.font) y_text += self.font.size + 5 # Line spacing filepath = os.path.join(self.output_dir, filename) img.save(filepath) return filepath def create_video_from_images(self, image_paths, output_filename="final_video.mp4", fps=1, duration_per_image=3): if not image_paths: print("No images provided to create video.") return None clips = [ImageClip(m).set_duration(duration_per_image) for m in image_paths] if not clips: print("Could not create ImageClips.") return None video_clip = concatenate_videoclips(clips, method="compose") output_path = os.path.join(self.output_dir, output_filename) video_clip.write_videofile(output_path, fps=fps) return output_path