Compress video files by Python and FFmpeg
Tools
FFmpeg is a powerful tool for video editing. And there is a great Python binding named ffmpeg-python (API Reference) for this. Firstly, pip install ffmpeg-python and install FFmpeg.
Steps
Probe the configuration of video by function ffmpeg.probe() to get duration, audio & video bit rate and so on. And calculate the bit rate of the target file based on what we have. Then, construct commands by ffmpeg.input() and ffmpeg.output(). Finally, run it.
Codes
Following is the example code. Change the compression algo for your situation if you want. For easy follow-up, I hided the code of boundary condition. The code I am using is in GitHub Gist. Any bug report is welcomed!
import os, ffmpeg
def compress_video(video_full_path, output_file_name, target_size):
# Reference: https://en.wikipedia.org/wiki/Bit_rate#Encoding_bit_rate
min_audio_bitrate = 32000
max_audio_bitrate = 256000
probe = ffmpeg.probe(video_full_path)
# Video duration, in s.
duration = float(probe['format']['duration'])
# Audio bitrate, in bps.
audio_bitrate = float(next((s for s in probe['streams'] if s['codec_type'] == 'audio'), None)['bit_rate'])
# Target total bitrate, in bps.
target_total_bitrate = (target_size * 1024 * 8) / (1.073741824 * duration)
# Target audio bitrate, in bps
if 10 * audio_bitrate > target_total_bitrate:
audio_bitrate = target_total_bitrate / 10
if audio_bitrate < min_audio_bitrate < target_total_bitrate:
audio_bitrate = min_audio_bitrate
elif audio_bitrate > max_audio_bitrate:
audio_bitrate = max_audio_bitrate
# Target video bitrate, in bps.
video_bitrate = target_total_bitrate - audio_bitrate
i = ffmpeg.input(video_full_path)
ffmpeg.output(i, os.devnull,
**{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 1, 'f': 'mp4'}
).overwrite_output().run()
ffmpeg.output(i, output_file_name,
**{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 2, 'c:a': 'aac', 'b:a': audio_bitrate}
).overwrite_output().run()
# Compress input.mp4 to 50MB and save as output.mp4
compress_video('input.mp4', 'output.mp4', 50 * 1000)
Notes
Don't waste your time! Judge the file size before compressing.
You can disable two-pass function by only keeping second
ffmpeg.output()without parameter'pass': 2.If video bit rate < 1000, it will throw exception
Bitrate is extremely low.The biggest min file size I recommend is:
# Best min size, in kB.
best_min_size = (32000 + 100000) * (1.073741824 * duration) / (8 * 1024)
- If you specify a extremely small target file size, the size of generated file maybe exceed it. For most time, this will not happen.
How to compress video to target size by Python? - Stack Overflow
compression - Compressing a video file in python with the standard library - Stack Overflow
Fast and efficient media compression codecs
Does anyone knows a Python module to convert a video format
Compress video files by Python and FFmpeg
Tools
FFmpeg is a powerful tool for video editing. And there is a great Python binding named ffmpeg-python (API Reference) for this. Firstly, pip install ffmpeg-python and install FFmpeg.
Steps
Probe the configuration of video by function ffmpeg.probe() to get duration, audio & video bit rate and so on. And calculate the bit rate of the target file based on what we have. Then, construct commands by ffmpeg.input() and ffmpeg.output(). Finally, run it.
Codes
Following is the example code. Change the compression algo for your situation if you want. For easy follow-up, I hided the code of boundary condition. The code I am using is in GitHub Gist. Any bug report is welcomed!
import os, ffmpeg
def compress_video(video_full_path, output_file_name, target_size):
# Reference: https://en.wikipedia.org/wiki/Bit_rate#Encoding_bit_rate
min_audio_bitrate = 32000
max_audio_bitrate = 256000
probe = ffmpeg.probe(video_full_path)
# Video duration, in s.
duration = float(probe['format']['duration'])
# Audio bitrate, in bps.
audio_bitrate = float(next((s for s in probe['streams'] if s['codec_type'] == 'audio'), None)['bit_rate'])
# Target total bitrate, in bps.
target_total_bitrate = (target_size * 1024 * 8) / (1.073741824 * duration)
# Target audio bitrate, in bps
if 10 * audio_bitrate > target_total_bitrate:
audio_bitrate = target_total_bitrate / 10
if audio_bitrate < min_audio_bitrate < target_total_bitrate:
audio_bitrate = min_audio_bitrate
elif audio_bitrate > max_audio_bitrate:
audio_bitrate = max_audio_bitrate
# Target video bitrate, in bps.
video_bitrate = target_total_bitrate - audio_bitrate
i = ffmpeg.input(video_full_path)
ffmpeg.output(i, os.devnull,
**{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 1, 'f': 'mp4'}
).overwrite_output().run()
ffmpeg.output(i, output_file_name,
**{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 2, 'c:a': 'aac', 'b:a': audio_bitrate}
).overwrite_output().run()
# Compress input.mp4 to 50MB and save as output.mp4
compress_video('input.mp4', 'output.mp4', 50 * 1000)
Notes
Don't waste your time! Judge the file size before compressing.
You can disable two-pass function by only keeping second
ffmpeg.output()without parameter'pass': 2.If video bit rate < 1000, it will throw exception
Bitrate is extremely low.The biggest min file size I recommend is:
# Best min size, in kB.
best_min_size = (32000 + 100000) * (1.073741824 * duration) / (8 * 1024)
- If you specify a extremely small target file size, the size of generated file maybe exceed it. For most time, this will not happen.
I have used MoviePy in the past with good results. Another option (not the safest) might be to run FFMpeg as an external process to compress or resize the media file.
» pip install CaaS
» pip install video-compressor
Video files are already compressed. You cannot compress them further, at least not significantly.
Your only option would be to decompress them, and then recompress them with a more effective compressor, e.g. HEVC.
I believe the small reduction in file size is due zlib being a lossless compression library, and mp4 is already a compressed format so there's little margin to improvement.
From the standard library, lzma claims to have the best compression ratio. But keep in mind it's also lossless so I would not expect that much difference.
I recommend you use the third-party lib ffmpeg-python. It's a wrapper for the command line application ffmpeg, which would let you transcode your mp4 using better encoders like h265.
Hello everyone!
I'm in search of the most efficient open-source compression algorithm for compressing videos and images.
I have a large collection of 1TB of images and videos that I need to upload to Google Drive. Before uploading, I want to compress them to save space.
Currently, I have written a Python script that recursively compresses files. It utilizes FFmpeg with H.265 for videos and MozJPEG for images.
In terms of space efficiency and quality preservation, the script works great. I achieve a compression rate of 60%-80% with no noticeable loss in visual quality.
However, when it comes to speed, it's quite slow. It takes more than 10 minutes to compress every 1GB of data.
Therefore, I am seeking alternative algorithms or codecs that can offer faster compression while delivering similar benefits in terms of space efficiency and quality preservation.