Skip to content

Subservient is an open-source, fully automated subtitle synchronization suite, with user friendliness at heart. Fetch, download and synchronize subtitles in your preferred languages with the simple press of a button. Available natively using Python, and available through a Docker container

License

Notifications You must be signed in to change notification settings

N3xigen/Subservient

Repository files navigation

🎬 Subservient - The AI Subtitle Synchronizer

Version Python Docker License Platform

Plex Jellyfin Emby Unraid


🔍 What Subservient Does

🎯 Automated subtitle synchronization for your video collection

Transform your viewing experience with perfectly synchronized subtitles in multiple languages. Subservient automatically extracts, downloads, and syncs subtitle files using advanced audio analysis, eliminating the frustration of out-of-sync dialogue. Unlike comprehensive media management systems like Bazarr or Sonarr, Subservient is a standalone, easy to use CLI tool that is dedicated specifically to subtitle synchronization. Simply point it at your video files, and it handles the technical complexity while giving you control over the results.

🔄 Core Workflow

ExtractDownloadSynchronizeVerify

  1. 📤 Subtitle Extraction: Automatically extracts embedded subtitles from video files
  2. 🌐 Intelligent Download: Searches OpenSubtitles for missing languages based on your preferences
  3. 🎵 Audio-Based Synchronization: Uses FFSubSync's advanced audio analysis to achieve frame-perfect timing
  4. ✅ Quality Verification: Presents sync results for manual verification when automatic quality thresholds aren't met

🧹 Optional: Content cleaning tool available separately to remove promotional text and translator notes

Processing Modes

Mode Description Best For
🎭 Movie Mode Processes the largest video file in each folder Film collections with extras and multiple versions
📺 Series Mode Processes all videos with SxxExx pattern detection TV shows with consistent episode naming

⚡ Synchronization Strategies

Strategy Approach Performance
🚀 First Match Uses first successful sync Quick processing, good results
🎯 Smart Sync Tests all newly downloaded subtitles, picks the best synced one Slower but highest quality sync

💡 Built for Real-World Use

Whether you're managing a personal movie collection, processing TV series with hundreds of episodes, or handling multilingual content for family viewing, Subservient adapts to your workflow while maintaining professional-grade subtitle quality.


📋 Table of Contents

  1. 🔧 Installing and Configuring Subservient
  2. 🎯 Using Subservient
  3. ⚙️ How Subservient Works: The Four-Phase Automation Process
  4. 🔍 Troubleshooting Common Issues
  5. ❓ Frequently Asked Questions (FAQ)
  6. 📚 Changelog
  7. 🚀 Future Updates & Roadmap
  8. 💝🎉 Support & Donations
  9. 📄 License

🔧 INSTALLING AND CONFIGURING SUBSERVIENT

🚀 Quick Start Guide - New to Subservient?

  1. Install first - Follow the installation steps below (or watch the video guide)
  2. Read the documentation - Take time to understand how Subservient works and what it can do
  3. Configure your settings - Review the .config file thoroughly - this controls everything Subservient does
  4. Need help? Ask questions on GitHub or Buy Me a Coffee

Subservient works out of the box with sensible defaults, but proper configuration is key to making it work exactly how you want it to.

Subservient offers two installation methods, each with distinct advantages:

🖥️ Native Python Installation (Recommended for Performance)

Best for: Windows, macOS, and Linux users who want maximum performance

  • ✅ Advantages: Uses 100% of your system resources, faster processing, native OS integration
  • ⚠️ Complexity: Requires multiple applications to be installed and might need manual PATH configurations. More complex.

🐳 Docker Container Installation

Best for: Unraid, Linux servers, and users who prefer containerized applications

  • ✅ Advantages: Easy setup, isolated environment, consistent across platforms
  • ⚠️ Performance: May be slower, especially with limited RAM/CPU allocation

📺 Video Installation Guide (Native Python)

The video below provides a comprehensive walkthrough for the native Python installation, covering Python setup, required dependencies, setting up an OpenSubtitles consumer, and external tools like ffmpeg and mkvtoolnix.

📝 Note: Although this video was created for an older Subservient version, the installation procedure remains exactly the same.

Subservient Installation Video Guide

Choose your installation method:

🐍 Install Subservient with Python (Native Installation)

Best for: Users who want direct Python access, development, or full customization control

After downloading the Subservient folder from the GitHub repository, ensure that all required files are present in the same folder.

📁 Required Files

File Purpose
subordinate.py Main menu and setup
extraction.py Extract internal subtitles
acquisition.py Download from OpenSubtitles
synchronisation.py AI sync and cleanup
utils.py Shared utilities
.config Configuration file
requirements.txt Python dependencies

⚠️ Keep all files together in the Subservient folder. Don't move or edit anything until setup is complete.


🐍 Step 1: Install Python

Subservient requires Python 3.8+. If you don't have Python:

  1. Download from python.org
  2. Install (Windows: recommended to install directly to C:\Python[version]\ for easier path management)
  3. During installation, check "Add Python to PATH"
  4. Test with: open a terminal and test by typing python --version. This should show the current version.

💡 Windows Installation Tip: Installing to a simple path like C:\Python[version]\ (you can shorten the folder name) makes troubleshooting much easier than the default AppData location.

🚨 If python --version doesn't work, Python wasn't added to PATH correctly during install.

Manual PATH Fix (Windows): Add these two folders to your system PATH (adjust path if you chose a different location):

  • If installed to C-drive: C:\Python[version]\ and C:\Python[version]\Scripts\
  • If default location: C:\Users\[YourUsername]\AppData\Local\Programs\Python\Python[version]\ and C:\Users\[YourUsername]\AppData\Local\Programs\Python\Python[version]\Scripts\
🏗️ Step 2: Initial Setup

Position the Subservient folder where you want to keep it permanently, then:

🚀 START: Run subordinate.py (double-click or python subordinate.py)

During initial setup:

Step Description Status
📦 Check for essential Python packages Auto-install if missing
Create anchor point and pathfiles Saves to system config
Verify installation Shows confirmation

⚠️ Windows Users: Microsoft Visual C++ Build Tools are required for Python package installation. If you don't have them installed, Subservient will notice this, direct you to install them first and then exit. See Step 4 for installation instructions.


🔧 Technical Setup Details ( click to expand)
  • If you miss essential Python packages, it will attempt to install them using 'pip install'. Once you have the packages installed, it will either continue or quit depending on your system. If it quits, restart subordinate.py and it should continue to the initial setup.
  • When it proceeds to the initial setup, it will create a Subservient_pathfiles textfile, where it
    will store all pathfiles. These paths will then be used throughout all Subservient scripts. This textfile is in your local appdata folder. The directory of this folder depends on your OS.
  • When finished, you will see a confirmation that everything is set up correctly.

📝 NOTE: If you ever decide to move the Subservient folder after installation, Subservient will automatically detect when essential files are missing or moved and will provide clear instructions. The old pathfile will be automatically cleaned up and you can simply follow the on-screen instructions to complete the re-setup. The subordinate.py file itself can be moved freely without issues.


📍 Where are the locations stored? ( click to expand)

Subservient stores the anchor and file locations in a user-specific config file:

Operating System Path
🪟 Windows %APPDATA%/Subservient/Subservient_pathfiles
🍎 macOS/Linux ~/.config/Subservient/Subservient_pathfiles
  • As long as this file exists and is reachable, Subservient will function normally.
  • If the folder is deleted or becomes inaccessible, you will need to redo the setup by running subordinate.py again, inside of the Subservient folder. subordinate.py should be informing you if it has any issues with Subservient_pathfiles, in theory..

After completing the initial setup, you are now able to access the subordinate.py main menu.

🎮 Step 3: Access the Main Menu
  • Press Enter (if you haven't already) to proceed from the initial setup to the main menu.
  • The menu options are:
Option Description
1 Start Subservient - Begin the subtitle automation process
2 Scan subtitle coverage - Analyze existing subtitle files in current directory
3 Show quick instructions - View a concise guide to using Subservient
4 Install & verify requirements - Install and verify all Python packages
5 Extra tools - Access Subtitle Cleaner and additional subtitle utilities
6 Recreate .config file - Generate a new configuration file if needed
7 Open README file - Open this documentation
8 Exit - Close the program

📊 About Subtitle Coverage Scanning (Option 2)

Works together with your preferred language setting in your .config file. E.g. if you have NL and EN specified as languages that you need, then it will check per video file if those languages are present.

It will scan your library and provide you with the following markers per video file when finished:

  • ✅ Complete coverage (all languages present)
  • ⚠️ Partial coverage (some languages missing)
  • ❌ No coverage (no subtitles found)

Use before processing to see what's available, or after to verify results.


🛠️ About Extra Tools (Option 5)

Access additional subtitle utilities and cleaning tools that complement the main Subservient workflow:

🧹 Subtitle Cleaner

Remove advertisements, promotional content, and unwanted text from .srt files using the built-in Subtitle Cleaner:

  • Smart Detection: Automatically identifies and removes ads, website credits, translator notes, and promotional text
  • Safe Operation: All original files are automatically backed up before cleaning
  • Restore Functionality: Easily undo any changes if needed with the built-in restore option
  • Batch Processing: Clean multiple subtitle files at once for efficient processing
  • Regex Profiles: Uses advanced pattern matching to identify unwanted content

How to use:

  1. Navigate to a folder containing video files and their .srt subtitle files
  2. Select "Extra tools" from the main menu (Option 5)
  3. Choose "Subtitle Cleaner" (Option 1)
  4. Select either "Clean subtitle files" or "Restore subtitle changes"

🗑️ Delete moved_subtitles Folders

Clean up backup subtitle folders created by resync_mode:

  • Safety Check: Verifies that replacement subtitles exist before deletion
  • Language Detection: Identifies which languages are in the backup folder
  • Smart Confirmation: Only prompts for confirmation when external subtitles are missing
  • Recursive Scan: Finds all moved_subtitles folders in your video directory structure

How to use:

  1. Navigate to your video library folder
  2. Select "Extra tools" from the main menu (Option 5)
  3. Choose "Delete moved_subtitles folders" (Option 2)
  4. Review the safety check and confirm deletions when prompted

⚠️ Note: Only use this tool after you've verified that your new subtitles are properly synchronized and you no longer need the backups.

📦 Step 4: Install & Verify Requirements

Select menu option (4) to install Python packages:

Package Purpose
colorama Colored terminal output
requests HTTP requests
langdetect Language detection
ffsubsync AI subtitle synchronization
platformdirs Cross-platform directories
pycountry Language code conversion
tqdm Progress bars

🛠️ External Tools Required

Subservient requires three external tools to function properly:

🎬 FFmpeg

  • Purpose: Audio/video processing and subtitle extraction
  • Download: ffmpeg.org
  • Installation: Extract and add the bin folder to your system PATH
  • Test: Open Command Prompt and run: ffmpeg -version
  • Expected: Should show FFmpeg version and configuration info

📁 MKVToolNix

  • Purpose: Extract subtitles from MKV video files

  • Download: mkvtoolnix.download (Look for your OS at the top and go for the non-portable version to be safe)

  • Installation: Install normally - remember the installation folder location

  • Test: Open Command Prompt and run: mkvmerge --version

  • Expected: Should show MKVToolNix version info

  • PATH issue: If mkvmerge --version fails on Windows:

    • Find your MKVToolNix installation folder (usually C:\Program Files\MKVToolNix or C:\Program Files (x86)\MKVToolNix)
    • Add this folder to your system PATH environment variable
    • Windows: Search "Environment Variables" → Edit System Environment Variables → Environment Variables → Select "Path" under System Variables → Edit → New → Add your MKVToolNix folder path → OK
    • Alternative: Reinstall MKVToolNix and choose "Add to PATH" if the option appears during installation

🔧 Microsoft Visual C++ Build Tools (Windows only) - Linux and macOS can run this natively

  • Purpose: Required for compiling Python packages with native code
  • Download: Visual Studio Build Tools (click on 'Download Build Tools')
  • During installation, you will only need to select C++ Build Tools and then start installing

If you encountered package installation failures during Step 2, retry the setup after installing Build Tools. If it still gives errors, then add cl.exe to PATH (see below)

  • CL issue: If cl command fails:
    • Find cl.exe, which is usually located in C:\Program Files\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\[version]\bin\Hostx64\x64\
    • Add this path to your system PATH environment variable
  • Test: Open Command Prompt and run: cl
  • Expected: Should show Microsoft compiler version info

🚨 If packages are not working

If any package is not working or not installed, that most likely means something went wrong during the pip install phase. Check the install_log inside the logs folder for more information. Also make sure that Subservient has the required privileges to install and run scripts. You can also try installing the requirements again to see if that works. AI assistants like ChatGPT are also excellent at solving Python package issues.

You can always try running Subservient anyway to see if it works, but it's about as likely as a cactus winning a wet T-shirt contest in Alaska. Please check the GitHub page for known issues or create a new issue when applicable.

💝 Support Note: Limited support is available via GitHub issues. For faster, more personalized Discord support, consider supporting via Buy Me a Coffee.


🐳 Install Subservient with Docker (Containerized)

Best for:
Users who want easy deployment, Unraid compatibility, or isolated environments.
Docker provides a completely self-contained Subservient environment with all dependencies pre-installed.
Perfect for NAS systems like Unraid, or users who prefer containerized applications.

📋 Prerequisites

  1. Docker Desktop (Windows/macOS) or Docker Engine (Linux)

    • Download from docker.com
    • Ensure Docker is running before proceeding
  2. Git (optional - for cloning repository)

    • Or download ZIP from GitHub and extract

🚀 Quick Start

  1. Get Subservient:

    git clone https://github.com/N3xigen/Subservient.git
    cd Subservient/docker
  2. Prepare your content:


Place your video files in the movies folder and configure OpenSubtitles credentials in the main .config file.

docker/
├── movies/          # ← Place your video files here
├── logs/            # ← Subservient logs (auto-generated)
└── data/            # ← Subtitle backups (auto-generated)
  1. Start Subservient:

    docker-compose up -d
  2. Access Subservient:

    docker exec -it subservient bash
    python subordinate.py

� Folder Structure

All your data is automatically preserved between container restarts:

Host Path Container Path Purpose
docker/movies/ /app/movies Your video files
Subservient/.config /app/.config Configuration file (shared with native version)
docker/logs/ /app/logs Subservient processing logs
docker/data/ /app/data Subtitle backups & data

🎮 Usage Examples

Interactive Mode (Recommended)

# Start container
docker-compose up -d

# Enter interactive session
docker exec -it subservient bash

# Run Subservient (inside container)
python subordinate.py

One-time Processing

# Start container and run directly
docker-compose up -d
docker exec subservient python subordinate.py

Unraid Template

For Unraid users, use these container settings:

  • Repository: ghcr.io/n3xigen/subservient:latest
  • Network Type: bridge
  • Console Shell Command: bash
  • Host Paths:
    • /mnt/user/Movies//app/movies
    • /mnt/user/appdata/subservient/logs//app/logs
    • /mnt/user/appdata/subservient/data//app/data
    • /mnt/user/appdata/subservient/.config/app/.config

💡 Alternative (Local Build): If you prefer to build locally or the image isn't available yet:

git clone https://github.com/N3xigen/Subservient.git
cd Subservient/docker
docker-compose build

Then use subservient:latest as repository name instead.

⚙️ Docker Commands

Action Command
Start container docker-compose up -d
Stop container docker-compose down
View logs docker-compose logs -f
Rebuild docker-compose up --build -d
Enter container docker exec -it subservient bash

🚀 Performance Optimization

Docker containers have resource limits that can slow down intensive operations like subtitle synchronization. For better performance:

Docker Desktop Users:

  1. Open Docker DesktopSettingsResources
  2. Recommended settings:
    • CPUs: 4-6 cores (or 75% of your available cores)
    • Memory: 6-8GB (or 50% of your total RAM)
    • Swap: 2GB

Docker Compose Users:

Add resource limits to your docker-compose.yml:

services:
  subservient:
    deploy:
      resources:
        limits:
          cpus: '4.0'    # Adjust based on your system
          memory: 6G     # Adjust based on your RAM

Performance Tips:

  • ffsubsync (audio sync) is CPU-intensive - more cores = faster sync
  • Large video files benefit from more RAM allocation
  • SSD storage improves file I/O performance significantly
  • Close other applications during processing for maximum resources

💡 Note: Subtitle synchronization can be 2-3x slower in Docker compared to native Python due to virtualization overhead.



⚙️ Configuration (after installing)

🔧 Unified Configuration System

Both installation methods use the same .config file for all settings. Configure your OpenSubtitles credentials, processing preferences, and subtitle languages in one place that works for both native Python and Docker versions.

💡 Take time to review the configuration settings below. While Subservient works with sensible defaults out of the box, understanding these settings determines how powerfully you can utilize and customize Subservient to match your specific needs.

📝 All Configuration settings explained (.config file)

📋 Configuration Overview

  • 🌐 OpenSubtitles Setup: Create account and configure API credentials (required)
  • 🔑 API Settings: OpenSubtitles credentials configuration
  • 🎯 Processing: Series/Movie mode, Smart Sync, languages
  • ⚙️ Quality: Sync thresholds, performance tuning
  • 📁 File Management: Video handling, subtitle preservation

🌐 OpenSubtitles Setup

  1. Create account at opensubtitles.com
  2. Go to API Consumers and create a new consumer
  3. Copy your API key, username, and password to .config
Account Type Daily Limit Cost
🆓 Free (Dev Mode) ~100 downloads Free
👑 VIP 1000 downloads $10-15/year

💡 VIP Recommendation

VIP membership is a paid upgrade that increases your daily download limit to 1000.
This is recommended if you plan to use Subservient substantially and want the highest sync quality (large subtitle batches, smart sync etc).
You can purchase VIP membership here: https://www.opensubtitles.com/en/vip.



🔑 Required Settings (OpenSubtitles API)

Setting Description Default Required
api_key OpenSubtitles consumer API key from API Consumers section your_api_key_here
username Your OpenSubtitles account username your_username
password Your OpenSubtitles account password your_password
api_url OpenSubtitles API endpoint (should already be filled in) https://api.opensubtitles.com/api/v1

🎯 Processing & Synchronization Settings

Setting Description Default Options
series_mode Processing mode selection false true = TV Series (all videos), false = Movies (largest per folder)
smart_sync Subtitle selection strategy true true = Test all candidates, pick best; false = Use first successful sync
languages Subtitle languages to download and sync en Comma-separated codes (e.g. en,nl,fr,de)
audio_track_languages Audio track languages to keep in video files en,ja Language codes or ALL to keep all tracks

📺 series_mode: When true, processes ALL videos with SxxExx pattern detection. When false, only processes the largest video file per folder (movie mode).

🎯 smart_sync: When true, tests all subtitle candidates and picks the best quality sync. When false, uses first acceptable match (faster but potentially lower quality).

🌐 languages: Controls which subtitle languages are downloaded from OpenSubtitles. Does not affect preservation of existing subtitles.

🔊 audio_track_languages: Removes audio tracks not in this list to reduce file size. Set to ALL to keep all audio tracks unchanged.

Series Mode Details:

  • false: Movie Mode - Processes only the largest video file per folder
  • true: TV Series Mode - Processes ALL videos with SxxExx pattern detection and integrity checking

Smart Sync Details:

  • false: First Match - Uses first subtitle that syncs acceptably (faster)
  • true: Smart Sync - Tests ALL candidates, compares results, picks best quality (slower but higher quality)

⚙️ Quality & Performance Settings

Setting Description Default Notes
accept_offset_threshold Auto-accept sync threshold (seconds) 0.05 Lower = stricter quality, higher = more auto-accepts
reject_offset_threshold Auto-reject sync threshold (seconds) 2.5 Higher = more lenient, lower = stricter rejections
max_search_results Maximum subtitle search results per video 10 Free: ≤12, VIP: 20+
top_downloads Subtitles to test per batch 3 Free: 2-4, VIP: 5-10
use_movie_hash Enable hash-based subtitle matching true Provides exact subtitle matches for popular releases
resync_mode Move existing subtitles before processing false Enables clean re-synchronization runs
download_retry_503 Retry attempts for server errors 6 Recommended: 6 for busy periods
pause_seconds Pause between processing phases 5 Prevents API rate limiting

✅ accept_offset_threshold: Subtitles with sync quality below this threshold are automatically accepted without manual verification. Lower values ensure higher quality but require more manual checks.

❌ reject_offset_threshold: Subtitles with sync quality above this threshold are automatically rejected. Higher values give more subtitle candidates a chance but may require more manual verification.

🔍 max_search_results: More results increase chances of finding good subtitles but use more API quota. Free users should stay ≤12, VIP users can go higher.

⬇️ top_downloads: Number of subtitles tested simultaneously. Lower preserves download quota, higher speeds up processing if you have sufficient quota.

🎯 use_movie_hash: When enabled, uses OpenSubtitles movie hash algorithm for exact subtitle matching. Provides 95-99% accuracy for popular releases upon a match, but not all movies can be hash matched. Automatically falls back to text search when no hash match exists.

🔄 resync_mode: When enabled, moves all existing .srt and .ass subtitle files to a backup folder (moved_subtitles) before processing. Useful when you want to re-synchronize your entire collection with fresh downloads.

🔄 download_retry_503: OpenSubtitles servers can be busy. More retries increase success rate but slow processing during peak times.

⏸️ pause_seconds: Prevents API rate limiting and gives you time to read processing information between phases.


📁 File Management Settings

Setting Description Default Warning
delete_extra_videos Handle extra videos in folders false ⚠️ true = PERMANENT DELETION
extras_folder_name Folder name for moved extras extras Used when delete_extra_videos=false
preserve_forced_subtitles Keep FORCED subtitle tracks false For foreign dialogue scenes
preserve_unwanted_subtitles Keep all subtitle languages false Override language filtering
skip_dirs Folder names to ignore extras,trailers,samples... Comma-separated list
unwanted_terms Terms to filter from searches 720p,BluRay,x264... Technical metadata removal

🗑️ delete_extra_videos: When false (safe), moves extra videos to specified folder. When true (dangerous), permanently deletes all but the largest video file per folder. Ignored in series mode.

📁 extras_folder_name: Name of the folder where extra videos are moved when delete_extra_videos=false.

🔤 preserve_forced_subtitles: Preserves FORCED subtitle tracks (typically used for foreign dialogue in otherwise native-language movies) when true.

🌐 preserve_unwanted_subtitles: When true, keeps ALL subtitle tracks regardless of language settings. When false, removes tracks not in the languages list.

🚫 skip_dirs: Ignores these folder names during video discovery (case-insensitive matching).

🏷️ unwanted_terms: Removes technical terms from filenames before searching OpenSubtitles for cleaner, more accurate search queries.

⚠️ Warning: delete_extra_videos=true PERMANENTLY DELETES all video files except the largest in each folder.


⚙️ Mode Details & Advanced Configuration

🔧 Processing Mode Explanations & Advanced Settings

Detailed explanations of how TV Series Mode and Smart Sync work, plus advanced configuration patterns like subtitle preservation logic. These help you understand and optimize your .config settings.

⚙️ Mode Details & Advanced Configuration
📺 TV Series Mode - Complete episode processing with SxxExx detection

🚀 What Series Mode Does

Series Mode (series_mode=true) transforms Subservient to handle TV shows with advanced episode detection and processing:

🔍 SxxExx Pattern Detection

  • Automatic Recognition: Detects S01E01, S02E15, S10E23 patterns in filenames
  • Integrity Checking: Validates consistent naming across episodes
  • Auto-Normalization: Converts S1E01S01E01 for consistency
  • Flexible Matching: Works with various naming conventions

📁 Processing Behavior

Mode File Selection Use Case
Movie Mode (false) Largest file per folder Movies, single videos
Series Mode (true) ALL video files TV shows, episode collections

🛡️ Built-in Safeguards

  • Movie Detection: Warns when movie files detected in series mode
  • Pattern Validation: Ensures episodes follow consistent SxxExx format
  • Missing Episode Detection: Identifies gaps in season/episode numbering
  • Duplicate Prevention: Handles multiple versions of same episode

🎯 Example Usage

/TV Shows/Breaking Bad Season 1/
├── Breaking.Bad.S01E01.720p.mkv    ← Processed ✅
├── Breaking.Bad.S01E02.720p.mkv    ← Processed ✅  
├── Breaking.Bad.S01E03.720p.mkv    ← Processed ✅
└── extras/                         ← Ignored ✅
🎯 Smart Sync Mode - Advanced subtitle selection for optimal quality

🚀 How Smart Sync Works

Smart Sync (smart_sync=true) revolutionizes subtitle selection by testing ALL candidates before choosing the best result:

🔄 Sync Strategies

Mode Strategy Speed Quality Best For
First Match (false) Use first acceptable sync ⚡ Fast 🟡 Good Quick processing, decent results
Smart Sync (true) Test all, pick best 🐌 Slower 🟢 Excellent Maximum quality, worth the wait

🎯 Smart Sync Process

  1. Batch Download: Gets all available subtitle candidates
  2. Parallel Sync: Tests synchronization for each candidate
  3. Quality Comparison: Measures offset precision for all results
  4. Best Selection: Automatically picks the highest-quality sync
  5. Results Display: Shows comparison of all tested candidates

📊 Quality Comparison Example

[Synchronisation] [Smart Sync] Smart Sync Results:
• subtitle1.srt: ✓ 0.025s ← BEST
• subtitle2.srt: ✓ 0.087s  
• subtitle3.srt: ✗ 3.2s (rejected)
• subtitle4.srt: ✗ Failed

⚙️ Performance Impact

  • Processing Time: ~2-5x longer per video
  • API Usage: Tests more subtitle downloads
  • Quality Gain: Significantly better sync accuracy
  • Recommendation: Enable for movies/important content
🔄 DRIFT Recovery System - Automatic subtitle retry when synchronization fails

🚀 What DRIFT Recovery Does

DRIFT Recovery is Subservient's intelligent fallback system that automatically handles subtitle synchronization failures by downloading alternative candidates:

🔍 How It Works

  1. Failure Detection: When a subtitle fails synchronization (offset > reject_offset_threshold)
  2. DRIFT Marking: Failed subtitle is renamed with .DRIFT.srt suffix (e.g., 16676.nl.number1.S01E08.DRIFT.srt)
  3. Automatic Re-Acquisition: acquisition.py automatically restarts to download new candidates
  4. Smart Index Tracking: System remembers which subtitle indices were already tried and excludes them
  5. Fresh Attempts: Downloads next-best subtitles from OpenSubtitles ranking

📊 DRIFT Marking Scenarios

Scenario Action Next Step
Sync offset too high Automatic DRIFT marking Re-acquisition starts
Manual marking User selects "Mark as DRIFT" during verification Re-acquisition starts
Multiple failures Each failed attempt tracked separately Tries remaining indices

🎯 Index Tracking Logic

Subservient maintains a record of already-tried subtitle indices to prevent re-downloading the same failed subtitles:

First attempt:  Downloads indices [1, 2, 3]
After DRIFT:    Index 1 marked as tried
Second attempt: Downloads indices [2, 3, 4]  ← Skips 1
After DRIFT:    Indices 1, 2 marked as tried
Third attempt:  Downloads indices [3, 4, 5]  ← Skips 1 & 2

🔧 DRIFT File Management

  • During Processing: DRIFT files remain to track failed attempts
  • After Success: All DRIFT files automatically cleaned up when valid subtitle found
  • Manual Cleanup: DRIFT files removed at end of synchronization phase

⚙️ Configuration Impact

Setting Effect on DRIFT Recovery
reject_offset_threshold Higher value = fewer DRIFT markings, more lenient acceptance
top_downloads More downloads = more candidates before DRIFT retry needed
smart_sync Tests all candidates before DRIFT, reduces unnecessary retries
  • Let it run: DRIFT recovery is automatic - no manual intervention needed
  • Check logs: DRIFT markings appear in synchronization logs for troubleshooting
  • Adjust thresholds: If too many DRIFTs occur, consider relaxing reject_offset_threshold
  • Use Smart Sync: Reduces DRIFT frequency by testing all candidates first
🎯 Hash-Based Subtitle Matching - Exact subtitle matching using video fingerprints

🚀 What Hash Matching Does

Hash Matching (use_movie_hash=true) creates a unique fingerprint of your video file to find exact subtitle matches, improving accuracy from 60-70% to 95-99% when matches are found.

💡 Feature contributed by Phil Wedel (vnakkar) via PR #5

🔍 How It Works

Instead of searching by filename (which can vary), hash matching creates a fingerprint:

Hash = File size + Checksum(first 64KB) + Checksum(last 64KB)

Example:

Movie.2024.1080p.BluRay.x264.mkv → Hash: 8f7d65a4c9e2b1f3
Movie.2024.renamed.mkv            → Hash: 8f7d65a4c9e2b1f3 (same!)
Movie.2024.720p.WEB-DL.mkv        → Hash: 2a3b4c5d6e7f8901 (different!)

The hash is the same regardless of filename, but changes if the video content differs.

Search Strategy

Step Method When Used
1. Hash Search Exact video fingerprint match First attempt (if use_movie_hash=true)
2. Text Search Filename-based search Automatic fallback when hash fails

Log Example:

[HASH SEARCH] Searching by movie hash for EN: 8f7d65a4c9e2b1f3
[HASH MATCH] Found 2 hash-matched subtitle(s) for EN!

📊 Accuracy Comparison

Method Accuracy Coverage Best For
Hash Match 🟢 95-99% 🟡 ~30% Popular releases from known groups
Text Search 🟡 60-70% 🟢 ~98% All content, backup method

Hash matching works best for popular movies and series from well-known release groups. For older or niche content, it automatically falls back to filename-based search.

🔄 Resync Mode - Clean slate re-synchronization

🚀 What Resync Mode Does

Resync Mode (resync_mode=true) moves all existing subtitle files to a backup folder before processing, allowing you to start with a clean slate and re-download/re-synchronize your entire collection.

🔍 How It Works

When enabled, Subservient moves existing subtitles before processing:

Before Resync:
├─ Movie.mkv
├─ Movie.en.srt  ← Existing subtitle
└─ Movie.nl.srt  ← Existing subtitle

After Resync:
├─ Movie.mkv
└─ moved_subtitles/
    ├─ Movie.en.srt  ← Backed up
    └─ Movie.nl.srt  ← Backed up

Subservient then downloads and synchronizes fresh subtitles as if processing the collection for the first time.

When To Use Resync Mode

Scenario Use Resync Mode
Improved subtitle quality available ✅ Yes - Get better matches with newer database entries
Changed language preferences ✅ Yes - Download new languages, remove old ones
Testing different sync settings ✅ Yes - Compare results with fresh synchronization
Corrupted subtitle files ✅ Yes - Replace damaged files with clean downloads
Regular processing ❌ No - Keep existing subtitles and only process missing ones

⚙️ Configuration

Setting Effect
resync_mode=true Move existing .srt/.ass files to moved_subtitles folder
resync_mode=false Keep existing subtitles, only process videos without subtitles

Note: The moved_subtitles folder is automatically excluded from processing via the skip_dirs setting.

🎯 Subtitle Preservation Logic - Advanced track management settings

🎮 Smart Preservation System: Control exactly what subtitle content gets preserved during processing:

Setting Combination FORCED Subtitles Regular Subtitles Use Case
preserve_forced_subtitles=true
preserve_unwanted_subtitles=true
✅ ALL languages ✅ ALL languages Maximum preservation - Keep everything
preserve_forced_subtitles=true
preserve_unwanted_subtitles=false
✅ Wanted languages only ❌ Unwanted languages removed FORCED-priority - Keep FORCED for wanted langs
preserve_forced_subtitles=false
preserve_unwanted_subtitles=true
❌ Treated as regular ✅ ALL languages Language-priority - Keep all but no FORCED special treatment
preserve_forced_subtitles=false
preserve_unwanted_subtitles=false
❌ Treated as regular ❌ Unwanted languages removed Minimal - Only wanted languages

🔧 What are FORCED subtitles?

  • Separate subtitle tracks that ONLY translate foreign dialogue segments
  • NOT full movie subtitles - they complement the main spoken language
  • Example: Japanese dialogue in an English movie gets FORCED subtitles, while English dialogue remains unsubditled
  • Often essential for understanding key plot points when foreign languages are spoken
  • Important: FORCED subtitles are completely independent from regular full-movie subtitles

💡 Recommended Settings:

  • Keep everything: preserve_forced_subtitles=true, preserve_unwanted_subtitles=true
  • Perserve languages in language setting only, including forced subtitles: preserve_forced_subtitles=true, preserve_unwanted_subtitles=false
  • Perserve subtitles for all encountered languages, but remove forced subtitles: preserve_forced_subtitles=false, preserve_unwanted_subtitles=true
  • Only preferred languages, nothing else: preserve_forced_subtitles=false, preserve_unwanted_subtitles=false
🌐 Language Codes - All supported languages and how to use them

Use ISO 639-1 codes in .config (e.g., en, nl, fr):

Language Code Language Code Language Code
🇺🇸 English en 🇳🇱 Dutch nl 🇫🇷 French fr
🇩🇪 German de 🇪🇸 Spanish es 🇮🇹 Italian it
🇵🇹 Portuguese pt 🇷🇺 Russian ru 🇯🇵 Japanese ja
🇨🇳 Chinese zh 🇰🇷 Korean ko 🇸🇦 Arabic ar

🌍 Need more? See ISO 639-1 Wikipedia for complete list.


🎁 OpenSubtitles Season Map Download Feature

💾 Bulk Download Subtitles from OpenSubtitles Website (VIP Feature)

⚠️ Requires OpenSubtitles VIP membership - This feature uses the bulk season download capability available only to VIP members.

Save massive amounts of API quota by manually downloading entire seasons at once from the OpenSubtitles website. Instead of using the API to download 2-5 subtitles per batch for each episode, download all available subtitles for an entire season in one go (often 100+ subtitles for a 20-episode season). Organize them in a special folder structure, and Subservient will automatically extract, test, and sync the best subtitle for each episode.

📋 How It Works

  1. 📥 Manual Download: Visit OpenSubtitles website, download complete season subtitle packs
  2. 📁 Organize: Place downloaded subtitles in specially-named folders
  3. 🔍 Extraction: Subservient extracts and matches subtitles to episodes automatically
  4. 🎯 Smart Testing: Tests all candidates with Smart Sync, picks best quality
  5. 🔄 Fallback: If all fail, automatically downloads from OpenSubtitles API

📺 Setting Up Season Subtitle Folders

Place subtitle folders directly in your season folder alongside video files:

📁 Required Folder Structure

/Breaking Bad/Season 1/
├── SUBTITLES.S01.EN.zip         ← English Season subtitles folder
├── SUBTITLES.S01.NL.zip         ← Dutch Season subtitles folder
├── Breaking.Bad.S01E01.mkv
├── Breaking.Bad.S01E02.mkv
└── Breaking.Bad.S01E03.mkv

🏷️ Folder Naming Convention

Component Format Example Required
Prefix SUBTITLES Exactly this word Yes
Season .S## .S01, .S02, .S10 Yes (2 digits)
Language .LANG .EN, .NL, .FR Yes (2-letter, UPPERCASE)
Extension .zip Must be a folder Yes

✅ Valid Examples:

  • SUBTITLES.S01.EN.zip
  • SUBTITLES.S02.NL.zip
  • SUBTITLES.S10.JA.zip

❌ Invalid Examples:

  • Subtitles.S01.EN.zip ❌ Wrong capitalization
  • SUBTITLES.S1.EN.zip ❌ Season must be 2 digits
  • SUBTITLES.S01.en.zip ❌ Language must be UPPERCASE

📂 Inside the Folder

Your downloaded subtitle files from OpenSubtitles website can be organized in two ways:

Option 1: Flat structure (all files directly in folder)

SUBTITLES.S01.EN.zip/
├── Breaking.Bad.S01E01.subtitle1.srt
├── Breaking.Bad.S01E01.subtitle2.srt
├── Breaking.Bad.S01E02.subtitle1.srt
└── ... (all subtitles)

Option 2: Episode subfolders (common for subtitle packs)

SUBTITLES.S01.EN.zip/
├── Episode 1/
│   ├── subtitle1.srt
│   └── subtitle2.srt
├── Episode 2/
│   ├── subtitle1.srt
│   └── subtitle2.srt
└── ... (more episode folders)

What Subservient does automatically:

  • ✅ Scans folder recursively (finds files in subfolders too)
  • ✅ Matches subtitles to episodes using SxxExx pattern recognition
  • ✅ Extracts and renames them to P-prefix format (P100.nl.number1.S01E08.srt)
  • ✅ Tests all candidates per episode and picks the best sync

You just need to:

  • ✅ Download subtitle pack from OpenSubtitles website
  • ✅ Create correctly-named folder (SUBTITLES.S##.LANG.zip)
  • ✅ Place the folder in your season directory (any internal structure works)
  • ✅ Run Subservient - it handles the rest automatically

⚙️ How Subservient Processes These Folders

1️⃣ Detection Phase

  • Scans season folder for SUBTITLES.S##.LANG.zip folders
  • Validates folder naming conventions
  • Matches languages with your .config settings

2️⃣ Extraction Phase

  • Extracts subtitles based on SxxExx pattern matching
  • Renames to P-prefix format: P100.nl.number1.S01E08.srt, P200.nl.number2.S01E08.srt
  • P-prefix marks them as pre-downloaded (separate from API downloads)

3️⃣ Synchronization Phase

  • Tests all P-prefix candidates with Smart Sync
  • Picks best synchronized subtitle for each episode
  • If all fail → Triggers DRIFT recovery → Downloads from OpenSubtitles API

4️⃣ Fallback System

  • Failed P-prefix subtitles marked as .DRIFT.srt
  • System automatically switches to OpenSubtitles API
  • Downloads fresh candidates with normal numbering: 16676.nl.number1.S01E08.srt

💡 Why Use This Feature?

Benefit Description
💰 Massive Quota Savings Download 80+ subtitles at once instead of 2-3 per episode via API
🚀 Faster Processing No API rate limits, immediate availability for all episodes
🎯 More Choices Access to ALL subtitles on OpenSubtitles, not just top-rated
🔄 Smart Fallback Automatically uses API if pre-downloaded subtitles fail

📊 P-Prefix Numbering System

Pre-downloaded subtitles use special numbering to distinguish them from API downloads:

Source Numbering Example
Pre-downloaded P100, P200, P300 P100.nl.number1.S01E08.srt
OpenSubtitles API 16676, 837, etc. 16676.nl.number1.S01E08.srt

Why separate numbering?

  • Tracks which source failed during DRIFT recovery
  • Prevents confusion between subtitle sources
  • Smart DRIFT recovery ignores P-prefix failures when switching to API downloads

⚠️ Important Notes

  • 👑 VIP membership required - Bulk season downloads are only available to OpenSubtitles VIP members
  • ⚠️ TV Series only - This feature is not supported for movies
  • ⚠️ Manual download required - You must download subtitle packs from OpenSubtitles website yourself
  • ⚠️ Folder naming critical - Must follow exact naming convention or folders won't be detected
  • Enable Smart Sync - Recommended to test all candidates and pick best quality (smart_sync=true)

🎯 USING SUBSERVIENT

Choose your preferred method for using Subservient:

🐍 Using Subservient with the native python installation

🎮 How to use subordinate.py

Move subordinate.py to where you want to process videos, then run it:

Scenario Action Result
Single Movie Move into folder with movie Processes one movie
Batch Movies Move next to movie folders Processes all folders
TV Series Move into series folder + series_mode=true All episodes in that series
Batch TV Series Move next to series folders + series_mode=true All episodes in all series folders

Please note that, in movie mode, you cannot have multiple movie files in the same folder. Doing so will cause Subservient to look for the largest movie file, process that one, and either move or delete all the other movies in there. Only in TV Series mode can you have multiple movie files in the same folder.

📺 Series Processing Options:

  • Single Series: Place subordinate.py inside a series folder (e.g., /Breaking Bad/) to process all episodes in that series
  • Batch Series: Place subordinate.py next to multiple series folders (e.g., /TV Shows/) to process all episodes in all series automatically

🎬 Movie Processing Options:

  • Single Movie: Place subordinate.py in the folder containing the movie file
  • Batch Movies: Place subordinate.py next to multiple movie folders - each folder must contain only one movie file

⚠️ Movement Rules: Use cut+paste (Ctrl+X+V), NOT copy+paste. Multiple copies will confuse Subservient.

🎯 Running the Process

  1. Run subordinate.py → Choose option 1 → Read pre-flight checklist → Confirm
  2. Subservient processes automatically based on .config settings
  3. Manual input only needed for edge cases (bad configs, series detection, etc.)
🐳 Using Subservient with a docker container

🎮 Using Docker Container

Using Docker Compose (Recommended)

Navigate to the docker folder and start the container:

cd docker
docker-compose up

The container will start with an interactive terminal showing the Subservient main menu.

Using Docker Run Command

docker run -it --rm \
  -v /path/to/your/movies:/movies \
  -v /path/to/config:/config \
  -v /path/to/persistent/logs:/app/logs \
  -v /path/to/persistent/data:/app/data \
  -v /path/to/persistent/home:/root \
  subservient:latest

🎯 Container Usage

  1. Interactive Mode: Container starts directly in Subservient's main menu
  2. Volume Access: All your movie files are accessible via /movies mount
  3. Persistent Data: Configuration, logs, and download backups persist between container runs
  4. File Operations: Process movies directly from mounted volumes

File Placement Strategy

Since you can't move the script file in a container environment:

Scenario Docker Approach
Single Movie Place movie in dedicated folder under /movies
Batch Movies Organize movies in separate folders under /movies
TV Series Use series folder structure under /movies + series_mode=true
Batch TV Series Organize multiple series folders under /movies + series_mode=true

📁 Volume Organization

Structure your mounted directories for optimal workflow:

/your/movies/
├── Movie1_Folder/
│   └── movie1.mkv
├── Movie2_Folder/
│   └── movie2.mp4
├── Breaking_Bad/
│   ├── Breaking.Bad.S01E01.mkv
│   ├── Breaking.Bad.S01E02.mkv
│   └── Breaking.Bad.S01E03.mkv
└── Better_Call_Saul/
    ├── Better.Call.Saul.S01E01.mkv
    └── Better.Call.Saul.S01E02.mkv

/your/config/
└── .config

/your/logs/
└── (Subservient logs)

/your/data/
└── (Subtitle backups)

💬 When is a 'human touch' required?

Four main situations require your input:

1. 🔤 No Valid 'languages' Entry in .config (`extraction.py`)

Trigger: If the extraction script does not find a valid 'languages' entry in your .config file

Prompt Options:

  • Type c to continue with English only (default)
  • Type any other key to exit and fix your config

Purpose: Ensures you are aware that only English subtitles will be processed unless you update your configuration (because apparently configuring languages is optional until it's not).

2. 🔍 No Subtitles Found for a Video (`acquisition.py`)

Trigger: If Subservient cannot find any search results when searching on OpenSubtitles

Prompt Options:

  • Option 1: 🔵 Type in a manual search term to try a different subtitle search
  • Option 2: 🔴 Delete the video file permanently
  • Option 3: 🟡 Increase global subtitle download limit (will allow more subtitle candidates to be downloaded when available)
  • Option 4: 🟡 Skip this video for now (can be processed again in future runs)
  • Option 5: 🟣 Skip this language and do not show again (adds language to permanent skip list in config)

Purpose: Gives you complete control over what happens to videos for which no subtitles could be found, with both temporary and permanent solutions. Because sometimes we need to admit defeat gracefully ;)

3. 🧹 Prompt for Cleaning Internal Subtitles (`synchronisation.py`)

Trigger: If not all required external subtitles in your preferred languages are present for a video

Prompt: "Not all external subtitles present for [video]. Do you want to clean internal subtitles anyway?"

Options:

  • 1 = Clean internal subtitles anyway (removes all internal subtitles for compatibility)
  • 2 = Do NOT clean internal subtitles (leaves internal subtitles untouched)

Purpose: Ensures you have control over internal subtitle removal, especially when some external subtitles are missing.

4. 🎯 Manual Offset Verification and Correction (`synchronisation.py`)

Trigger: If any subtitles had timing offset corrections applied during synchronisation

Process:

  • Initial Verification: For each corrected subtitle, verify if timing matches audio well enough
  • Video Opening Options: Automatically open video or show path for manual opening
  • Correction Menu: Provides multiple options for handling subtitle timing and quality
  • Automatic Handling: If marked as DRIFT, acquisition.py restarts automatically to download new candidates

Purpose: Ensures perfect synchronisation quality through manual verification when needed.

Available Menu Options:

  1. Open video file
  2. Type in a correction (manual timing adjustment)
  3. Restore original offset
  4. Clear logs in terminal (only visual)
  5. Mark as Drift (will download a new subtitle after all videos are checked)
  6. Remove subtitle and skip this movie-language combination (adds to skipped_movies)

🛡️ Safety Philosophy

Interactive prompts protect your files and provide fallbacks when automation fails, while maintaining maximum automation.


⚙️ HOW SUBSERVIENT WORKS: FOUR-PHASE AUTOMATION

Subservient runs through four automated phases:

Phase Script Purpose
🎮 1 subordinate.py Setup and preparation
📤 2 extraction.py Extract internal subtitles
🌐 3 acquisition.py Download from OpenSubtitles
🎯 4 synchronisation.py AI sync and cleanup

Each phase calls the next automatically. User input only for edge cases.

🎮 PHASE 1: SETUP & ANCHORING (`subordinate.py`)

Role of subordinate.py: subordinate.py serves as the central reference point for all other scripts in the native Python version.
You place subordinate.py directly in the folder containing your video files,
and all other scripts use its location to discover and process videos in that directory and subdirectories.

Key Functions:

  • 🎯 Process Launcher: Initiates the complete 4-phase automation (Option 1) with pre-flight checklist verification
  • 🏠 Central Hub: Provides main menu access to all tools, configuration, and documentation
  • 📍 Anchor Point: Other scripts locate videos relative to subordinate.py's position
  • 🔧 Tool Collection: Subtitle coverage scans, subtitle cleaning (ads/credits removal), configuration management

Technical Operations:

  • Package Management: Installs core dependencies (colorama, langdetect, requests, tqdm, platformdirs) if missing
  • Pathfile Creation: Writes anchor directory path to persistent pathfile for cross-session access
  • Configuration Management: Creates and validates configuration files with video/audio processing settings
  • Initial Setup: Ensures directory structure and required files exist before processing begins
  • Menu Interface: Provides interactive navigation between all four phases

Files Modified: pathfile.txt, config files, dependency installations
Manual Input: [Manual Input 1] - Configuration validation and directory selection

📤 PHASE 2: EXTRACTION (`extraction.py`)

Role of extraction.py: The subtitle discovery engine that intelligently harvests internal subtitles already embedded within your video files.
Since internal subtitles are perfectly synchronized and don't count against OpenSubtitles download quotas,
extraction prioritizes using existing content before searching online.

Key Functions:

  • 🔍 Container Scanning: Systematically analyzes video files for embedded subtitle streams
  • 🌍 Smart Language Detection: Uses AI to identify subtitle languages with high accuracy
  • 🎯 FORCED Subtitle Preservation: Protects essential foreign dialogue subtitles from removal
  • 🧹 Intelligent Track Management: Handles multiple subtitle/audio tracks based on user preferences

Technical Operations:

  • Container Analysis: Uses ffprobe to scan video files for embedded subtitle streams
  • Language Detection: Analyzes subtitle content using langdetect library for automatic language identification
  • Subtitle Extraction: Executes mkvmerge operations to extract internal subtitles to .srt files
  • Track Management: Preserves forced subtitle flags and handles multiple language tracks per video
  • Format Conversion: Converts various subtitle formats (VobSub, ASS, etc.) to standardized SRT format

Files Created: {video_basename}.{lang}.srt files extracted from video containers
Manual Input: [Manual Input 2] - Language confirmation and forced subtitle handling

🌐 PHASE 3: ACQUISITION (`acquisition.py`)

Role of acquisition.py: The subtitle hunting specialist that searches the OpenSubtitles database when internal subtitles are missing or incomplete.
Uses sophisticated search strategies and automatic retry logic to find the best available subtitles for your videos.

Key Functions:

  • 🔍 Multi-Strategy Search: Employs hash-based, filename-based, and manual query approaches
  • 🌐 OpenSubtitles Integration: Handles JWT authentication and API communication seamlessly
  • 📥 Smart Download Logic: Selects top-rated subtitles with automatic 503 error retry handling
  • 🤔 Interactive Fallbacks: Provides manual search options when automatic matching fails

Technical Operations:

  • API Integration: Authenticates with OpenSubtitles API using JWT tokens for subtitle database access
  • Search Strategy: Implements multiple search algorithms (hash-based, filename-based, manual query)
  • Download Logic: Downloads top-rated subtitles with automatic retry for 503 server responses
  • File Management: Saves subtitles with numbered naming convention ({video}.{lang}.number{N}.srt)
  • Fallback Handling: Provides manual search interface when automatic matching fails

Files Created: {video_basename}.{lang}.number{N}.srt files from OpenSubtitles database
Manual Input: [Manual Input 3] - Search term specification and subtitle selection

🎯 PHASE 4: SYNCHRONIZATION (`synchronisation.py`)

Role of synchronisation.py: The precision timing expert that uses AI-powered ffsubsync technology to achieve perfect subtitle synchronization.
Employs intelligent quality control and provides manual verification tools for edge cases requiring human judgment.

Key Functions:

  • 🤖 AI Synchronization: Leverages ffsubsync's audio analysis for automatic timing alignment
  • 📊 Quality Assessment: Uses configurable thresholds to classify sync quality automatically
  • 🎛️ Manual Verification: Provides interactive tools for fine-tuning problematic subtitles
  • 🧹 Final Cleanup: Removes temporary files and organizes results for optimal user experience

Technical Operations:

  • AI Synchronization: Executes ffsubsync to align subtitle timestamps with video audio tracks
  • Offset Calculation: Compares original vs synchronized timestamps to measure correction accuracy
  • Quality Thresholds: Applies configurable accept/reject thresholds (default: 0.05s/0.3s) for automatic processing
  • Manual Verification: Creates offset tracking file for subtitles requiring human review
  • File Cleanup: Removes .DRIFT, .FAILED, and redundant numbered subtitle files

Files Created: Final synchronized .srt files, movies_with_linear_offset.txt tracking file
Manual Input: [Manual Input 4] - Offset verification and timing correction interface


🔍 TROUBLESHOOTING COMMON ISSUES

Here are some common issues and solutions to help you get Subservient up and running:

0. File Rename Errors During Extraction

💥 Symptom: Error about "Cannot rename subtitle file - target already exists" during extraction.

✅ Solution:

  • This happens when Subservient was interrupted previously and left incomplete files
  • Remove incomplete subtitle files: Look for files like *.und0.srt, *.temp.srt, or duplicate .forced.srt files
  • Clean restart: Delete any partial/temporary subtitle files and run Subservient again
  • Subservient will show you exactly which files are causing conflicts

🐍 Python Issues

1. Python Not Found / Incorrect Version

💥 Symptom: Running python --version shows an error or an older version (<3.8).

✅ Solution:

  • Reinstall Python from the official Python website
  • ⚠️ Ensure you check "Add Python to PATH" during installation
  • Verify with python --version again

📁 File Structure Issues

2. Missing Files or Incorrect Folder Structure

💥 Symptom: Errors about missing files or modules when running Subservient.

✅ Solution:

  • Ensure all required files are in the same folder as subordinate.py
  • Required files: extraction.py, acquisition.py, synchronisation.py, .config, requirements.txt, README.md
  • Do not move or delete any files until subordinate.py shows the main menu
3. Permission Errors

💥 Symptom: Errors about not being able to access or modify files/folders.

✅ Solution:

  • Ensure you have read, write, and execute permissions
  • On Windows: Run as administrator if needed
  • Check folder permissions for video files location

📦 Dependency Issues

4. Package Installation Issues

💥 Symptom: Errors when Subservient tries to install Python packages

✅ Solution:

  • Install packages manually: pip install <package> (e.g., pip install requests)
5. FFmpeg Not Found or Not Working

💥 Symptom: Errors about ffmpeg command not found or FFmpeg-related failures.

✅ Solution:

6. MKVToolNix Not Found

💥 Symptom: Errors about mkvmerge command not found or MKV extraction failures.

✅ Solution:

  • MKVToolNix is required for extracting subtitles from MKV files
  • See Step 4: Install & Verify Requirements for detailed installation instructions
  • If still not found after installation: MKVToolNix may not have been added to PATH automatically
    • Find your installation folder (usually C:\Program Files\MKVToolNix)
    • Add this folder to your system PATH environment variable
    • Windows PATH Guide: Search "Environment Variables" → Edit System Environment Variables → Environment Variables → Select "Path" under System Variables → Edit → New → Add your MKVToolNix folder path → OK
    • Restart Command Prompt and test with mkvmerge --version
7. Microsoft Visual C++ Runtime Error

💥 Symptom: Error messages about missing Microsoft Visual C++ Redistributable or version 14.0 or higher required.

✅ Solution:

🌐 API Issues

8. OpenSubtitles API Errors

💥 Symptom: Errors related to API key, username, or password.

✅ Solution:

  • ✔️ Double-check credentials in .config file
  • ✔️ Verify API consumer exists on OpenSubtitles website
  • ✔️ Check account status (not banned/suspended)
  • ✔️ Verify API status on OpenSubtitles website
  • ✔️ New: Check for 503 errors in logs - these are temporary server overload issues that Subservient handles automatically
8b. 503 Service Unavailable Errors

💥 Symptom: Repeated 503 errors when downloading subtitles, even with valid credentials.

✅ Solution:

  • This is normal! 503 errors indicate OpenSubtitles servers are temporarily overloaded
  • Subservient handles this automatically with intelligent retry logic
  • If persistent: Increase download_retry_503 setting in .config (default: 6)
  • Check logs: Subservient shows retry attempts and automatically backs off when needed
9. Network Issues

💥 Symptom: Unable to connect to internet or OpenSubtitles API.

✅ Solution:

  • Check internet connection
  • Configure proxy/VPN settings if needed
  • Ensure firewall allows Python/Subservient internet access

🚀 Runtime Issues

10. File Not Found / Incorrect File Paths

💥 Symptom: Errors about files not being found during processing.

✅ Solution:

  • Place subordinate.py in correct folder with video files
  • Avoid network drives or removable media
  • Run subordinate.py once after moving to re-anchor

🔧 If Issues Persist:

  1. Re-anchor Setup: Simply run subordinate.py and it will automatically detect and resolve file location issues
  2. Manual Reset: If problems continue, manually delete the Subservient_pathfiles directory (typically in your user config folder) and rerun subordinate.py in the Subservient folder
  3. Fresh Start: Backup the .config and re-download Subservient from GitHub and replace your .config file. Then meticulously follow the installation setup at the top of this README.
11. Subservient Crashes or Disappears Suddenly

💥 Symptom: Program closes unexpectedly without showing error messages, or freezes during execution.

✅ Solution:

  1. Run from Terminal/Command Prompt to see error messages:

    • Windows: Open cmd.exe, drag subordinate.py into the window, press Enter
    • Linux/macOS: Open terminal, drag subordinate.py into the window, press Enter
    • This prevents Subservient from closing automatically and shows error details
  2. Basic Troubleshooting:

    • Ensure sufficient free memory (at least 2GB RAM available)
    • Close unnecessary programs
    • Check if antivirus software is interfering
  3. Get Help:

    • If you can't solve the error: create an issue on GitHub Issues with the error message
    • BMAC supporters can contact me directly on Discord for faster support

🎯 User Error Issues

12. "Package Requirements Error" when running Subservient for the first time

💥 Symptom: Missing packages error when running extraction.py, acquisition.py, or synchronisation.py directly.

✅ Solution:

  • This is normal behavior! Always start with subordinate.py
  • Individual scripts are designed to be run through subordinate.py
  • subordinate.py handles package installation and setup
13. Initial Setup Not Complete Errors

💥 Symptom: Scripts report incomplete setup, even after running subordinate.py.

✅ Solution:

  • Run subordinate.py from main Subservient folder (not movie folder), so that initial setup triggers
  • Setup creates anchor points that all scripts need and should prevent the incomplete setup message from coming up again

🆘 Need More Help?

If you encounter issues not covered here:

  • 📚 Check the Subservient GitHub repository
  • 🐛 Open a new issue with detailed information
  • 💬 Direct support available through Discord for supporters

❓ FREQUENTLY ASKED QUESTIONS (FAQ)

🔧 Installation & Setup

1. Do I need to install Python and dependencies every time?

Answer: No, you only need to install Python and the required dependencies (packages and ffmpeg) once. Subservient will remember these settings and use them for future runs on the device used for installing.

2. Can I use Subservient on macOS/Linux?

Answer: Yes, Subservient is cross-platform and works on Windows, macOS, and Linux. The installation and setup process is similar on all platforms

⚠️ Disclaimer: Subservient is built and tested on Windows. While programmed with cross-platform compatibility in mind, there could be lingering issues. Please consult the GitHub repository for known issues and please report an issue yourself if you encounter a problem.

🔐 Credentials & API

3. Why do I need OpenSubtitles credentials?

Answer: Subservient uses your OpenSubtitles credentials to access the OpenSubtitles API, required for searching and downloading subtitles. Your credentials are stored locally and are securely handled by OpenSubtitles.

4. What if I don't have an OpenSubtitles account?

Answer: You can create a free OpenSubtitles account on their website. Free accounts have limitations (download limits), but are sufficient for testing and light usage. For heavier usage, consider upgrading to VIP.

⚙️ Configuration & Usage

5. Can I customize subtitle languages and settings?

Answer: Yes, you can customize subtitle languages, file handling options, and other settings in the .config file. Subservient also provides interactive prompts to guide you through configuration.

6. How does Subservient handle TV series?

Answer: Subservient can automatically detect and process TV series with multiple episodes, as long as they follow consistent naming (e.g., S01E01, S01E02). Set series_mode=true in your config for series processing.

🛠️ Troubleshooting

7. What if Subservient fails to find subtitles?

Answer: Subservient handles errors and missing subtitles gracefully. It will log issues and prompt for input when necessary. Subservient prompts you to manually search for subtitles or adjust settings in the .config file (it's surprisingly polite about failure).

8. Is there a download limit for subtitles?

Answer: Subservient has no hard limit, but OpenSubtitles accounts do:

  • 🆓 Free (Dev Mode): ~100 downloads/day
  • 👑 VIP: 1000 downloads/day
  • 🆓 Free (Non-Dev): 5-10 downloads/day

📜 Legal & Support

9. Can I download subtitles for copyrighted content?

Answer: Subservient can download subtitles for all content available on OpenSubtitles, which is generally a huge number of videos. However, you should only use it for content you own or have rights to use subtitles for. Please refer to the legal disclaimer near the bottom of the Readme file.

10. Where can I get help and support?

Answer:

Note: Support is provided when possible, but time is limited. Direct Discord support is available for those who support the project financially.

📚 CHANGELOG

🚀 Recent Major Updates

Date Version Feature Description
🚀 2026-01-28 v0.89.2 Tools & Options Update Added "Delete moved_subtitles folders" cleanup tool and manual verification option 6 (skip & exclude)
🚀 2026-01-26 v0.89 Season Maps & DRIFT Recovery Pre-downloaded subtitle support (Season Maps) and automatic DRIFT recovery system
🚀 2025-11-30 v0.88 Smart Sync & Series Enhancement Smart Sync mode for optimal subtitle selection and enhanced TV-Series functionality
🌐 2025-11-23 v0.87 Early TV-Series Support TV-Series mode with basic SxxExx detection and episode processing
🐳 2025-08-04 v0.85 Docker Support Full Docker containerization with docker-compose support and Unraid compatibility!
🧹 2025-08-03 v0.83 Subtitle Cleaner Full subtitle cleaning tool with ad removal, backup/restore, and batch processing!
💬 2025-08-01 v0.81 7 bugs fixed! More in-depth (forced)subtitle preservation, language code mismatch fix and more!
🔥 2025-07-28 v0.80 ALPHA release Video synchronisation is fully operational, repo is public!
🐛 2025-07-20 v0.79 Single/batch video syncs now work! Public alpha release
🔧 2025-07-05 v0.78 Manual Verification Added manual offset verification menu and editor

🎉 Current Version: v0.89.2 - New: moved_subtitles cleanup tool & enhanced manual verification with skip option!


🚀 Future Updates & Roadmap

Subservient is actively developed with exciting new features planned! Here's what's coming next:

📅 Updates that I should be doing

Priority Feature Target Description
🤝 Planned 📺 TV-Series Support v0.9 BETA Complete automation for TV shows with episode detection
📋 High 📚 Containerization for easy use v0.95 Packaging everything in a container/executable to make it easy to install
🔥 High 🛠️ 'Tools' option in Subservient menu & complete LINUX bugfixing v1.00 RELEASE manual syncing, batch-renaming, muxing/de-muxing, manual subtitle offset tools, you name it!
Medium 📊 Smarter subtitle search queries v1.06 More fallbacks for more comprehensive searches
Medium 🔄 Asynchronous synchronisation (whaat?) v1.08 Synchronizing multiple videos simultaneously

💬 Community Suggestions Welcome!

Have an idea for Subservient? Feel free to post your ideas in the Subservient GitHub repo!

How to Suggest Method Response Time
🐛 Bug Reports GitHub Issues In my spare time (varies a lot)
💡 Feature Requests GitHub Discussions In my spare time (varies a lot)
VIP Suggestions Discord (for supporters) Same day, possibly within minutes after your message

🎉 Get Involved!

Subservient thrives on community feedback. Whether you're a casual user or a power user, your suggestions help shape the future of the project. Don't hesitate to share your ideas, no matter how big or small!


💝🎉 Support & Donations

🎯 Subservient Will Always Be Free

Subservient is and will always remain completely free for personal use. This project was created out of passion for automation and the belief that useful tools should be accessible to everyone. No features are locked behind paywalls, no subscriptions are required, and you'll never be pressured to pay for anything.

❤️ But Your Support Is Warmly Welcome

While financial support is never required or expected, it is incredibly meaningful when offered. This project is developed and maintained entirely in my free time, and every contribution (whether code, feedback, or financial), helps me dedicate more time to improving Subservient and assisting users.

🎯 Ways to Support (All Optional!)

Method Description Impact
GitHub Star Star the repository Helps others discover Subservient
🐛 Bug Reports Report issues you encounter Makes Subservient better for everyone
💡 Feature Requests Suggest improvements Shapes future development
🗣️ Word of Mouth Tell others about Subservient Grows our community
Buy Me a Coffee BMAC donation page Helps me dedicate more time to improving Subservient, while keeping it free for everyone ❤️

☕ About My Buy Me a Coffee Page

Beyond being a platform for optional financial support, my Buy Me a Coffee page serves as the central hub for project updates and development insights. Here's what you'll find:

  • 📢 Regular Updates: Detailed posts about Subservient development progress, new features, and behind-the-scenes insights
  • 🚀 Project Announcements: First looks at new projects I'm working on, from early concepts to beta releases
  • 💬 Community Interaction: Direct communication with supporters and the broader community
  • 🎯 Development Roadmap: Insights into what's coming next and how community feedback shapes development priorities

Whether you choose to support financially or just follow along, it's a great way to stay connected with the ongoing development of Subservient and discover other automation tools I'm building!

🙏 A Heartfelt Thank You

Whether you use Subservient daily or just tried it once, whether you've contributed code or simply starred the repo, whether you've supported financially or spread the word, thank you! Every interaction, no matter how small, means the world to me and keeps this project alive 💝
-- Nexigen


📄 License

This project is licensed under the GPL-3.0 License.

🆓 Open Source License

This software is free and open source, licensed under the GNU General Public License v3.0. You are free to:

  • Use the software for any purpose
  • Study how the software works and modify it
  • Distribute copies of the software
  • Distribute modified versions of the software

📋 GPL-3.0 Requirements

If you distribute this software or create derivative works, you must:

  • 📝 Provide source code when distributing binaries
  • 🏷️ Include copyright notices and license information
  • 📋 License derivatives under GPL-3.0 as well
  • 📢 Document changes made to the original code

📖 Full License Text

For the complete license terms, see the LICENSE file in this repository or visit: https://www.gnu.org/licenses/gpl-3.0.html

💡 In Simple Terms: This is free software that will always remain free. You can use, modify, and share it, but if you distribute modified versions, they must also be open source under GPL-3.0.


⚖️ Legal Disclaimer

Subservient is designed for use with content you legally own or have rights to process. This software provides technical functionality for subtitle management and synchronization, similar to media players, converters, and other multimedia tools.

The inclusion of various technical format filters and metadata cleaning capabilities serves interoperability purposes only and enables the software to work with diverse file naming conventions found in multimedia content, regardless of source.

Users are responsible for ensuring their use of this software complies with applicable copyright laws and terms of service of subtitle providers. The developers do not endorse or encourage any illegal activity.

🙏 Acknowledgments

  • Thanks to all the contributors and open-source projects that made this software possible
  • Special thanks to the OpenSubtitles team for providing an excellent API and subtitle database
  • Special thanks to KBlixt/subcleaner for the powerful subtitle cleaning engine integrated into Subservient
  • Special thanks to Phil Wedel (vnakkar) for contributing the OpenSubtitles movie hash matching feature (PR #5)
  • Very special thanks to all of my current and future supporters! You are simply the best and the biggest reason why I will release most of my projects free and largely open-source.





**🎬 Made with ❤️ for the subtitle automation community**

Version GitHub Python Docker License

Plex Jellyfin Emby Unraid

Happy subtitle processing! 🎯


About

Subservient is an open-source, fully automated subtitle synchronization suite, with user friendliness at heart. Fetch, download and synchronize subtitles in your preferred languages with the simple press of a button. Available natively using Python, and available through a Docker container

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors 2

  •  
  •