No articles found
Try different keywords or browse our categories
Python FFMPEG Integration: Edit Videos in Terminal
Master video editing from the command line using Python and FFmpeg. Learn to trim, merge, compress, and manipulate videos programmatically.
FFmpeg is the industry-standard tool for video processing, and when combined with Python, it becomes a powerful automation engine for video editing tasks. This tutorial shows you how to leverage FFmpeg from Python scripts to edit videos directly from the terminal.
Why FFmpeg with Python?
Combining FFmpeg with Python is perfect for:
- Automating video processing workflows
- Batch processing multiple video files
- Server-side video manipulation without GUI tools
- Building video processing pipelines
- Creating custom video editing tools
Prerequisites
First, install FFmpeg on your system:
macOS:
brew install ffmpeg
Ubuntu/Debian:
sudo apt update
sudo apt install ffmpeg
Windows: Download from ffmpeg.org and add to PATH.
Then install the Python wrapper:
pip install ffmpeg-python
For a simpler subprocess approach, FFmpeg is all you need.
Basic FFmpeg Commands from Python
Let’s start with running FFmpeg commands using Python’s subprocess module:
# basic_ffmpeg.py
import subprocess
import sys
def run_ffmpeg_command(command):
"""Execute FFmpeg command and handle output."""
try:
result = subprocess.run(
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True
)
print("Success!")
return result
except subprocess.CalledProcessError as e:
print(f"Error: {e.stderr}")
sys.exit(1)
def get_video_info(input_file):
"""Get video information using ffprobe."""
command = [
'ffprobe',
'-v', 'quiet',
'-print_format', 'json',
'-show_format',
'-show_streams',
input_file
]
result = subprocess.run(
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
print(result.stdout)
if __name__ == "__main__":
get_video_info("input.mp4")
Trimming Videos
Cut a specific portion from a video:
# trim_video.py
import subprocess
import argparse
def trim_video(input_file, output_file, start_time, duration):
"""
Trim video to specific duration.
Args:
input_file: Input video path
output_file: Output video path
start_time: Start time (format: HH:MM:SS or seconds)
duration: Duration in seconds or HH:MM:SS format
"""
command = [
'ffmpeg',
'-i', input_file,
'-ss', start_time,
'-t', str(duration),
'-c:v', 'libx264',
'-c:a', 'aac',
'-y', # Overwrite output file
output_file
]
print(f"Trimming video from {start_time} for {duration} seconds...")
try:
subprocess.run(command, check=True)
print(f"Video trimmed successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error trimming video: {e}")
def main():
parser = argparse.ArgumentParser(description='Trim video using FFmpeg')
parser.add_argument('--input', required=True, help='Input video file')
parser.add_argument('--output', required=True, help='Output video file')
parser.add_argument('--start', required=True, help='Start time (HH:MM:SS or seconds)')
parser.add_argument('--duration', required=True, help='Duration (seconds or HH:MM:SS)')
args = parser.parse_args()
trim_video(args.input, args.output, args.start, args.duration)
if __name__ == "__main__":
main()
Usage:
python trim_video.py --input video.mp4 --output trimmed.mp4 --start 00:00:10 --duration 30
Merging Multiple Videos
Concatenate multiple video files:
# merge_videos.py
import subprocess
import os
def merge_videos(video_list, output_file):
"""
Merge multiple videos into one.
Args:
video_list: List of video file paths
output_file: Output merged video path
"""
# Create a temporary file list for FFmpeg
list_file = 'video_list.txt'
with open(list_file, 'w') as f:
for video in video_list:
# Write in FFmpeg concat format
f.write(f"file '{video}'\n")
command = [
'ffmpeg',
'-f', 'concat',
'-safe', '0',
'-i', list_file,
'-c', 'copy',
'-y',
output_file
]
print(f"Merging {len(video_list)} videos...")
try:
subprocess.run(command, check=True)
print(f"Videos merged successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error merging videos: {e}")
finally:
# Clean up temporary file
if os.path.exists(list_file):
os.remove(list_file)
if __name__ == "__main__":
videos = ['video1.mp4', 'video2.mp4', 'video3.mp4']
merge_videos(videos, 'merged_output.mp4')
Compressing Videos
Reduce video file size while maintaining quality:
# compress_video.py
import subprocess
import os
import argparse
def get_file_size_mb(file_path):
"""Get file size in MB."""
return os.path.getsize(file_path) / (1024 * 1024)
def compress_video(input_file, output_file, crf=23):
"""
Compress video using H.264 codec.
Args:
input_file: Input video path
output_file: Output video path
crf: Constant Rate Factor (18-28, lower = better quality)
"""
command = [
'ffmpeg',
'-i', input_file,
'-c:v', 'libx264',
'-crf', str(crf),
'-preset', 'medium',
'-c:a', 'aac',
'-b:a', '128k',
'-y',
output_file
]
original_size = get_file_size_mb(input_file)
print(f"Compressing video (CRF: {crf})...")
print(f"Original size: {original_size:.2f} MB")
try:
subprocess.run(command, check=True)
compressed_size = get_file_size_mb(output_file)
compression_ratio = (1 - compressed_size/original_size) * 100
print(f"Compressed size: {compressed_size:.2f} MB")
print(f"Compression: {compression_ratio:.1f}% reduction")
print(f"Video compressed successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error compressing video: {e}")
def main():
parser = argparse.ArgumentParser(description='Compress video using FFmpeg')
parser.add_argument('--input', required=True, help='Input video file')
parser.add_argument('--output', required=True, help='Output video file')
parser.add_argument('--crf', type=int, default=23, help='CRF value (18-28)')
args = parser.parse_args()
compress_video(args.input, args.output, args.crf)
if __name__ == "__main__":
main()
Converting Video Formats
Convert between different video formats:
# convert_format.py
import subprocess
import argparse
def convert_video_format(input_file, output_file, codec='libx264'):
"""
Convert video to different format.
Args:
input_file: Input video path
output_file: Output video path
codec: Video codec (libx264, libx265, libvpx-vp9)
"""
command = [
'ffmpeg',
'-i', input_file,
'-c:v', codec,
'-c:a', 'aac',
'-strict', 'experimental',
'-y',
output_file
]
print(f"Converting {input_file} to {output_file}...")
try:
subprocess.run(command, check=True)
print(f"Video converted successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error converting video: {e}")
def main():
parser = argparse.ArgumentParser(description='Convert video format')
parser.add_argument('--input', required=True, help='Input video file')
parser.add_argument('--output', required=True, help='Output video file')
parser.add_argument('--codec', default='libx264', help='Video codec')
args = parser.parse_args()
convert_video_format(args.input, args.output, args.codec)
if __name__ == "__main__":
main()
Extracting Audio from Video
Extract audio track to a separate file:
# extract_audio.py
import subprocess
import argparse
def extract_audio(input_file, output_file, format='mp3'):
"""
Extract audio from video file.
Args:
input_file: Input video path
output_file: Output audio path
format: Audio format (mp3, aac, wav)
"""
command = [
'ffmpeg',
'-i', input_file,
'-vn', # No video
'-acodec', 'libmp3lame' if format == 'mp3' else format,
'-q:a', '2', # Quality (0-9, lower is better)
'-y',
output_file
]
print(f"Extracting audio from {input_file}...")
try:
subprocess.run(command, check=True)
print(f"Audio extracted successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error extracting audio: {e}")
def main():
parser = argparse.ArgumentParser(description='Extract audio from video')
parser.add_argument('--input', required=True, help='Input video file')
parser.add_argument('--output', required=True, help='Output audio file')
parser.add_argument('--format', default='mp3', help='Audio format')
args = parser.parse_args()
extract_audio(args.input, args.output, args.format)
if __name__ == "__main__":
main()
Adding Watermark to Video
Overlay an image or text watermark:
# add_watermark.py
import subprocess
import argparse
def add_image_watermark(input_file, watermark_image, output_file, position='bottom-right'):
"""
Add image watermark to video.
Args:
input_file: Input video path
watermark_image: Watermark image path (PNG with transparency)
output_file: Output video path
position: Watermark position (top-left, top-right, bottom-left, bottom-right)
"""
# Position mapping
positions = {
'top-left': '10:10',
'top-right': 'main_w-overlay_w-10:10',
'bottom-left': '10:main_h-overlay_h-10',
'bottom-right': 'main_w-overlay_w-10:main_h-overlay_h-10'
}
overlay_position = positions.get(position, positions['bottom-right'])
command = [
'ffmpeg',
'-i', input_file,
'-i', watermark_image,
'-filter_complex', f'[1:v]scale=100:-1[wm];[0:v][wm]overlay={overlay_position}',
'-c:a', 'copy',
'-y',
output_file
]
print(f"Adding watermark to video ({position})...")
try:
subprocess.run(command, check=True)
print(f"Watermark added successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error adding watermark: {e}")
def add_text_watermark(input_file, text, output_file):
"""Add text watermark to video."""
command = [
'ffmpeg',
'-i', input_file,
'-vf', f"drawtext=text='{text}':fontsize=24:fontcolor=white:x=10:y=10:box=1:boxcolor=black@0.5:boxborderw=5",
'-c:a', 'copy',
'-y',
output_file
]
print(f"Adding text watermark: {text}")
try:
subprocess.run(command, check=True)
print(f"Text watermark added successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error adding text watermark: {e}")
def main():
parser = argparse.ArgumentParser(description='Add watermark to video')
parser.add_argument('--input', required=True, help='Input video file')
parser.add_argument('--output', required=True, help='Output video file')
parser.add_argument('--image', help='Watermark image file')
parser.add_argument('--text', help='Watermark text')
parser.add_argument('--position', default='bottom-right', help='Watermark position')
args = parser.parse_args()
if args.image:
add_image_watermark(args.input, args.image, args.output, args.position)
elif args.text:
add_text_watermark(args.input, args.text, args.output)
else:
print("Error: Provide either --image or --text")
if __name__ == "__main__":
main()
Creating Thumbnails
Extract frames as thumbnails:
# create_thumbnails.py
import subprocess
import argparse
def create_thumbnail(input_file, output_file, timestamp='00:00:01'):
"""
Extract frame as thumbnail.
Args:
input_file: Input video path
output_file: Output image path
timestamp: Time to extract frame (HH:MM:SS)
"""
command = [
'ffmpeg',
'-i', input_file,
'-ss', timestamp,
'-vframes', '1',
'-q:v', '2',
'-y',
output_file
]
print(f"Creating thumbnail at {timestamp}...")
try:
subprocess.run(command, check=True)
print(f"Thumbnail created successfully: {output_file}")
except subprocess.CalledProcessError as e:
print(f"Error creating thumbnail: {e}")
def create_multiple_thumbnails(input_file, output_pattern, interval=5):
"""
Create multiple thumbnails at intervals.
Args:
input_file: Input video path
output_pattern: Output pattern (e.g., 'thumb_%03d.jpg')
interval: Interval in seconds between thumbnails
"""
command = [
'ffmpeg',
'-i', input_file,
'-vf', f'fps=1/{interval}',
'-q:v', '2',
'-y',
output_pattern
]
print(f"Creating thumbnails every {interval} seconds...")
try:
subprocess.run(command, check=True)
print(f"Thumbnails created successfully: {output_pattern}")
except subprocess.CalledProcessError as e:
print(f"Error creating thumbnails: {e}")
def main():
parser = argparse.ArgumentParser(description='Create video thumbnails')
parser.add_argument('--input', required=True, help='Input video file')
parser.add_argument('--output', required=True, help='Output file or pattern')
parser.add_argument('--timestamp', default='00:00:01', help='Timestamp for single thumbnail')
parser.add_argument('--interval', type=int, help='Interval for multiple thumbnails')
args = parser.parse_args()
if args.interval:
create_multiple_thumbnails(args.input, args.output, args.interval)
else:
create_thumbnail(args.input, args.output, args.timestamp)
if __name__ == "__main__":
main()
Batch Processing Videos
Process multiple videos automatically:
# batch_processor.py
import subprocess
import os
import glob
class VideoProcessor:
"""Batch video processing utility."""
def __init__(self, input_dir, output_dir):
self.input_dir = input_dir
self.output_dir = output_dir
# Create output directory if it doesn't exist
os.makedirs(output_dir, exist_ok=True)
def process_all_videos(self, operation='compress', **kwargs):
"""
Process all videos in input directory.
Args:
operation: Operation to perform (compress, convert, thumbnail)
**kwargs: Additional arguments for the operation
"""
video_files = glob.glob(os.path.join(self.input_dir, '*.mp4'))
if not video_files:
print(f"No videos found in {self.input_dir}")
return
print(f"Found {len(video_files)} videos to process")
for idx, video_file in enumerate(video_files, 1):
filename = os.path.basename(video_file)
output_file = os.path.join(self.output_dir, filename)
print(f"\n[{idx}/{len(video_files)}] Processing: {filename}")
if operation == 'compress':
self.compress_video(video_file, output_file, kwargs.get('crf', 23))
elif operation == 'convert':
self.convert_video(video_file, output_file, kwargs.get('format', 'mp4'))
elif operation == 'thumbnail':
thumb_file = output_file.replace('.mp4', '.jpg')
self.create_thumbnail(video_file, thumb_file)
print(f"\n✓ Batch processing complete! Output in: {self.output_dir}")
def compress_video(self, input_file, output_file, crf=23):
"""Compress single video."""
command = [
'ffmpeg',
'-i', input_file,
'-c:v', 'libx264',
'-crf', str(crf),
'-preset', 'medium',
'-c:a', 'aac',
'-b:a', '128k',
'-y',
output_file
]
subprocess.run(command, check=True, capture_output=True)
def convert_video(self, input_file, output_file, format='mp4'):
"""Convert video format."""
output_file = output_file.replace('.mp4', f'.{format}')
command = [
'ffmpeg',
'-i', input_file,
'-c:v', 'libx264',
'-c:a', 'aac',
'-y',
output_file
]
subprocess.run(command, check=True, capture_output=True)
def create_thumbnail(self, input_file, output_file):
"""Create thumbnail from video."""
command = [
'ffmpeg',
'-i', input_file,
'-ss', '00:00:01',
'-vframes', '1',
'-q:v', '2',
'-y',
output_file
]
subprocess.run(command, check=True, capture_output=True)
if __name__ == "__main__":
processor = VideoProcessor('./input_videos', './output_videos')
processor.process_all_videos(operation='compress', crf=23)
Best Practices
When working with FFmpeg and Python:
- Always validate input files - Check file existence before processing
- Handle errors gracefully - Use try-except blocks for subprocess calls
- Use appropriate codecs - H.264 for compatibility, H.265 for better compression
- Monitor encoding progress - Parse FFmpeg output for progress updates
- Clean up temporary files - Remove intermediate files after processing
- Test commands individually - Verify FFmpeg commands work before automating
- Consider hardware acceleration - Use GPU encoding for faster processing
Conclusion
FFmpeg with Python provides a powerful combination for video editing automation. Whether you need to:
- Process videos in batch operations
- Build automated video workflows
- Create custom video editing tools
- Handle server-side video processing
This terminal-based approach gives you complete control over video manipulation without requiring heavy GUI applications. Start with these examples and build more complex video processing pipelines tailored to your specific needs.
The flexibility of combining FFmpeg’s powerful video processing capabilities with Python’s scripting makes it an ideal solution for both simple tasks and complex video editing workflows.
Related Articles
Python ReportLab Tutorial: Edit PDF Files in Terminal
Learn how to use Python's ReportLab library to create and edit PDF files directly from the command line with practical examples.
Generate Excel Files from Raw Data with Python
Quick guide to creating Excel files from raw data using Python. Learn to use openpyxl, xlsxwriter, and pandas for Excel generation.
Read and Write CSV Files with Python
Simple guide to reading and writing CSV files in Python using csv module and pandas. Quick examples for data processing.