Matches a folder of Blu-ray rips against dvdcompare.net comparisons and renames the files to reflect the exact release/edition and cut (Theatrical vs Director's Cut, etc.) they correspond to, based on runtime matching.
By default this runs as a Textual TUI: selection menus instead of
typed numbers, a live file/match table that fills in as matches are
found, an editable tag field with a live rename preview, and a confirm
step before anything is touched. Pass --classic for the original plain
text-prompt interface instead (e.g. for scripting or a very narrow
terminal).
- Guesses a search title from your folder name (strips resolution, codec, release-group tags, etc.) and lets you override it.
- Searches dvdcompare.net's advanced search and shows you the matching titles in a selection list.
- Fetches that title's comparison page and shows you every disc
release/edition it lists, along with any runtimes it could parse for
both the main feature (from the "CUTS" section) and bonus content
(from the "Extras" field, e.g.
"Is There a Stargate?" featurette (12:11)). - Reads the actual duration of every video file in your folder with
ffprobeand matches each one -- main feature or extra alike -- to the closest-duration entry from that combined list, accounting for the ~4.3% PAL/NTSC speed difference where relevant. The file table fills in with each match ([feature]/[extra]) as it's found, alongside a live preview of the new filename. - Shows you the full rename plan (a persistent dry-run preview, updated live as you edit the tag field) and asks for confirmation before touching anything.
If a file can't be confidently matched by duration -- e.g. a release with
no listed runtime at all for its main feature (this happens; some
dvdcompare entries just say "No cuts" without timing it) -- select its row
and press a to assign it a label manually from the release's known
cut/extra names (even untimed ones, pulled from quoted phrases in the
site's notes), or enter a custom label. Pass --auto-only to disable this
and just leave unmatched files untouched instead.
Nothing is renamed without an explicit confirmation step, files are never overwritten, and any file with no confident duration match -- and no manual assignment -- is left untouched and reported separately.
feature file: {title} ({year})[-{tag}].{ext} e.g. Dune (2021).mkv
extra file: {extra name}[-{tag}].{ext} e.g. My Desert, My Dune featurette.mkv
{tag} is optional and off by default -- pass --tag to append something
(no tag means no trailing hyphen either). Note that a single --tag applies
to every file renamed in that run, so if a release has more than one
feature-length cut (e.g. Theatrical + Director's Cut), renaming both in the
same run with no tag would give them the same filename. The tool detects
this and refuses to rename anything rather than clobber a file -- either
give --tag (e.g. run it twice, once per cut, with a different tag each
time), or rename those files by hand.
pip install -r requirements.txt # requests, beautifulsoup4, lxml, textual
# ffmpeg (for ffprobe) must also be installed and on PATHpython -m marquee "/path/to/Stargate.1994.REMASTERED.1080p.BluRay.x264-GROUP"
# Classic plain-text prompts instead of the TUI:
python -m marquee /path/to/folder --classic
# Dry run (preview only -- the Apply button/prompt is disabled entirely):
python -m marquee /path/to/folder --dry-run
# Override the guessed title:
python -m marquee /path/to/folder --title "Stargate"
# Adjust rate limiting (defaults: 4-7s randomized delay between every
# request to dvdcompare.net, sequential only, with retry backoff):
python -m marquee /path/to/folder --min-delay 6 --max-delay 10
# Append a tag to every renamed file, e.g. to distinguish a specific cut
# (pre-fills the TUI's tag field too):
python -m marquee /path/to/folder --tag "Theatrical"
# -> "Dune (2021)-Theatrical.mkv"- Arrow keys / mouse to navigate selection lists and the file table.
Enter/ click to select.aon a selected file row: manually assign a feature/extra label (opens a selection list of known labels plus a custom-text option).Escape: back to the previous screen.- Editing the "Tag" field live-updates every "New name" preview.
dvdcompare.net is a small, hobby-run site with no public API and no
indication it tolerates automated traffic. This tool:
- Never issues concurrent requests -- everything is sequential.
- Sleeps a randomized 4-7 second delay (configurable) before every request, including the very first one.
- Backs off further (with increasing delay) on any error or non-2xx response, up to a small retry limit, rather than hammering the site.
- Sends a plain, honest
User-Agentidentifying this as a personal-use tool.
If you're running this against a large batch of folders, consider adding your own pause between separate invocations too.
marquee/
http_client.py rate-limited requests.Session wrapper
title_guess.py folder name -> search title/year
search.py advanced-search request + results parsing
filmpage.py film.php comparison page parsing (releases + CUTS runtimes)
media.py ffprobe-based folder scanning
matcher.py duration matching (with PAL/NTSC adjustment)
rename.py filename building + applying renames
cli.py classic plain-text interactive flow (--classic)
tui.py Textual TUI (default interface)
tests/
fixtures/ sample HTML pages (provided) used for offline parser tests
test_parsing.py pytest suite for parsing/matching/renaming -- run with `pytest`
test_tui.py Pilot-based integration tests for the TUI
The parsers in filmpage.py and search.py were built against the sample
pages in tests/fixtures/. If the tool stops finding results or releases,
the site's markup may have changed since. The most useful things to
capture and share are:
# 1. A simple advanced-search result for a common title, so we can check
# the search page markup hasn't changed:
curl -s -A "Mozilla/5.0 (compatible; marquee/1.0)" \
-d "title_search=Stargate" -d "director_search=" -d "year_search=" \
-d "country_search=" -d "company_search=" -d "edition_search=" \
-d "and_or=and" \
https://www.dvdcompare.net/comparisons/adv_search_results.php \
-o adv_search_results_sample.html
# 2. A search with zero results, to check how "no matches" is rendered:
curl -s -A "Mozilla/5.0 (compatible; marquee/1.0)" \
-d "title_search=zzzznotarealfilmzzzz" -d "director_search=" -d "year_search=" \
-d "country_search=" -d "company_search=" -d "edition_search=" \
-d "and_or=and" \
https://www.dvdcompare.net/comparisons/adv_search_results.php \
-o adv_search_no_results.html
# 3. A film.php comparison page for a title that only has ONE release listed
# (to check the single-release layout, which sometimes differs slightly
# from the multi-release table layout):
curl -s -A "Mozilla/5.0 (compatible; marquee/1.0)" \
"https://www.dvdcompare.net/comparisons/film.php?fid=<some_fid>" \
-o film_single_release_sample.html
# 4. robots.txt, just so we can confirm nothing in it disallows these paths:
curl -s https://www.dvdcompare.net/robots.txt -o robots_sample.txtWait a several seconds between running these by hand too -- no need to fire them back-to-back. Send over the resulting files and the parsers can be adjusted.
This project is licensed under the GNU General Public License v3.0 (GPL-3.0-or-later).