A collection of portable scripts for managing, standardizing, and repairing a large media library.
This project is licensed under the MIT License - see the LICENSE file for details.
- Python 3.6+
- FFmpeg & FFprobe β Must be installed and available on
PATH.brew install ffmpeg
Medinox/
catalog/ β Read-only discovery & reporting (e.g. Master Dashboard)
organize/ β File naming, metadata, merging split parts
process/ β Active media transformation
utils/ β Shared utilities (logger, ffprobe, constants, scoring, filesystem)
config/ β Configuration files for library paths
output/ β All generated reports, dashboards, logs, and state
Medinox features an intelligent multi-threading system (utils/system.py) that accelerates scanning and transformation.
- Hardware-Aware: Automatically detects if the target directory is on a Solid State Drive (SSD) or a mechanical Hard Disk Drive (HDD) on macOS.
- I/O Protection: Dynamically throttles parallel workers down to 2 concurrent threads for HDDs to prevent catastrophic disk I/O thrashing, while fully unlocking thread limits for fast NVMe/SSDs (up to 16 threads).
- Timeouts & Safety: Built-in 5-second timeouts for drive detection and 30-second timeouts for
ffprobeto ensure scripts never hang indefinitely on sleeping or corrupted drives. - Thread-Safe: Uses
threading.Lockfor all log file I/O and history file writes to prevent data corruption under parallel execution.
All scripts utilize a unified MediaLogger utility (utils/logger.py):
- Dynamic Progress Bars: Visually track the scan and processing percentage in real time.
- Execution Summaries: Clean, formatted blocks outputting total files processed, total time taken, and the exact paths to generated CSV/HTML/Log artifacts.
- Log Rotation: Daily rolling console logs are automatically captured in
output/logs/.
Every destructive script defaults to a safe dry-run. No files are modified unless you pass the activation flag:
| Script | Activation Flag | What it Does |
|---|---|---|
organize/standardize.py |
--rename <csv> |
Applies renames from a CSV plan |
process/embed_subtitles.py |
--apply |
Embeds SRT files into containers |
process/extract_subtitles.py |
--apply |
Extracts embedded subs to .srt files |
process/strip_subtitles.py |
--apply |
Removes subtitle tracks |
process/integrity_check.py |
--apply |
Runs scan or repair for real |
process/transcode.py |
--apply |
Transcodes AVC files to HEVC or AV1 |
process/convert_container.py |
--apply |
Remuxes to preferred containers losslessly |
organize/tag_metadata.py |
--apply |
Writes metadata tags to files |
organize/merge_parts.py |
--apply |
Performs the actual merge |
catalog/find_duplicates.py |
--delete |
Trashes lower-quality duplicates |
Most scripts accept both a single file and a directory:
| Script | File | Directory |
|---|---|---|
process/embed_subtitles.py |
β | β |
process/extract_subtitles.py |
β | β |
process/strip_subtitles.py |
β | β |
process/integrity_check.py |
β | β |
process/transcode.py |
β | β |
process/convert_container.py |
β | β |
organize/tag_metadata.py |
β | β |
All catalog/ scripts |
β | β (library-wide) |
organize/standardize.py |
β | β |
organize/merge_parts.py |
β | β (split folder) |
All scripts process files in case-insensitive alphabetical order (matching macOS Finder sort).
Consistent tagging across Ultrawide, IMAX, and Open Matte content:
| Category | Threshold (Total Pixels) | Tag |
|---|---|---|
| 4K | > 6,000,000 | 4K |
| 1080p | 1,500,000 β 6,000,000 | 1080p |
| 720p | 650,000 β 1,500,000 | 720p |
| Other | < 650,000 | Actual height (e.g. 480p) |
All scripts that modify files preserve the original atime/mtime to keep Finder sort order intact.
Orchestrator script that generates the Master Media Dashboard. It reads paths from config/catalog_jobs.csv.
- Outputs:
output/dashboard/index.html,output/dashboard/Catalog.xlsx, and individual runs inoutput/dashboard/latest/.
Generates an interactive HTML dashboard and CSV report of the media library.
- Usage:
python3 Medinox/catalog/catalog.py /path/to/movies [/path/to/more ...] - Features: Deep HDR10+/Dolby Vision/HLG detection, sortable table, multi-folder support.
- Outputs:
output/reports/media_catalog_<ts>.htmland.csv
Single-command library audit β a "what still needs work" report.
- Usage:
python3 Medinox/catalog/health_check.py /path/to/movies [/path/to/more ...] - Checks: Missing subtitles, AVC codec, non-standard names, low resolution, legacy containers, missing audio, unreadable files.
- Output: Console summary +
output/reports/health_check_<ts>.csv&.html - Read-only: Never modifies any files.
Detects duplicate movies by fuzzy title+year matching and recommends which to keep.
- Usage:
python3 Medinox/catalog/find_duplicates.py /path/to/movies [/path/to/more ...] [--delete] - Matching: Normalizes titles (strips junk tags, punctuation) then groups by title+year.
- Scoring: Resolution, bitrate, codec efficiency, bit depth, audio, subtitle presence.
--delete: Moves lower-quality duplicates to Trash (macOS only).- Output:
output/reports/duplicates_<ts>.csv
Compares two video files and calculates a quality score.
- Usage:
python3 Medinox/catalog/compare.py file1.mkv file2.mp4 - Scoring: Pixel count, bitrate, codec efficiency (AV1 > HEVC > AVC), HDR bonus, audio channels.
Renames files to a clean standardized format based on technical metadata.
- Output Format:
Title (Year).Resolution.V_Codec.HDR.A_Codec.A_Channels.ext- HDR tag omitted for SDR. Example:
Inception (2010).4K.HEVC.HDR10.AAC.5.1.mkv
- HDR tag omitted for SDR. Example:
- Workflow:
python3 Medinox/organize/standardize.py /path/to/moviesβ generatesoutput/reports/rename_plan_<ts>.csv- Review and edit the CSV
python3 Medinox/organize/standardize.py --rename <csv>
- Rollback:
python3 Medinox/organize/standardize.py --rollback <csv>
Writes technical info into the video's internal Title and Comment tags.
- Usage:
python3 Medinox/organize/tag_metadata.py <file_or_dir> [--apply] - Tag Format:
4K | HEVC | HDR10 5.1 | 45.2Mbps - Detects: Dolby Vision via DOVI configuration records.
Scans for movies split into multiple parts (CD1, CD2, Disc 1, etc.).
- Usage:
python3 Medinox/organize/find_splits.py /path/to/movies - Note: Only matches strict CD/Disc/Disk patterns.
Checks that all parts have identical stream configurations before merging.
- Usage:
python3 Medinox/organize/verify_splits.py /path/to/split_folder
Merges split parts into a single file.
- Usage:
python3 Medinox/organize/merge_parts.py /path/to/split_folder [--apply] [--reencode] - Fast-concat: Lossless stream copy (requires identical stream configs).
- Re-encode (
--reencode): Scales to highest resolution, encodes H.264 + AAC 192k. Auto-triggered on resolution mismatch. - Output:
<parent_dir>/<folder_name>_merged.<ext>
Lossless remux between containers (e.g., .avi β .mkv, .ts β .mp4) without re-encoding.
- Usage:
python3 Medinox/process/convert_container.py <file_or_dir> [--apply] - Supported Maps:
.avi,.wmvto.mkv;.ts,.flv,.mov,.m4vto.mp4. - Safety: Original moved to macOS Trash (via Finder) after successful conversion.
- Deduplication: History file at
output/history/container_convert_history.txt.
Transcodes AVC (H.264) files to a more efficient codec to save disk space.
- Usage:
python3 Medinox/process/transcode.py <file_or_dir> [--codec hevc|av1] [--apply] [--delete] [--cpu] - Codecs:
hevc(default) β ~40β50% smaller. Universal compatibility.av1β ~50β60% smaller. Best efficiency, limited device support.
- Hardware Acceleration: Auto-detects VideoToolbox on macOS for fast HEVC encoding. Use
--cputo force software encoding for maximum quality. - Encoders:
hevc_videotoolbox(HW),libx265(CPU),libsvtav1(AV1). - Output: Creates
<name>.hevc.mkvor<name>.av1.mkvalongside the original. --delete: Trashes the original after successful conversion. Use with caution.
Scans for corruption and repairs broken container indices.
- Usage:
python3 Medinox/process/integrity_check.py <file_or_dir> [--mode scan|deep|repair] [--apply] - Modes:
scan(quick, first 5s),deep(full decode),repair(lossless remux). - Repair Safety: Verifies output is β₯ 90% original size before replacing.
Embeds external .srt files into video containers.
- Usage:
python3 Medinox/process/embed_subtitles.py <file_or_dir> [--apply] - SRT matching: Looks for
<same_name>.srtnext to the video file. - Safety: Includes a strict 5MB size limit to reject falsely named video files and prevent memory lockups.
- Encoding support: Auto-detects UTF-8, UTF-16, UTF-8 BOM, Latin-1, CP1252, ISO-8859-1.
- Timestamp repair: Fixes missing ms, periodβcomma, single-digit hours, re-indexes cues.
- Deduplication: History file at
output/history/subtitles_merge_history.txt. - SRT cleanup: Trashes SRT after merge (macOS, via Finder) β only if video had 0 existing subs.
- Container handling:
.aviβ.mkv; MP4 usesmov_text, all others usesrtcodec.
Extracts embedded subtitle tracks to external .srt files.
- Usage:
python3 Medinox/process/extract_subtitles.py <file_or_dir> [--apply] - Language tagging: Outputs
Movie.eng.srt,Movie.fre.srt, etc. Falls back to track number. - Format conversion: Converts ASS/SSA/mov_text/etc. to SRT automatically.
- Safety: Will not overwrite existing
.srtfiles. - Use case: Run before
strip_subtitles.pyto preserve subtitle data externally.
Removes all embedded subtitle tracks from a video container.
- Usage:
python3 Medinox/process/strip_subtitles.py <file_or_dir> [--apply] - Safety: Original moved to macOS Trash (via Finder) before the cleaned file takes its place.
- Stream mapping: Uses
0:v? 0:a?so files missing video or audio don't cause errors.
| Module | Purpose |
|---|---|
utils/logger.py |
Thread-safe MediaLogger with daily log rotation, progress tracking, and summary output |
utils/system.py |
Hardware-aware thread count detection (SSD/HDD) and dependency checks |
utils/constants.py |
Single source of truth for VIDEO_EXTENSIONS and codec maps |
utils/ffprobe.py |
Shared FFprobe wrapper: get_metadata(), detect_hdr(), get_resolution_tag(), get_audio_label() |
utils/fs.py |
Cross-platform safe_trash() β uses Finder on macOS, falls back to permanent delete |
utils/scoring.py |
Shared score_file() for quality-based duplicate comparison |
- Safe Trash: Scripts that remove originals after processing use
utils/fs.py:safe_trash(), which calls Finder on macOS and falls back to permanent delete on other platforms. - SSD Detection:
utils/system.pyusesdiskutilon macOS for drive type detection. On other platforms it defaults to conservative HDD threading.
output/dashboard/β Master Dashboard, Merged Catalogs (Excel), and Latest Library HTML Reports.output/reports/β Standalone CSV plans, HTML dashboards, health reports.output/history/β Script state & processed file history.output/logs/β FFmpeg debug logs (created on failure, auto-deleted on success).