| 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"]) |
| |
| |
| if step.get("end"): |
| video = video.subclip(step["start"], step["end"]) |
| else: |
| video = video.subclip(step["start"]) |
| |
| |
| video = video.set_fps(target_fps) |
| |
| |
| target_width, target_height = target_resolution |
| target_aspect = target_width / target_height |
| video_aspect = video.w / video.h |
| |
| |
| if abs(video_aspect - target_aspect) > 0.01: |
| print("I'm here in abs") |
| if video_aspect > target_aspect: |
| |
| print("I'm here in video aspect >") |
| new_width = int(target_height * video_aspect) |
| video = video.resize(height=target_height) |
| |
| 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") |
| |
| new_height = int(target_width / video_aspect) |
| video = video.resize(width=target_width) |
| |
| 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 = video.resize(target_resolution) |
| |
| |
| 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. |
| """ |
| |
| width_ratio, height_ratio = map(int, aspect_ratio.split(":")) |
| target_aspect = width_ratio / height_ratio |
| |
| |
| target_height = 1920 |
| target_width = int(target_height * target_aspect) |
| target_resolution = (target_width, target_height) |
| |
| |
| final_clip = concatenate_videoclips(subclips, method="compose") |
| |
| |
| random_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8)) |
| file_name = f"edited_videos/video_edited{random_string}.mp4" |
| |
| |
| final_clip.write_videofile( |
| file_name, |
| codec='libx264', |
| audio_codec='aac', |
| fps=30, |
| preset='medium', |
| ffmpeg_params=['-pix_fmt', 'yuv420p', '-aspect', aspect_ratio], |
| verbose=False, |
| temp_audiofile=f"temp_audio_{random_string}.m4a", |
| ) |
| |
| |
| final_clip.close() |
| |
| |
| |
| return file_name |
|
|
|
|
|
|
|
|
|
|
| if __name__ == "__main__": |
| file_path = '/Users/georgia.bucea/products/ShortsAI/all_files_metadata.json' |
|
|
| 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) |
|
|
| |
|
|
| get_final_video(all_videos) |
|
|
|
|