Download your favorite segments from any YouTube playlist using chapter markers, at 720p or lower, and concatenate them into one MP4.
- Python 3.10+
- FFmpeg (required for
yt-dlp --download-sectionsand for joining clips) - Install deps:
pip install -e .(from this directory). This pullsyt-dlp[default](includesyt-dlp-ejs) for YouTube’s JS / n-challenge handling; reinstall after upgrading crackascript so yt-dlp stays current. - Node or Deno on your PATH is strongly recommended for yt-dlp’s EJS solver (see yt-dlp EJS wiki).
Segments now use a compatibility-first selector at <=720p:
- prefer H.264 video (
avc1) + AAC audio (mp4a), - then fall back to generic MP4 video/audio,
- then fall back to best available pair at or below 720p.
This makes individual segment files much more likely to play cleanly in Windows players during a run.
The final file tries stream copy first; if codecs or layout differ, it re-encodes to 720p H.264 + AAC.
For packaged Windows releases, download the latest installer from GitHub Releases:
crackascript-<version>-windows-installer.exe
The installer includes the app runtime and creates Start Menu/Desktop shortcuts.
Install the package, then start the app (no arguments opens the GUI):
pip install -e .
python -m crackascriptOr explicitly:
python -m crackascript guiIn the window: paste the playlist URL, choose the final megacut path and clips folder (<clips folder>/segments/). Under Segment Picker, click Discover segments to scan chapter titles, then pick a recurring segment; you will see clip count and estimated megacut length, and a JSON choice is saved under <clips folder>/.segment_choice.json. Then click Download. (Check Classic mode to skip the picker and use Chapter title regex under Options instead—the old one-clip-per-video segments/<video_id>.mp4 layout.)
Under Options, pick YouTube cookies if you need a logged-in session (see Age-restricted videos), set yt-dlp JS runtime (e.g. node) and remote components (default ejs:github) if needed. Use Clip order (megacut) for chronological vs playlist order (see Megacut clip order).
Compile Megacut appears only after downloads finish and verify. For numbered jobs, concat order follows integer filenames 1.mp4, 2.mp4, … in <clips folder>/segments/ (so you can rename clips to reorder the megacut); generic chapter titles like “Intro” may appear as false-positive clusters—treat picker results as a hint, not ground truth.
If the verified megacut is longer than 12 hours (YouTube’s upload limit), the GUI first measures segment lengths, then walks you through a short dialog: you can split into equal-ish parts (full clips only, balanced under 12h per file), pack greedily into as many ~12h parts as possible plus a shorter last file, or compile one long file anyway. Split outputs are named like YourTitle_part01.mp4, YourTitle_part02.mp4, … next to your chosen output path. If any single clip is over 12 hours, splitting on clip boundaries is impossible—the app will explain that case.
The GUI also shows the currently processed episode thumbnail/title, live progress, ETA, download speed (to spot throttling), and the final concat step. You can hide the log panel with the Hide Log button.
The GUI includes an Updates section that can:
- check GitHub releases for your app repo,
- check latest yt-dlp and FFmpeg releases,
- auto-check on startup (configurable),
- run a one-click
yt-dlpupgrade in the current Python environment.
This is intended as the "pre-installer" update layer: release detection + notifications + tool update command. Installer-level in-place self-replacement is still handled later when you package/distribute.
To build release artifacts on Windows:
powershell -ExecutionPolicy Bypass -File scripts/build_installer.ps1Outputs are written to release/:
crackascript-1.0.2-windows-installer.execrackascript-1.0.2-windows-portable.zip
- Copy your playlist URL from YouTube (channel “Uploads” playlist, or a dedicated podcast playlist).
- Run:
python -m crackascript build --source "https://www.youtube.com/playlist?list=..." -o cracker_montage.mp4Inspect recurring chapter clusters (metadata only, JSON to stdout):
python -m crackascript discover-segments --source "https://www.youtube.com/playlist?list=..."| Flag | Meaning |
|---|---|
--source |
Required. Playlist or compatible channel listing URL. |
-o / --out |
Output file (default: cracker_montage.mp4). |
--work-dir |
Cache directory for per-episode segments (default: .crackascript_work). |
--chapter-regex |
Regex against chapter titles (default matches “cracker of the week”, case-insensitive). Ignored when --segment-choice-file is used. |
--segment-choice-file |
JSON file (cluster + clips[]) from the GUI segment picker; writes numbered clips 1.mp4, 2.mp4, … and sets a distinct job id. Also accepted on build. |
--redownload-clip-index |
Re-download one numbered clip N.mp4 (cluster jobs only); conflicts with --redownload-video-id. |
--skip-existing |
Skip re-downloading if the segment file for that job already exists. |
--cookies |
Path to a Netscape-format cookies file for yt-dlp. If set together with --cookies-from-browser, the file wins. |
--cookies-from-browser |
Browser name for yt-dlp to load cookies from (e.g. chrome, edge, firefox). Use a profile where you are logged into YouTube. |
--ffmpeg-location |
Path to folder containing ffmpeg/ffprobe (or a direct path to ffmpeg). Use this if FFmpeg is not on PATH. |
--js-runtimes |
Pass-through to yt-dlp --js-runtimes (e.g. node, deno). Can improve YouTube extraction reliability. |
--remote-components |
yt-dlp remote component specs (space/comma-separated). Default: ejs:github (fetches EJS challenge scripts when needed). Pass an empty value to disable (e.g. --remote-components "" where your shell allows it). |
--segment-order |
How matched clips are ordered for download and the final megacut: upload_date_asc (default) = oldest YouTube upload first; playlist = strict playlist position (first video in the list first). |
--scan-sleep-seconds |
Delay between metadata submissions during scan (default: 0.05). |
--scan-sleep-jitter-seconds |
Random extra delay added per scan submission (default: 0.05). |
--scan-workers |
Number of concurrent metadata scan workers (default: auto-selected). |
--scan-adaptive-backoff |
Increase scan pacing delay automatically when rate limiting is detected (default: enabled). |
--download-workers |
Number of concurrent clip download+validation workers (default: auto-selected). |
--download-retries |
yt-dlp retry count for HTTP/media transfer failures during download (default: 10). |
--fragment-retries |
yt-dlp retry count for segmented media fragments (default: 10). |
--extractor-retries |
yt-dlp retry count for extractor-stage failures (default: 3). |
--retry-sleep-seconds |
Base sleep between retries (default: 1.0). |
--retry-sleep-max-seconds |
Max sleep for fragment retry backoff (default: 10.0). |
--duration-tolerance-ratio |
Allowed relative duration drift for validated clips (default: 0.20 = +/-20%). |
--decode-probe-seconds |
Optional ffmpeg decode probe window for each downloaded clip (default: 0 = disabled). |
-v |
Verbose / debug logs. |
These flags apply only to python -m crackascript concat … (used internally for multi-part compiles):
| Flag | Meaning |
|---|---|
--concat-paths-file |
UTF-8 file: one segment path per line (absolute or relative to --work-dir). Each path must lie under <work-dir>/segments/ and match a segment in job state; concat uses that order/subset instead of the default ordering. |
--concat-expected-duration-seconds |
Override expected output duration for final validation (per-part total when splitting). |
--concat-success-phase |
done (default) or concat_ready. After a successful concat, set job phase accordingly—concat_ready is used between multi-part runs until the last part finishes. |
Many playlists (including channel Uploads) appear newest-first on YouTube. The default upload_date_asc sorts by real upload / publish time so the megacut runs oldest episode → newest, independent of that list order. Use playlist only when you want the megacut to follow the playlist’s on-screen order (e.g. a manually curated sequence).
Changing --segment-order changes the internal job id (with the same source, output path, and chapter regex), so existing work-dir state from a different order is not reused—run a fresh scan when you switch.
YouTube often throttles media URLs unless yt-dlp solves the n parameter via EJS. If downloads are extremely slow or you see n challenge solving failed in the log:
- Keep yt-dlp updated (
pip install -U "yt-dlp[default]"or reinstall crackascript). - Install Node or Deno and pass
--js-runtimes node(ordeno). - Leave
--remote-componentsat the defaultejs:githubso yt-dlp can obtain solver scripts when they are not bundled locally (see the EJS wiki).
The GUI shows live download speed during each clip; sustained very low speeds usually mean throttling or extraction issues.
For best overall speed, use a local non-synced --work-dir while downloading and validating clips, then copy the finished output to Dropbox/OneDrive afterward. Sync clients can add lock contention and extra write latency during frequent checkpoint updates.
Each downloaded clip is now validated before being marked complete:
- Must contain both video and audio streams.
- Must have a readable duration.
- Duration must be within tolerance of the requested chapter range (
--duration-tolerance-ratio). - Optional decode sanity pass can be enabled with
--decode-probe-seconds.
If a clip fails download or validation, crackascript retries and emits structured events such as:
CRACKASCRIPT_EVENT EPISODE_RETRY ... reason=<classification>CRACKASCRIPT_EVENT EPISODE_FAILED ... reason=<classification>
CRACKASCRIPT_EVENT EPISODE_DONE is emitted only after strict validation passes.
After concat, the final output is also validated before CRACKASCRIPT_EVENT CONCAT_DONE is emitted.
YouTube may block metadata and downloads for age-restricted clips unless yt-dlp sends your logged-in session. Log into YouTube in a desktop browser, then either:
- Pass
--cookies-from-browser edge(orchrome,firefox, etc.), or - Export a Netscape cookies file and pass
--cookies path/to/cookies.txt.
On Windows, the browser’s cookie database can be locked while the browser is open; if cookie loading fails, close that browser and try again, or use --cookies with an exported file.
- Chrome (Windows): if you see “Could not copy Chrome cookie database”, fully quit Chrome and retry, or use an exported cookies file. See
https://github.com/yt-dlp/yt-dlp/issues/7271.
Treat cookie files like passwords and do not share them.
- Classic (regex) jobs:
<work-dir>/segments/<video_id>.mp4 - Segment-picker (numbered) jobs:
<work-dir>/segments/<n>.mp4forn = 1 … N; concat uses ascending numeric order of existing files among the job’s clip indices (manual renames change megacut order). - Chapter end time: next chapter’s start, or video duration, or chapter
end_timeif present.
ffmpeg/ffprobe must be installed and available. You can either:
- Add
<ffmpeg>\binto yourPATH, or - Pass
--ffmpeg-location "C:\path\to\ffmpeg\bin"(or select it in the GUI's FFmpeg location field).
