Automatically add chapter markers to video files using tracklists from 1001Tracklists.com.
Navigate DJ sets, live recordings, and music mixes track by track.
- 🔍 Smart Search - Search 1001Tracklists.com directly from the command line
- 📁 Filename Detection - Automatically derives search query from video filename
- 🎯 Intelligent Relevance Scoring - Results ranked by duration match, keywords, abbreviations, event patterns, year, and recency
- 🔤 Abbreviation Matching - Recognizes event abbreviations (e.g.,
AMFmatches "Amsterdam Music Festival") - 📅 Event Pattern Detection - Understands multi-day event notation (
WE1,WE2,Day1,D2, etc.) - 🌍 Accent-Insensitive Matching -
ChateaumatchesChâteau,IbanezmatchesIbañez - 🎬 YouTube ID Stripping - Automatically removes yt-dlp video IDs from filenames (e.g.,
[dQw4w9WgXcQ]) - ⚡ Fast In-Place Editing - Uses
mkvpropeditfor near-instant chapter embedding (no remuxing) - 🍪 Session Caching - Login cookies cached for ~100 days for faster consecutive runs
- 🔄 Duplicate Detection - Skips files that already have identical chapters
- 🔗 URL Storage - Stores tracklist URL in file for instant reuse on subsequent runs
- 🕐 Future Timestamp Pickup - Tags files with tracklist URL even when timestamps aren't available yet
- 📦 Pipeline Support - Batch process multiple files via PowerShell pipeline
- ⏭️ Auto-Select Mode - Fully automated chapter embedding for batch processing
- 🛡️ Rate Limit Protection - Configurable delay between requests, automatic retry with backoff on rate limits
- ✅ WhatIf/Confirm Support - Standard PowerShell
-WhatIfand-Confirmsupport for safe operation
- PowerShell 5.1+ (Windows) or PowerShell Core 7+ (cross-platform)
- MKVToolNix installed (provides
mkvmerge,mkvextract, andmkvpropedit) - 1001Tracklists.com account (free, required for search functionality)
- Download
Add-TracklistChapters.ps1 - Create configuration files:
.\Add-TracklistChapters.ps1 -CreateConfig
- Edit
config.jsonin the script directory:{ "Email": "your-email@example.com", "Password": "your-password", "ChapterLanguage": "eng", "MkvMergePath": "", "ReplaceOriginal": false, "NoDurationFilter": false, "AutoSelect": false, "DelaySeconds": 5 } - Optionally edit
aliases.jsonto add custom event abbreviations (see Event Aliases).
Simply provide a video file - the script will search using the filename:
.\Add-TracklistChapters.ps1 -InputFile "2025 - AMF - Sub Zero Project.webm"This searches for "2025 AMF Sub Zero Project" and presents matching tracklists for selection.
Point directly at a folder to process all MKV/WEBM files in it:
# Top-level files only
.\Add-TracklistChapters.ps1 -InputFile "D:\DJ Sets" -AutoSelect -ReplaceOriginal
# Include subfolders
.\Add-TracklistChapters.ps1 -InputFile "D:\DJ Sets" -Recurse -AutoSelect -ReplaceOriginal
# Mix folders and files
.\Add-TracklistChapters.ps1 "D:\Ultra", "D:\EDC", "special-set.mkv" -AutoSelectUse -AutoSelect to automatically pick the best match:
.\Add-TracklistChapters.ps1 -InputFile "video.mkv" -AutoSelect.\Add-TracklistChapters.ps1 -InputFile "video.mkv" -Tracklist "Hardwell Ultra Miami 2024"# Using URL
.\Add-TracklistChapters.ps1 -InputFile "video.mkv" -Tracklist "https://www.1001tracklists.com/tracklist/1g6g22ut/..."
# Using tracklist ID
.\Add-TracklistChapters.ps1 -InputFile "video.mkv" -Tracklist "1g6g22ut".\Add-TracklistChapters.ps1 -InputFile "video.mkv" -TrackListFile "chapters.txt"Tracklist file format:
[00:00] Artist - Track Title
[03:45] Another Artist - Another Track
[1:07:30] Third Artist - Third Track
Copy a tracklist from your browser, then:
.\Add-TracklistChapters.ps1 -InputFile "video.mkv" -FromClipboardSee what chapters would be added without modifying the file:
.\Add-TracklistChapters.ps1 -InputFile "video.mkv" -Preview.\Add-TracklistChapters.ps1 -InputFile "video.mkv" -ReplaceOriginalThe script supports pipeline input for processing multiple files:
# Process all MKV files with auto-select
Get-ChildItem "D:\DJ Sets\*.mkv" | .\Add-TracklistChapters.ps1 -AutoSelect -ReplaceOriginal
# Process all WEBM files recursively
Get-ChildItem "D:\Videos\*.webm" -Recurse | .\Add-TracklistChapters.ps1 -AutoSelect -ReplaceOriginal
# Preview chapters for all files without modifying
Get-ChildItem "*.webm" | .\Add-TracklistChapters.ps1 -PreviewA delay is automatically added between files to avoid rate limiting (default: 5 seconds). You can adjust this:
# Faster processing (may trigger rate limits)
Get-ChildItem "*.mkv" | .\Add-TracklistChapters.ps1 -AutoSelect -DelaySeconds 2
# More conservative delay
Get-ChildItem "*.mkv" | .\Add-TracklistChapters.ps1 -AutoSelect -DelaySeconds 10A summary is displayed after batch processing:
--------------------------------------------------
Summary: 12 files processed
7 chapters added
2 already up-to-date
2 tagged (awaiting timestamps)
1 skipped
The script uses intelligent relevance scoring to find the best matching tracklist. Use -Verbose to see the scoring breakdown for each result.
The scoring uses a multiplicative approach: content relevance (keywords, abbreviations, etc.) is the primary signal, and duration acts as a multiplier that amplifies good matches. This prevents duration-only matches from outranking content-relevant results (e.g., a random set with matching duration beating the correct artist/event).
Content score (multiplied by duration):
| Factor | Points | Description |
|---|---|---|
| Keywords | 0 to 120 | Proportional to matched keywords (max 100), +20 bonus if all match |
| Abbreviations | +35 each | AMF → "Amsterdam Music Festival", EDC → "Electric Daisy Carnival" |
| Aliases | +35 each | Matches from aliases.json (case-insensitive), e.g., tml → "Tomorrowland" |
| Event Patterns | -30 to +40 | Correct pattern = +40, wrong pattern = -30 |
Duration multiplier (applied to content score):
| Difference | Multiplier | Meaning |
|---|---|---|
| ±1 min | 2.0x | Exact match — almost certainly the same recording |
| ±5 min | 1.8x | Close match — likely same recording |
| ±15 min | 1.4x | Moderate — possibly edited or partial |
| ±30 min | 1.1x | Significant — unlikely same recording |
| >30 min | 0.8x | Very different — reduces score |
Additive bonuses (not multiplied):
| Factor | Points | Description |
|---|---|---|
| Year | +25 | Matches year in query to tracklist date |
| Recency | 0 to 10 | Minor tiebreaker favoring newer tracklists |
Results with 0 keyword matches are always filtered out (these are pure noise from duration/year matching).
Additionally, when an event is specified (via alias or abbreviation), results with only 1 keyword match and no event match are filtered out. This removes false positives like "House Party 133" matching "Swedish House Mafia".
The script automatically handles common filename patterns:
- YouTube IDs:
Video Title [dQw4w9WgXcQ]→ stripped automatically - Accented characters:
TiëstoandTiestoboth match,ChâteaumatchesChateau - Event patterns:
WE2,W2,Weekend2all recognized as "Weekend 2" and count as matched keywords - Abbreviations: Uppercase words like
AMF,EDC,ASOTmatched against full event names - Aliases: Any word matching a key in aliases.json (case-insensitive) boosts results containing the target event name
Event pattern matching (WE1 → Weekend 1):
Query: "2025 - TML Belgium - Hardwell WE1"
QueryParts: Year=2025, Keywords=[tml, belgium, hardwell, we1], Aliases=[TML->Tomorrowland], EventPatterns=[Weekend1]
Score 355.1 for 'Hardwell @ Mainstage, Tomorrowland Weekend 1, Belgium...'
[Dur:x2.0(1m diff) | Alias:35(TML->Tomorrowland) | Kw:120(4/4) | Pat:40 | Year:25 | Rec:5.1]
Score 185.9 for 'Hardwell @ Mainstage, Tomorrowland Weekend 2, Belgium...'
[Dur:x2.0(1m diff) | Alias:35(TML->Tomorrowland) | Kw:75(3/4) | Pat:-30 | Year:25 | Rec:5.9] ← Wrong weekend, penalized
Abbreviation matching (AMF, EDC):
Query: "2025 AMF KI/KI B2B Armin van Buuren"
QueryParts: Year=2025, Keywords=[amf, ki/ki, b2b, armin, van, buuren], Abbreviations=[AMF]
Score 226.2 for 'Armin van Buuren & KI/KI @ Two Is One, Amsterdam Music Festival...'
[Dur:x1.8(4m diff) | Abbr:35(AMF=AMF) | Kw:66.7(4/6) | Year:25 | Rec:4.2] ← AMF matched
Score 179.8 for 'Armin van Buuren - Piano...'
[Dur:x1.8(5m diff) | Abbr:0 | Kw:50(3/6) | Year:25 | Rec:6.8] ← No abbreviation match
YouTube ID stripping:
Query: "Marlon Hoffstadt Live at EDC Las Vegas 2025 [JX2STP6HL5k]"
→ YouTube ID stripped, EDC detected as abbreviation
Score 171.4 for 'Marlon Hoffstadt @ kineticFIELD, EDC Las Vegas...'
[Dur:x2.0(0m diff) | Abbr:35(EDC(direct)) | Kw:63.6(7/11) | Rec:5]
Accent-insensitive matching:
Query: "Tiësto - Dreamstate 2025 (Full Set)"
→ Tiësto normalized for matching
Score 134.9 for 'Tiësto @ The Dream Stage, Dreamstate SoCal...'
[Dur:x2.0(0m diff) | Kw:50(2/4) | Year:25 | Rec:9.9]
Alias matching (lowercase/unofficial abbreviations):
Query: "armin van buuren - asot 2025 - utrecht"
→ asot matched via aliases.json to "A State of Trance"
Score 199.5 for 'Armin van Buuren @ A State of Trance 1000, Utrecht...'
[Dur:x2.0(0m diff) | Alias:35(asot->A State of Trance) | Kw:66.7(4/6) | Year:25 | Rec:4.5]
| Score Range | Meaning |
|---|---|
| 250+ | Excellent match - likely the exact recording |
| 150-250 | Good match - probably correct |
| 80-150 | Partial match - review manually |
| <80 | Poor match - likely wrong tracklist |
Artist with abbreviation matching (AMF → Amsterdam Music Festival):
Search Results (video: 47m):
--------------------------------------------------------------------------------------------------------------
1. ✓ Armin van Buuren & KI/KI @ Two Is One, Amsterdam Music Festival [📅 2025-10-25 | ⏱️ 51m (+4m)]
2. ≈ Armin van Buuren - Piano [📅 2025-11-10 | ⏱️ 52m (+5m)]
3. ≈ Armin van Buuren @ SLAM! (Amsterdam Dance Event, Netherlands) [📅 2025-10-22 | ⏱️ 51m (+4m)]
4. ~ Armin van Buuren @ Mainstage, Tomorrowland Brasil [📅 2025-10-10 | ⏱️ 58m (+11m)]
5. ~ Armin van Buuren @ Amsterdam Music Festival, Netherlands [📅 2025-10-25 | ⏱️ 1h 24m (+37m)]
--------------------------------------------------------------------------------------------------------------
B2B set with many keywords (Martin Garrix B2B Alesso @ Red Rocks):
Search Results (video: 60m):
--------------------------------------------------------------------------------------------------------------
1. ✓ Martin Garrix & Alesso @ Red Rocks Amphitheatre, United States [📅 2025-10-24 | ⏱️ 1h (±0m)]
2. ≈ Martin Garrix @ Red Rocks Amphitheatre, United States [📅 2025-10-23 | ⏱️ 1h 59m (+59m)]
3. ≈ Alesso @ Red Rocks Amphitheatre, United States [📅 2025-10-24 | ⏱️ 1h 2m (+2m)]
--------------------------------------------------------------------------------------------------------------
YouTube filename with accent (Tiësto - Live at We Belong Here Miami 2026):
Search Results (video: 126m):
--------------------------------------------------------------------------------------------------------------
1. ~ Tiësto @ We Belong Here, Historic Virginia Key Park [📅 2026-03-01 | ⏱️ 3h (+54m)]
2. ~ MOGUAI & Tiësto & MARTEN HØRGER - 1LIVE DJ Session [📅 2026-01-31 | ⏱️ 2h 58m (+52m)]
3. ~ Tiësto @ Dome SVP Stadium, India [📅 2026-01-23 | ⏱️ 2h 19m (+13m)]
--------------------------------------------------------------------------------------------------------------
Festival set with event alias (Oliver Heldens at Mysteryland):
Search Results (video: 89m):
--------------------------------------------------------------------------------------------------------------
1. ✓ Oliver Heldens @ Mainstage, Mysteryland, Netherlands [📅 2025-08-23 | ⏱️ 1h 29m (±0m)]
2. ≈ Oliver Heldens @ Mainstage, Tomorrowland Weekend 1, Belgium [📅 2025-07-18 | ⏱️ 1h (-29m)]
3. ~ Oliver Heldens @ Orangerie, Tomorrowland Weekend 2, Belgium [📅 2025-07-26 | ⏱️ 1h 58m (+29m)]
--------------------------------------------------------------------------------------------------------------
EDC set with long filename (Tiësto - In Search Of Sunrise live set at EDC Las Vegas):
Search Results (video: 77m):
--------------------------------------------------------------------------------------------------------------
1. ✓ Tiësto @ In Search Of Sunrise, kineticFIELD, EDC Las Vegas [📅 2025-05-18 | ⏱️ 1h 17m (±0m)]
2. ≈ Tiësto @ kineticFIELD, EDC Las Vegas, United States [📅 2025-05-17 | ⏱️ 1h 13m (-4m)]
3. ~ GORDO @ bassPOD, EDC Las Vegas, United States [📅 2025-05-16 | ⏱️ 1h 7m (-10m)]
--------------------------------------------------------------------------------------------------------------
Result quality indicators (based on overall relevance score):
- ✓ (green) - Excellent match (score 250+)
- ≈ (yellow) - Good match (score 150-250)
- ~ (dim) - Partial match (score 80-150)
- ✗ (red) - Poor match (score <80)
Duration difference is shown as (±0m), (+Xm), or (-Xm) relative to the video file.
| Parameter | Description |
|---|---|
-InputFile |
One or more MKV/WEBM files or folders to process. Accepts pipeline input. |
-Tracklist |
Search query, URL, or tracklist ID |
-TrackListFile |
Local text file with timestamps |
-FromClipboard |
Read tracklist from clipboard |
-AutoSelect |
Automatically select the top result |
-DelaySeconds |
Delay between files in pipeline mode (default: 5, range: 0-60) |
-NoDurationFilter |
Disable duration-based result filtering |
-Preview |
Show chapters without modifying file (alias for -WhatIf) |
-WhatIf |
Show what would happen without making changes |
-Confirm |
Prompt for confirmation before modifying each file |
-IgnoreStoredUrl |
Force fresh search, ignoring any stored tracklist URL |
-Recurse |
When InputFile is a folder, include subfolders |
-ReplaceOriginal |
Replace original file instead of creating new |
-OutputFile |
Custom output filename |
-ChapterLanguage |
Chapter language code (default: eng) |
-MkvMergePath |
Custom path to MKVToolNix directory |
-Email |
1001Tracklists.com email (overrides config) |
-Password |
1001Tracklists.com password (overrides config) |
-Credential |
PSCredential object (alternative to Email/Password) |
-CreateConfig |
Generate or update config.json and aliases.json files |
-Verbose |
Show detailed scoring breakdown and debug info |
The config.json file supports the following options:
{
"Email": "",
"Password": "",
"ChapterLanguage": "eng",
"MkvMergePath": "",
"ReplaceOriginal": false,
"NoDurationFilter": false,
"AutoSelect": false,
"DelaySeconds": 5
}Command-line parameters always override config file values.
Running -CreateConfig is non-destructive - it merges new default settings with your existing configuration:
.\Add-TracklistChapters.ps1 -CreateConfigOutput:
config.json: Updated (added: AutoSelect, DelaySeconds)
aliases.json: Unchanged (already up to date)
Your existing credentials and settings are preserved while new options are added.
The aliases.json file maps event abbreviations to their full names for improved search matching. This helps when:
- Using lowercase abbreviations in filenames (e.g.,
asotinstead ofASOT) - Using unofficial abbreviations that can't be dynamically detected (e.g.,
TMLfor Tomorrowland)
{
"AMF": "Amsterdam Music Festival",
"ADE": "Amsterdam Dance Event",
"EDC": "Electric Daisy Carnival",
"UMF": "Ultra Music Festival",
"ASOT": "A State of Trance",
"ABGT": "Above & Beyond Group Therapy",
"WAO138": "Who's Afraid of 138",
"FSOE": "Future Sound of Egypt",
"GDJB": "Global DJ Broadcast",
"SW4": "South West Four",
"TML": "Tomorrowland",
"TL": "Tomorrowland",
"DWP": "Djakarta Warehouse Project",
"MMW": "Miami Music Week"
}Alias matching is case-insensitive. When a filename contains an alias key (e.g., asot), results containing the target name (e.g., "A State of Trance") receive a +35 score boost.
Add your own abbreviations for regional events or personal naming conventions.
The script uses mkvpropedit to modify chapters and tags directly in the file without remuxing. This makes chapter embedding nearly instantaneous regardless of file size:
| File Size | Time |
|---|---|
| 1 GB | < 1 second |
| 10 GB | < 1 second |
| 50 GB | < 1 second |
When not using -ReplaceOriginal, the file is first copied to the output location, then modified in place.
Login cookies are cached in .1001tl-cookies.json in the script directory. This speeds up consecutive runs by avoiding repeated logins. Cache is valid until cookies expire (~100 days).
1001Tracklists.com has rate limits to prevent abuse. The script includes several protections:
- Automatic delay: A configurable delay (default: 5 seconds) is added between files in pipeline mode
- Detection: Both HTTP 429 status codes and rate limit page content are detected
- Auto-retry: When rate limited, the script waits 30 seconds and retries once before giving up
- Session preservation: Rate limits don't invalidate your session — cookies are preserved for the retry
If the auto-retry fails:
- Visit 1001Tracklists.com in your browser
- Solve the captcha
- Re-run the script (your existing session will still work)
Before modifying, the script extracts existing chapters using mkvextract and compares them with the new chapters. If they're identical and the tracklist URL is already stored, the file is skipped:
Chapters already exist and are identical - skipping.
If chapters are identical but no URL is stored yet (e.g., files processed before this feature), the file will be updated to add the URL:
Chapters identical, but adding tracklist URL to file...
When chapters are added from 1001Tracklists.com, the tracklist URL and title are stored as MKV global tags in the output file. URLs are stored in short format (e.g., https://www.1001tracklists.com/tracklist/2ft171s9/).
On subsequent runs:
-
Interactive mode: Prompts with the stored tracklist info:
Found stored tracklist: Martin Garrix @ Mainstage, Tomorrowland Weekend 2, Belgium 2025 https://www.1001tracklists.com/tracklist/2ft171s9/ Y = Use this tracklist | S = Skip file | R = Retry search Use this tracklist? (Y/s/r)Press Enter or
Yto reuse,Sto skip the file, orRto start a new search. -
AutoSelect mode: Uses the stored URL directly without searching, significantly speeding up batch re-processing.
Use -IgnoreStoredUrl to force a fresh search even when a stored URL exists.
Some tracklists on 1001Tracklists.com don't have timestamps yet - timestamps are added by the community over time. When you select a tracklist without timestamps, the script stores the tracklist URL in the file so it can automatically pick up the timestamps on a future run.
Interactive mode prompts for action:
This tracklist has no timestamps yet. Timestamps are added by users on 1001Tracklists.com.
T = Tag only (check again later) | R = Retry search | S = Skip
Action? (T/r/s)
Press Enter or T to tag the file for future pickup, R to search for a different tracklist, or S to skip.
AutoSelect mode automatically tags the file:
No timestamps yet - tagging for future pickup.
Tagging file...
Tagged for future timestamp pickup: video.mkv
On subsequent runs, if the tracklist now has timestamps, chapters are added automatically. If timestamps are still unavailable:
Already tagged, awaiting community timestamps.
The file is skipped since it's already tagged with the same URL.
This workflow allows you to batch-process files immediately when tracklists are published, then re-run later to pick up timestamps as the community adds them.
When using filename-based search, the script:
- Removes the file extension
- Removes YouTube video IDs (11-character codes in brackets at the end)
- Replaces
-,_,.with spaces - Normalizes multiple spaces
"No tracklists found"
- Try a different search query
- Use
-NoDurationFilterto see all results regardless of duration - Check if the tracklist exists on 1001Tracklists.com
"Rate limited by 1001Tracklists"
- The script automatically retries once after a 30-second wait
- If the retry also fails, visit 1001Tracklists.com in your browser and solve the captcha
- Re-run the script (your session cookies are preserved)
- Consider increasing
-DelaySecondsfor batch processing
"This tracklist has no timestamps yet"
- The tracklist exists but timestamps haven't been added by users yet
- Choose
Tto tag the file now and re-run later when timestamps are available - Or choose
Rto search for a different tracklist that has timestamps - In
-AutoSelectmode, files are automatically tagged for future pickup
"Already tagged, awaiting community timestamps"
- The file was previously tagged with a tracklist URL that still has no timestamps
- Re-run the script later when the community has added timestamps
- Use
-IgnoreStoredUrlto search for a different tracklist
"Chapters already exist and are identical - skipping"
- The file already has the same chapters - no action needed
- Use a different tracklist if you want different chapters
mkvmerge/mkvpropedit not found
- Install MKVToolNix
- Or specify the path:
-MkvMergePath "C:\Program Files\MKVToolNix\mkvmerge.exe"
Wrong tracklist selected in AutoSelect mode
- Use
-Verboseto see scoring breakdown - Try adding more specific keywords to the filename or
-Tracklistparameter - Include the year, event abbreviation, or weekend/day number for better matching
Cookie/session errors
- Delete
.1001tl-cookies.jsonin the script directory to force a fresh login
See CHANGELOG.md for a detailed history of changes.
