from moviepy.editor import VideoFileClip, concatenate_videoclips,ColorClip,CompositeVideoClip from find_steps import find_all_steps import json import random import string step={ "path" :"/Users/georgia.bucea/products/ShortsAI/21_aug/IMG_8299.MOV", "start":0.0, "end": '', } def crop_video(step, target_resolution=(1080, 1920), target_fps=30): """ Crop a video clip to the specified start and end times, and resize to target resolution while maintaining the original aspect ratio with padding if necessary. Args: step (dict): Dictionary with 'path', 'start', and 'end' keys. target_resolution (tuple): Desired output resolution (width, height). target_fps (int): Desired frame rate for the output video. Returns: VideoClip: Cropped and resized video clip with preserved audio. """ video = VideoFileClip(step["path"]) # Crop the video based on start and end times if step.get("end"): video = video.subclip(step["start"], step["end"]) else: video = video.subclip(step["start"]) # Set consistent frame rate video = video.set_fps(target_fps) # Calculate target aspect ratio target_width, target_height = target_resolution target_aspect = target_width / target_height video_aspect = video.w / video.h # Resize or pad to match target resolution while preserving aspect ratio if abs(video_aspect - target_aspect) > 0.01: # Allow small tolerance print("I'm here in abs") if video_aspect > target_aspect: # Video is wider than target: scale to match height, add black bars on sides print("I'm here in video aspect >") new_width = int(target_height * video_aspect) video = video.resize(height=target_height) # Create a background clip with black padding background = ColorClip(size=(target_width, target_height), color=(0, 0, 0)) video = video.set_position(("center", "center")).on_color(size=(target_width, target_height), color=(0, 0, 0)) else: print("I'm here in video aspect") # Video is taller than target: scale to match width, add black bars on top/bottom new_height = int(target_width / video_aspect) video = video.resize(width=target_width) # Create a background clip with black padding background = ColorClip(size=(target_width, target_height), color=(0, 0, 0)) video = video.set_position(("center", "center")).on_color(size=(target_width, target_height), color=(0, 0, 0)) else: print("I'm here in video aspect") # Aspect ratio matches, resize directly video = video.resize(target_resolution) # Ensure audio is preserved if video.audio is None: print(f"Warning: No audio in {step['path']}") return video def get_final_video(subclips, aspect_ratio="9:16"): """ Concatenate video clips and save the final video with consistent resolution and audio. Args: subclips (list): List of VideoClip objects. aspect_ratio (str): Desired aspect ratio (e.g., '9:16'). Returns: str: Path to the saved video file. """ # Parse aspect ratio width_ratio, height_ratio = map(int, aspect_ratio.split(":")) target_aspect = width_ratio / height_ratio # Set target resolution (e.g., 1080x1920 for 9:16) target_height = 1920 # Standard for vertical videos target_width = int(target_height * target_aspect) target_resolution = (target_width, target_height) # Concatenate clips final_clip = concatenate_videoclips(subclips, method="compose") # Generate unique filename random_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8)) file_name = f"edited_videos/video_edited{random_string}.mp4" # Changed to .mp4 for compatibility # Write the final video file final_clip.write_videofile( file_name, codec='libx264', audio_codec='aac', fps=30, # Consistent frame rate preset='medium', ffmpeg_params=['-pix_fmt', 'yuv420p', '-aspect', aspect_ratio], # Ensure compatibility with most players verbose=False, temp_audiofile=f"temp_audio_{random_string}.m4a", # Explicit temp audio file ) # Close clips to free memory final_clip.close() # for clip in sub: # clip.close() return file_name if __name__ == "__main__": file_path = '/Users/georgia.bucea/products/ShortsAI/all_files_metadata.json' # Update this with the actual file path context = """I am putting stuff in a car, with pipes and a guy in a red shirt. I am walking past a band with a DJ. I am explaining something on the phone""" with open(file_path, 'r') as file: data = json.load(file) steps=find_all_steps(data,context) all_videos=[] for step in steps: v=crop_video(step) all_videos.append(v) # v=crop_video(step) get_final_video(all_videos)