High-quality video to GIF converter using FFmpeg with palette generation for optimal color reproduction and file size.
- ✅ Batch Conversion: Process multiple videos at once automatically
- 🎨 High Quality: Two-pass palette generation for superior color accuracy
- 📐 Smart Scaling: Specify width, height auto-scales maintaining aspect ratio
- 🎬 Flexible FPS Control: Manual FPS setting or auto-detection (capped at 30fps)
- 🎯 Multiple Formats: Supports MP4, AVI, MOV, MKV, WebM, FLV, WMV (case-insensitive)
- 📊 Progress Tracking: Real-time conversion progress with color-coded output
- 🧹 Auto Cleanup: Automatic temporary file management
- 🔄 Robust Error Handling: Continues processing even if individual files fail
Ubuntu/Debian:
sudo apt update
sudo apt install ffmpegMacOS:
brew install ffmpegWindows: Download from FFmpeg official website and add to PATH.
Verify Installation:
ffmpeg -version
ffprobe -version- Clone or download this repository:
git clone <repository-url>
cd video2gif- Make the script executable:
chmod +x convert.sh- Verify directory structure:
video2gif/
├── convert.sh
├── input/ # Place video files here
└── output/ # GIFs will be created here
# Convert with defaults (640px width, auto FPS)
./convert.sh
# Convert with custom width (auto FPS)
./convert.sh 800
# Convert with custom width and FPS
./convert.sh 800 15
# Convert for smaller file size
./convert.sh 480 10Parameters:
width: Target width in pixels (optional, default: 640)fps: Target frames per second (optional, default: auto-detect, capped at 30)
-
Add Videos: Place your video files in the
input/foldercp /path/to/your/video.mp4 ./input/
-
Run Conversion: Execute the script with desired parameters
./convert.sh 640 # 640px width, auto FPS ./convert.sh 640 20 # 640px width, 20 FPS
-
Get Results: Find your GIFs in the
output/folderls -lh output/
./convert.sh 640- Output: 640px wide GIFs at original FPS (max 30)
- Use case: General sharing, social media
- File size: Medium
- Quality: High (maintains source smoothness)
./convert.sh 1280 20- Output: 1280px wide GIFs at 20 FPS
- Use case: High-resolution displays, presentations
- File size: Large but optimized
- Quality: Very high resolution with smooth motion
./convert.sh 320 10- Output: 320px wide GIFs at 10 FPS
- Use case: Thumbnails, mobile, bandwidth-limited
- File size: Small
- Quality: Acceptable for previews
./convert.sh 640 30- Output: 640px wide GIFs at 30 FPS
- Use case: Smooth, fluid animations
- File size: Larger due to more frames
- Quality: Very smooth motion
# Add multiple videos
cp video1.mp4 video2.mov video3.avi input/
# Convert all at once with custom settings
./convert.sh 800 15
# Results in output/
# - video1.gif (800px @ 15fps)
# - video2.gif (800px @ 15fps)
# - video3.gif (800px @ 15fps)The script uses a two-pass palette generation approach for optimal quality:
ffmpeg -i input.mp4 -vf "fps=FPS,scale=W:H:flags=lanczos,palettegen=stats_mode=diff" palette.png- Analyzes video to create optimal 256-color palette
fps: Auto-detected from source (max 30) or user-specifiedstats_mode=diffconsiders temporal differences for better color selection- Lanczos scaling algorithm for high-quality resizing
ffmpeg -i input.mp4 -i palette.png -lavfi "fps=FPS,scale=W:H:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle" output.gif- Uses generated palette for conversion
- Bayer dithering (scale 5) for smooth color gradients
- Rectangle diff mode for better compression
- FPS: Matches source video (capped at 30) or user-specified
| Parameter | Value | Purpose |
|---|---|---|
fps |
Auto-detect (max 30) or user-specified | Frame rate control for file size and smoothness |
scale |
User-defined width | Horizontal resolution |
flags=lanczos |
- | High-quality scaling algorithm |
palettegen |
stats_mode=diff | Optimal color palette generation |
dither |
bayer | Smooth color transitions |
bayer_scale |
5 | Dithering intensity |
diff_mode |
rectangle | Compression optimization |
The script automatically detects the original video's frame rate and uses it for conversion:
- Auto Mode (no FPS specified): Uses original FPS, capped at 30fps
- Example: 60fps video → 30fps GIF
- Example: 24fps video → 24fps GIF
- Manual Mode (FPS specified): Uses your specified FPS value
- Example:
./convert.sh 800 15→ 15fps GIF regardless of source
- Example:
| Format | Extension | Notes |
|---|---|---|
| MP4 | .mp4 | Most common, H.264/H.265 |
| AVI | .avi | Older format, various codecs |
| MOV | .mov | QuickTime format |
| MKV | .mkv | Matroska container |
| WebM | .webm | Web-optimized format |
| FLV | .flv | Flash video |
| WMV | .wmv | Windows Media Video |
Method 1: Command-line parameter (Recommended)
./convert.sh 640 15 # Set FPS to 15
./convert.sh 640 24 # Set FPS to 24Method 2: Edit default behavior Modify the FPS detection logic if you want different auto-detection rules (e.g., cap at 24fps instead of 30fps)
Edit line 117 in convert.sh:
# Adjust bayer_scale (0-5)
bayer_scale=3 # Less dithering
bayer_scale=5 # More dithering (default)Edit line 35 in convert.sh:
WIDTH=640 # Change to your preferred defaultError: FFmpeg is not installed.
Solution: Install FFmpeg using the instructions in Prerequisites
No video files found in ./input
Solution:
- Verify videos are in the
input/folder - Check file extensions match supported formats
- Ensure file names don't contain special characters
✗ Failed to convert filename.mp4 to GIF
Solutions:
- Check if video file is corrupted:
ffprobe input/filename.mp4 - Verify sufficient disk space:
df -h - Try with a different width value
- Check FFmpeg version:
ffmpeg -version(v4.0+ recommended)
bash: ./convert.sh: Permission denied
Solution: Make script executable
chmod +x convert.shSolutions:
- Reduce width:
./convert.sh 480 - Lower frame rate: Edit
fps=10tofps=5in script - Trim video duration before conversion
- Use video compression before GIF conversion
Optimization Tips:
- Use smaller width values
- Reduce source video resolution before conversion
- Use SSD storage for temp files
- Close other resource-intensive applications
Depends on:
- Video duration and resolution
- Target GIF dimensions
- CPU performance
- Disk I/O speed
Typical Performance (on modern hardware):
- 30-second 1080p video → 640px GIF: ~10-20 seconds
- 10-second 720p video → 480px GIF: ~5-10 seconds
Approximate Output Sizes:
- 10 sec video @ 320px: 0.5-2 MB
- 10 sec video @ 640px: 2-5 MB
- 10 sec video @ 1280px: 5-15 MB
Note: Actual sizes vary based on video complexity and motion
# Modify line 70 in convert.sh to process only MP4 files
for video_file in "$INPUT_DIR"/*.mp4; do# Modify line 79 to include timestamp
output_gif="$OUTPUT_DIR/${filename_no_ext}_$(date +%Y%m%d_%H%M%S).gif"Add before line 81:
if [ -f "$output_gif" ]; then
echo " ⊙ Skipping (already exists): $filename"
continue
fi-
Video Preparation
- Trim videos to essential content before conversion
- Remove unnecessary audio (GIFs have no audio anyway)
- Consider compressing source videos first
-
Quality vs Size
- Use 480-640px for general web use
- Use 320px for thumbnails and previews
- Use 800px+ only when quality is critical
-
Batch Processing
- Group videos of similar length for better time estimation
- Monitor disk space when processing many videos
- Use consistent naming conventions for input files
-
Optimization
- Test with one video first to verify quality settings
- Adjust frame rate based on content (high motion = higher fps)
- Use lower fps for static content to reduce file size
Q: Why use palette generation? A: GIFs support only 256 colors. Palette generation analyzes your video to select the optimal 256 colors, resulting in better quality and smaller files.
Q: Can I convert just part of a video? A: Yes, use FFmpeg to extract the segment first:
ffmpeg -i input.mp4 -ss 00:00:10 -t 00:00:05 -c copy input/segment.mp4
./convert.sh 640Q: Why is my GIF file large? A: GIF file size depends on dimensions, duration, frame rate, and content complexity. Reduce any of these factors to decrease file size.
Q: Can I add text or watermarks? A: Yes, modify the FFmpeg commands to include overlay filters. See FFmpeg drawtext documentation.
Q: How do I change the output folder?
A: Modify line 47 in convert.sh:
OUTPUT_DIR="/path/to/your/output/folder"Improvements and suggestions welcome! Consider:
- Additional output formats (WebP, APNG)
- Quality presets (low/medium/high)
- Progress bars for long conversions
- Parallel processing for multiple files
- Configuration file support
This script is provided as-is for personal and commercial use.
Built with FFmpeg - the leading multimedia framework.
- Added: FPS parameter support for manual frame rate control
- Added: Automatic FPS detection from source video (capped at 30fps)
- Improved: Display original and target FPS in conversion progress
- Enhanced: Better control over file size vs. smoothness trade-offs
- Fixed: Batch processing bug where only first video was converted
- Fixed: Script now properly handles
set -eand error checking - Improved: Better error handling with detailed output on failures
- Added: Case-insensitive file extension matching (e.g., .MP4, .mp4)
- Added:
nullgloboption for graceful handling of missing file types
- Initial release with palette-based high-quality GIF conversion
- Support for 7 major video formats
- Automatic aspect ratio preservation
- Batch processing capability
- Color-coded progress output