Resized videos can take up less memory space and memory power to process large batches of videos. Smaller videos are also easy to transmit from one location to another.
Here are two important ways to resize a video in Python:
- Using moviepy
- Using FFmpeg via subprocess
To illustrate the process, I will use the following “sample.mp4” video in this practical.
The original size of the above video is (2160 X 3840). We will resize this video to (640 X 480).
Method 1: Using moviepy
The moviepy is a library designed specifically for video editing tasks such as resizing, cutting, and adding effects.
Decision Tree Diagram
As illustrated in the above decision-tree diagram, we first check if the input video file exists. If it does then load the video using the VideoFileClip() function.
Furthermore, we resized the video based on the specified height.
Atlast, save the resized video file in your output directory and close the video resources.
To implement the above diagram in the program, we need to install the “moviepy” library:
pip install moviepy
Code example
from moviepy.editor import VideoFileClip # Custom function that accepts @input_path, @output_path, @height, and @width def resize_video(input_path, output_path, width=None, height=None): try: # Loading the video clip = VideoFileClip(input_path) # Get original size original_width, original_height = clip.size print(f"Original video size: {original_width}x{original_height}") # Check if both width and height are provided for resizing if width is not None and height is not None: # Resizing the video by specifying both width and height resized_clip = clip.resize(newsize=(width, height)) elif width is not None: # Resizing based only on width (moviepy will keep the aspect ratio) resized_clip = clip.resize(width=width) elif height is not None: # Resizing based only on height (moviepy will keep the aspect ratio) resized_clip = clip.resize(height=height) else: # If neither width nor height is provided, no resizing is done resized_clip = clip # Get resized size resized_width, resized_height = resized_clip.size print(f"Resized video size: {resized_width}x{resized_height}") # Writing the result to a file resized_clip.write_videofile( output_path, codec='libx264', audio_codec='aac') print(f"Video resized successfully. Saved as '{output_path}'.") except FileNotFoundError as e: print(f"File Error: {e}") except Exception as e: print(f"An error occurred: {e}") finally: # Ensuring resources are released if 'clip' in locals(): clip.close() if 'resized_clip' in locals(): resized_clip.close() # Example usage resize_video('sample.mp4', './output/resized.mp4', width=640, height=480)
Output
Original video size: 2160x3840 Resized video size: 640x480 Moviepy - Building video ./output/resized_video.mp4. MoviePy - Writing audio in resized_videoTEMP_MPY_wvf_snd.mp4 MoviePy - Done. Moviepy - Writing video ./output/resized_video.mp4 Moviepy - Done ! Moviepy - video ready ./output/resized_video.mp4 Video resized successfully. Saved as './output/resized.mp4'.
You can see from the above output that the input video is resized to 640X480.
The moviepy library supports many video formats, codecs, and advanced editing features. However, it can be very slow for larger videos and relies on FFMpeg and other libraries. So, FFMpeg must be installed on your system in order to work with moviepy.
The time complexity is O(N) because it depends on the size of the video which is N.
The space complexity is O(N) and can take more memory if the video size is large.
Method 2: Using FFMpeg with subprocess
The FFMpeg is a robust command line to process videos and other multimedia files and Python provides a subprocess module through which you can create a command for FFMpeg that will resize the video.
Decision Tree Diagram
In the above diagram, we first checked if the file exists and if it does then we will create an FFMpeg command and execute that command that will resize the image. If the process fails then it will display the error.
import subprocess import os # Custom function to get video dimensions using ffprobe (part of FFmpeg) def get_video_dimensions(file_path): try: # Use ffprobe to get video width and height command = [ 'ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=width,height', '-of', 'csv=p=0:s=x', file_path ] # Run the ffprobe command result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Check if the command was successful if result.returncode != 0: raise Exception(f"ffprobe error: {result.stderr.decode('utf-8')}") # Extract and return the dimensions as a tuple (width, height) width, height = map(int, result.stdout.decode('utf-8').strip().split('x')) return width, height except Exception as e: print(f"An error occurred while retrieving video dimensions: {e}") return None, None # Custom function that will accept input file, output file path, new height, and new width def resize_video_ffmpeg(input_file, output_file, new_width, new_height): try: # Check if the input video file exists if not os.path.exists(input_file): raise FileNotFoundError(f"Input video file '{input_file}' not found.") # Get the original dimensions original_width, original_height = get_video_dimensions(input_file) if original_width and original_height: print(f"Original video size: {original_width}x{original_height}") # Build the FFmpeg command to resize the video command = [ 'ffmpeg', '-i', input_file, '-vf', f'scale={new_width}:{new_height}', output_file ] # Run the FFmpeg command result = subprocess.run( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Check if the FFmpeg command was successful if result.returncode != 0: raise Exception(f"FFmpeg error: {result.stderr.decode('utf-8')}") # Get the new dimensions of the resized video resized_width, resized_height = get_video_dimensions(output_file) if resized_width and resized_height: print(f"Resized video size: {resized_width}x{resized_height}") except FileNotFoundError as e: print(f"File Error: {e}") except Exception as e: print(f"An error occurred: {e}") # Calling the function resize_video_ffmpeg('sample.mp4', 'resized_ffmpeg.mp4', 640, 480)
Output
Original video size: 2160x3840 Resized video size: 640x480
The FFMpeg with subprocess approach is fast, efficient, and supports various video formats. However, the command line does not provide complete control like the moviepy library does and its behavior may vary across different operating systems.
If you want to process the video very quickly and do it in the form of batch processing then I highly recommend you to use this approach.
Time measurement for executing each approach
I ran a time-tracking experiment for each method and created a bar chart like the below image:
As you can see from the above bar chart, the fastest method is FFMpeg with a subprocess module with 4.45s and the slowest method is moviepy with 10.48s as expected.