Skip to content

imShaikhAR/immich-video-replace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Immich Video Replace

A Python script to intelligently replace lower-quality videos in Immich with transcoded versions while preserving all metadata, managing backups, and supporting batch processing.

⚠️ Compatibility Notice

Minimum Immich Version: v2.4.0+
Tested Versions: v2.4.1
Last Updated: December 28, 2025

This script requires Immich v2.4.0 or newer due to API endpoint changes. If you're running an older version of Immich, please upgrade first or use an older version of this script.

Recent API Changes

  • Authentication endpoint changed from /auth/me to /users/me
  • Asset metadata updates changed from PATCH to PUT
  • See API_TEST_RESULTS_FINAL.md for detailed compatibility testing

✨ What's New in v1.1.1

  • 🔧 Fixed Immich v2.4+ compatibility - Updated authentication and metadata endpoints
  • 100% API compatibility - All endpoints tested and working
  • 📊 Comprehensive testing - Tested against Immich v2.4.1 demo server
  • 📚 Enhanced docs - Added detailed API compatibility reports

✨ What's New in v1.1.0

  • 🔍 Two-tier matching strategy - Exact match (auto) + fuzzy match (with confirmation)
  • 🐛 Debug mode - Comprehensive API logging with DEBUG_API flag
  • 📊 Better visibility - Clear distinction between exact and fuzzy matches
  • 🛠️ Bug fixes - All critical bugs resolved (see CHANGELOG.md)

Features

Smart Video Matching

  • Priority: Exact match (filename + duration <0.5s) - automatic, no confirmation
  • Fallback: Fuzzy match (filename + duration ±tolerance) - requires confirmation
  • Interactive prompts for uncertain matches
  • Detailed matching logs showing why videos matched or didn't

🎬 Intelligent Replacement

  • Uses Immich's replaceAsset API endpoint to maintain asset IDs
  • Preserves original upload dates and all metadata
  • Automatically moves original videos to backup album
  • Adds transcoded video to all albums the original was in

💾 Backup Management

  • Automatically creates backup album if it doesn't exist
  • Moves original assets to backup album before replacement
  • Preserves complete asset history

📊 Progress & Reporting

  • Real-time progress bar during processing
  • Detailed summary statistics (exact/fuzzy matches, replaced, failed)
  • Comprehensive logging to file
  • Dry-run mode to preview actions before executing

🐛 Debug Mode

  • DEBUG_API flag logs all API requests and responses
  • Helps troubleshoot connection issues and unexpected behavior
  • Automatic API key redaction in logs
  • See DEBUG_GUIDE.md for details

⚙️ Flexible Configuration

  • All settings via .env file
  • Accept album by name or UUID
  • Configurable retry policy
  • Tolerance settings for fuzzy matching

Requirements

  • Python 3.8+
  • FFmpeg/FFprobe installed
  • Immich v2.4.0+ instance with API access
  • Video files in a designated folder

Quick Start

1. Installation

# Clone repository
git clone https://github.com/Mr187k/immich-video-replace.git
cd immich-video-replace

# Create virtual environment
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

2. Install FFmpeg

# Ubuntu/Debian
sudo apt install ffmpeg

# macOS
brew install ffmpeg

# Windows
choco install ffmpeg

3. Configuration

# Copy example config
cp .env.example .env

# Edit with your settings
nano .env  # or your preferred editor

Minimum required settings:

IMMICH_URL=http://192.168.1.100:2283/api
IMMICH_API_KEY=your_api_key_here
ALBUM_ID_OR_NAME=MyVideos

Getting your API key:

  1. Open Immich web interface
  2. Settings → Account → API Keys
  3. Create API Key
  4. Copy to .env

4. Test Connection

python test_connection.py

Expected output:

✅ ALL TESTS PASSED - Ready to use immich_video_replace.py!

If you see authentication errors, ensure you're running Immich v2.4.0 or newer.

5. First Run (Dry-Run)

# Ensure DRY_RUN=true in .env
python immich_video_replace.py

Review output, then set DRY_RUN=false and run again.

Configuration

Environment Variables

Variable Type Default Description
IMMICH_URL str - Base URL of Immich API (include /api)
IMMICH_API_KEY str - Immich API key for authentication
ALBUM_ID_OR_NAME str - Album UUID or name containing original videos
BACKUP_ALBUM_NAME str "Backup - Original Videos" Album name for storing original assets
INPUT_FOLDER str "./output" Folder containing transcoded videos
MATCH_DURATION_TOLERANCE_SECONDS int 2 Tolerance in seconds for fuzzy matching
MAX_RETRIES int 3 Max retry attempts for failed uploads
RETRY_DELAY_SECONDS int 5 Delay between retry attempts
LOG_FILE str "./immich_replace.log" Log file path
LOG_LEVEL str "INFO" Logging level (see below)
DEBUG_API bool false Log all API requests/responses (true/false)
DRY_RUN bool false Preview actions without executing (true/false)

Log Levels

Level When to Use What You'll See
DEBUG Troubleshooting, development All operations, matching details, API calls (if DEBUG_API=true)
INFO Normal operation (recommended) Progress, matches, successes, important events
WARNING Production monitoring Issues that didn't prevent completion
ERROR Minimal logging Only failures and critical errors
CRITICAL Emergency only Only catastrophic failures

Recommended settings:

  • First run: LOG_LEVEL=DEBUG + DRY_RUN=true
  • Production: LOG_LEVEL=INFO
  • Troubleshooting: LOG_LEVEL=DEBUG + DEBUG_API=true

Usage

Basic Workflow

# 1. Test connection
python test_connection.py

# 2. Dry-run to preview
DRY_RUN=true python immich_video_replace.py

# 3. Review output and logs
cat immich_replace.log

# 4. Run for real
DRY_RUN=false python immich_video_replace.py

Enable Debug Mode

# Edit .env:
DEBUG_API=true
LOG_LEVEL=DEBUG

# Run and check logs
python immich_video_replace.py
cat immich_replace.log

How It Works

Video Matching Strategy

The script uses a two-tier matching approach:

1. Priority: Exact Match

  • Criteria: Filename matches + duration difference < 0.5s
  • Behavior: Automatically accepted (no confirmation)
  • Use case: Same video, just transcoded

2. Fallback: Fuzzy Match

  • Criteria: Filename matches + duration difference ≤ tolerance (default: 2s)
  • Behavior: Requires user confirmation
  • Use case: Transcoding changed duration slightly

See MATCHING_STRATEGY.md for complete details.

Replacement Workflow

For each matched video:

  1. Get original metadata (description, rating, favorite, GPS location)
  2. Move original to backup album (removed from all existing albums)
  3. Replace asset with transcoded version using Immich API
    • Maintains original asset ID
    • Preserves original fileCreatedAt date
    • Preserves original upload timestamp
  4. Update metadata on new asset
  5. Add to all original albums (restore album membership)
  6. Delete local file (after successful upload)

Supported Video Formats

.mp4, .mkv, .mov, .avi, .webm, .flv, .m4v

Example Output

=== Video Matching ===
Strategy: 1) Exact (filename + duration <0.5s), 2) Fuzzy (filename + ±2s)

[PRIORITY] Searching exact match for "vacation.mp4" (duration: 125.42s)
✅ [EXACT MATCH] Found: "vacation.mp4" (duration diff: 0.040s)

[PRIORITY] Searching exact match for "beach_trip.mp4" (duration: 95.20s)
[PRIORITY] No exact match found
[FALLBACK] Searching fuzzy match for "beach_trip.mp4"
⚠️  [FUZZY MATCH] Found: "beach_trip.mp4" (duration diff: 1.38s)

⚠️  Fuzzy match found (requires confirmation):
  Local file:    beach_trip_transcoded.mp4
  Immich file:   beach_trip.mp4
  Local duration:  95.20s
  Immich duration: 96.58s
  Difference:      1.38s (tolerance: ±2s)

Are these the same video? (yes/no): yes

=== Matching Summary ===
Scanned: 2
Matched: 2 (✅ 1 exact, ⚠️  1 fuzzy)
Unmatched: 0

Proceed with replacement? (yes/no): yes

=== Processing Videos ===
Replacing videos: 100%|████████████| 2/2 [00:15<00:00, 7.5s/video]

=== Final Summary ===
Matched: 2 (✅ 1 exact, ⚠️  1 fuzzy)
Successfully replaced: 2
Failed: 0
Moved to backup: 2

Metadata Preserved

All metadata is inherited from the original video:

  • fileCreatedAt - Original upload date
  • dateTimeOriginal - Original capture date/time
  • description - Video description
  • rating - Star rating (1-5)
  • isFavorite - Favorite status
  • latitude / longitude - GPS location data
  • ✅ Album membership - Restored to all original albums

Troubleshooting

Compatibility Issues

Problem: Authentication failed or 404 Not Found on /auth/me

Solution: You're running Immich < v2.4.0. Either:

  1. Upgrade Immich to v2.4.0+ (recommended)
  2. Use an older version of this script (v1.0.0)

Check your Immich version:

curl http://your-immich:2283/api/server/version

Connection Issues

Problem: Failed to connect to Immich

Solutions:

  1. Verify IMMICH_URL includes /api
  2. Check Immich is accessible: curl http://your-immich:2283/api/users/me
  3. Verify API key is valid
  4. Run python test_connection.py to diagnose

Album Not Found

Problem: Album not found: MyVideos

Solutions:

  1. Check album name spelling (case-sensitive)
  2. Use album UUID instead of name
  3. Run python test_connection.py to list available albums

Videos Not Matching

For exact matches:

  • Check if filename is similar (case-insensitive matching)
  • Verify duration difference is < 0.5s
  • Enable LOG_LEVEL=DEBUG to see matching details

For fuzzy matches:

  • Adjust MATCH_DURATION_TOLERANCE_SECONDS (try 3-5s)
  • Check logs for "duration differs" messages
  • Use DEBUG_API=true to see full asset data

See MATCHING_STRATEGY.md for detailed troubleshooting.

Upload Failures

Solutions:

  • Increase MAX_RETRIES and RETRY_DELAY_SECONDS
  • Check Immich server disk space
  • Verify file permissions on input folder
  • Enable DEBUG_API=true to see exact error responses

FFprobe Not Found

Solutions:

  • Ubuntu/Debian: sudo apt install ffmpeg
  • macOS: brew install ffmpeg
  • Windows: Install FFmpeg and add to PATH

Documentation

Testing

Test API compatibility with your Immich instance:

# Run automated compatibility tests
python test_api_endpoints.py

# Should show 100% compatibility for Immich v2.4+

See API_TEST_RESULTS_FINAL.md for expected results.

Project Structure

immich-video-replace/
├── immich_video_replace.py      # Main script (v1.1.1)
├── test_connection.py           # Connection testing utility
├── test_api_endpoints.py        # API compatibility tester
├── requirements.txt             # Python dependencies
├── .env.example                 # Example configuration
├── .env.test                    # Demo instance test config
├── .gitignore                   # Git ignore rules
├── README.md                    # This file
├── CHANGELOG.md                 # Version history
├── MATCHING_STRATEGY.md         # Matching algorithm guide
├── DEBUG_GUIDE.md               # Debug mode documentation
├── TEST_WITH_DEMO.md            # Testing guide
├── API_TEST_RESULTS_FINAL.md    # API compatibility report
└── API_COMPATIBILITY_REPORT.md  # Detailed endpoint analysis

FAQ

Q: What Immich versions are supported?

A: Immich v2.4.0 and newer. Tested with v2.4.1. Run test_api_endpoints.py to verify compatibility.

Q: Will this delete my original videos?

A: No! Originals are moved to a backup album. You can delete them later if desired.

Q: Can I undo a replacement?

A: Yes, restore the original from the backup album manually in Immich.

Q: What if the script crashes mid-operation?

A: Videos are replaced one at a time. Already replaced videos won't be re-processed. Check logs and re-run.

Q: Can I process multiple albums?

A: Currently one album per run. Run the script multiple times with different ALBUM_ID_OR_NAME values.

Q: Does it support photos?

A: No, only video files are processed.

Q: How do I get an Immich API key?

A: In Immich web UI: Settings → Account → API Keys → Create API Key

Q: What happens to local files after replacement?

A: Successfully uploaded files are automatically deleted from the INPUT_FOLDER.

Q: Why am I getting 404 errors?

A: Check your Immich version. This script requires v2.4.0+. See "Compatibility Issues" in Troubleshooting.

Safety Features

The script includes multiple safety mechanisms:

  1. Version Check - Warns if Immich version is incompatible
  2. Dry-Run Mode - Preview all changes before executing
  3. Backup Album - Originals moved to backup, not deleted
  4. Metadata Preservation - All metadata inherited by new video
  5. User Confirmation - Ask before fuzzy matches
  6. Comprehensive Logging - Full audit trail of operations
  7. Error Handling - Graceful failure with detailed error messages
  8. Retry Logic - Automatic retries for transient failures
  9. Connection Testing - Verify setup before replacement

Support

Having issues? Follow these steps:

  1. Check Immich version: Must be v2.4.0+
  2. Run python test_api_endpoints.py to verify API compatibility
  3. Run python test_connection.py to verify connectivity
  4. Enable debug mode: DEBUG_API=true + LOG_LEVEL=DEBUG
  5. Check API_TEST_RESULTS_FINAL.md for known issues
  6. Check DEBUG_GUIDE.md for troubleshooting
  7. Review MATCHING_STRATEGY.md for matching issues
  8. Check log file for detailed error messages
  9. Open an issue with sanitized logs (remove sensitive data)

Version Compatibility Matrix

Script Version Immich Version Status
v1.1.1+ v2.4.0+ ✅ Fully Compatible
v1.1.0 v2.4.0+ ⚠️ Partial (needs endpoint updates)
v1.0.0 < v2.4.0 ⚠️ May work (uses old endpoints)

License

MIT License - feel free to use and modify as needed.

Contributing

Issues, bug reports, and pull requests welcome!

Disclaimer

  • ⚠️ Test on a backup of your Immich library first
  • ⚠️ Ensure you're running Immich v2.4.0 or newer
  • ✅ Always enable dry-run mode for initial testing
  • ✅ Verify configuration carefully before running
  • ✅ Run test_api_endpoints.py to verify compatibility
  • ✅ This script modifies your Immich library; ensure backups exist

Happy video transcoding! 🎬✨

About

Python script to replace lower-quality videos in Immich with transcoded versions while preserving metadata and managing backups

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors