Last active
May 27, 2025 22:38
-
-
Save ph33nx/0c320ae1c8d4dfb29c560d8a9f9088ad to your computer and use it in GitHub Desktop.
Python script to recursively download missing subtitles for video files in formats like .mp4, .mkv, .avi, and .mov. Ideal for Jellyfin, Plex, Emby, and other media servers in homelab setups. Automatically fetches the best-matched .srt subtitles in your preferred language using subliminal. Boosts your media library with accurate subtitles for mov…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
Author: ph33nx | |
URL: https://github.com/ph33nx | |
Description: | |
This script automatically scans a directory (recursively) for video files and downloads the best matching subtitles using the `subliminal` library. | |
It avoids duplicate work by checking for existing `.srt` subtitle files and is suitable for organizing media libraries in homelab setups. | |
Key Features: | |
- Supports popular video formats: MP4, MKV, AVI, MOV | |
- Downloads subtitles in the preferred language (default: English) | |
- Skips hidden/system files and already-subtitled videos | |
- Useful for Jellyfin, Plex, Emby, and other media server setups | |
- Ideal for homelab automation scripts and post-processing media workflows | |
Keywords: | |
jellyfin, plex, media server, subtitles, movies, homelab, subliminal, automation, python | |
Requirements: | |
- Python >= 3.8 | |
- `subliminal` and `babelfish` Python packages | |
Installation: | |
pip install subliminal babelfish | |
Usage: | |
python download_subtitles.py <directory> [language] | |
Arguments: | |
<directory> Path to the root folder where your media files are stored. | |
[language] Optional subtitle language code (default: "eng" for English). | |
Example: | |
python download_subtitles.py /mnt/media/movies | |
python download_subtitles.py /mnt/media/tvshows spa | |
Note: | |
- Subtitle files are saved alongside the video with `.srt` extension. | |
- The script uses a local DBM cache for faster repeated scans. | |
""" | |
import os | |
import sys | |
from babelfish import Language | |
from subliminal import download_best_subtitles, region, save_subtitles, scan_video | |
# Configure subliminal cache | |
region.configure('dogpile.cache.dbm', arguments={'filename': 'cachefile.dbm'}) | |
# Supported video extensions | |
VIDEO_EXTENSIONS = ('.mp4', '.mkv', '.avi', '.mov') | |
def download_subtitles_for_directory(directory, languages=['eng']): | |
""" | |
Recursively scan a directory for video files and download subtitles if missing. | |
:param directory: Path to the directory to scan | |
:param languages: List of languages for subtitles (default: ['eng']) | |
""" | |
for root, _, files in os.walk(directory): | |
for file in files: | |
# Skip files starting with dot (e.g., ".file" or "._file") | |
if file.startswith('.') or file.startswith('._'): | |
print(f"Skipping hidden or system file: {file}") | |
continue | |
if file.endswith(VIDEO_EXTENSIONS): | |
video_path = os.path.join(root, file) | |
subtitle_path = os.path.splitext(video_path)[0] + '.srt' | |
# Skip if subtitles already exist | |
if os.path.exists(subtitle_path): | |
print(f"Subtitle already exists for: {video_path}") | |
continue | |
print(f"Processing video: {video_path}") | |
try: | |
# Scan the video | |
video = scan_video(video_path) | |
if not video: | |
print(f"Could not process video: {video_path}") | |
continue | |
# Download subtitles | |
subtitles = download_best_subtitles([video], {Language(lang) for lang in languages}) | |
if video in subtitles: | |
save_subtitles(video, subtitles[video]) | |
print(f"Subtitle downloaded and saved for: {video_path}") | |
else: | |
print(f"No subtitles found for: {video_path}") | |
except Exception as e: | |
print(f"Error processing {video_path}: {e}") | |
if __name__ == "__main__": | |
if len(sys.argv) < 2: | |
print("Usage: python download_subtitles.py <directory> [language]") | |
sys.exit(1) | |
directory = sys.argv[1] | |
language = sys.argv[2] if len(sys.argv) > 2 else 'eng' | |
if not os.path.isdir(directory): | |
print(f"Invalid directory: {directory}") | |
sys.exit(1) | |
print(f"Scanning directory: {directory} for language: {language}") | |
download_subtitles_for_directory(directory, languages=[language]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment