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
Fast and efficient media compression codecs
Does anyone knows a Python module to convert a video format
Analyzing Python Compression Libraries: zlib, LZ4, Brotli, and Zstandard
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
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.