pythonmoviepy

How can i crop a video, using moviepy, and only export the cropped part without the black blackground?


ive made a function which crops a video using moviepy and ive made another algorithm to detect what coordinates to crop by using the variables top_left_crop etc this shows the output right now

BUT i want it to crop out the video and remove the black background so it would basically just be an asset and it would look like this where exported output is just the cropped video.

here is the function

def crop_video():
    global cropped_base

    print("Cropping base video...")

    cropped_base = f"{id_folder}/3cropped_base-{id}.mp4"

    if os.path.exists(cropped_base):
        print("Cropped base video already exists, importing...\n")
    
    else:
        def region_of_interest(frame):
            vertices = np.array([[top_left_crop, top_right_crop, bottom_right_crop, bottom_left_crop]], np.int32)
            mask = np.zeros_like(frame)
            cv2.fillPoly(mask, vertices, (255, 255, 255))
            return cv2.bitwise_and(frame, mask)

        clip = VideoFileClip(base_video)
        cropped_clip = clip.fl_image(region_of_interest)
        cropped_clip.write_videofile(cropped_base, audio=True, verbose=False)

        print("Cropped base video!\n")

ive tried creating a 1080x1920 white image and putting the cropped version over it but got this which is not what i want

def crop_video():
    global cropped_base

    print("Cropping base video...")

    cropped_base = f"{id_folder}/3cropped_base-{id}.mp4"

    if os.path.exists(cropped_base):
        print("Cropped base video already exists, importing...\n")
    
    else:
        def region_of_interest(frame):
            vertices = np.array([[top_left_crop, top_right_crop, bottom_right_crop, bottom_left_crop]], np.int32)
            mask = np.zeros_like(frame)
            cv2.fillPoly(mask, vertices, (255, 255, 255))
            return cv2.bitwise_and(frame, mask)

        clip = VideoFileClip(base_video)
        cropped_clip = clip.fl_image(region_of_interest)
        white_bg = ImageClip("./white_background_1080x1920.png").set_duration(cropped_clip.duration)
        cropped_clip = cropped_clip.resize(height=1080)
        cropped_clip = cropped_clip.set_position(("center", "center"))
        final = CompositeVideoClip([white_bg.set_duration(cropped_clip.duration), cropped_clip], size=(1080, 1920))

        final.write_videofile("./test.mp4", fps=clip.fps, audio_codec="aac")

        print("Cropped base video!\n")

Solution

  • I have fixed it!

    I found the midpoint and this is the test code for this

    from moviepy.editor import VideoFileClip
    
    video = VideoFileClip("./input.mp4")
    
    # Define the coordinates of the rectangle's corners
    top_left = (161, 482)
    top_right = (562, 482)
    bottom_right = (562, 881)
    bottom_left = (161, 881)
    
    # Calculate the width and height
    width = top_right[0] - top_left[0]
    height = bottom_left[1] - top_left[1]
    
    # Calculate the midpoint
    midpoint_x = int((top_left[0] + top_right[0]) / 2)
    midpoint_y = int((top_left[1] + bottom_left[1]) / 2)
    
    print(f"Width: {width}")
    print(f"Height: {height}")
    print(f"Midpoint (x, y): ({midpoint_x}, {midpoint_y})")
    
    video = video.crop(x_center=midpoint_x, y_center=midpoint_y, width=width, height=height)
    
    video.write_videofile('./output.mp4')