Repository navigation
Releases: xwitty/CutlistDude
Releases · xwitty/CutlistDude
Release list
1.1.2
[1.1.2] - 2026-09-24 (build 96)
Fixed
- The missing-dependency error now prints a ready-to-paste
sudo apt install
command with the correct package names, instead of only the binary names
(which are not installable as-is:mkvmergeis inmkvtoolnix,ffprobein
ffmpeg). The ffmsindex package is namedffmsindexon current Ubuntu/Debian
(older releases shipped it inlibffms2-utils); both the error message and the
README now lead withffmsindex. - The working directory now honours
$TMPDIRinstead of being hard-coded to
/tmp. On systems where/tmpis a small RAM-backed tmpfs — notably WSL2,
where it defaults to roughly half of RAM — a full HD recording's intermediate
files (segment cuts, MPEG-TS parts, the joined video) could overflow/tmp
and fail with "No space left on device" even when the real disk had hundreds
of GB free. SetTMPDIRto a directory on a roomy filesystem to relocate all
scratch files:TMPDIR=~/cutlisttmp ./CutlistDude.sh ...
1.1.1
[1.1.1] - 2026-09-24 (build 94)
Fixed
OTR_DECODERset in the config file is now honoured. The config was read
only during the decryption step, which ran after the decoder was first
looked up — so a configured path was ignored and only a decoder onPATHor
beside the script was found. The config is now read at startup.- Decrypting a
.otr2file whose decrypted form has a different extension
(e.g.movie.HD.otr2→movie.HD.mp4) no longer fails with "file not found".
Instead of assuming the name by stripping.otr2, the script now discovers
the actual decrypted file (probing.mp4/.mkv/.avi).
1.1.0
[1.1.0] - 2026-09-05 (build 93)
Added
- Support for the modern OTR
.mp4formats — LQ (640×360, AAC only),
HQ (720×576 anamorphic, AAC+AC3) and HD (1280×720, AAC+AC3):
Lavf-muxed, closed-GOP x264 at 50 fps. - Embedded multi-track audio for the mp4 formats: all audio tracks are kept; the
AC3 track (untranscoded broadcast original) is default when present, else AAC. - Support for the new OTR decoder
otr_cli_decoder.py, which decrypts both the
legacy.otrkeyand the newer.otr2format. It is auto-detected on
PATHand next to the script, or configured viaOTR_DECODERin the config
file, and is preferred overotrtoolwhen present.--nicht-wartenis passed
to it so it does not wait/poll. .otr2recordings are now accepted as input. Because the new decoder unlocks
every encrypted file in the folder in one pass, the encrypted extension on the
command line is irrelevant — the suffix is stripped and cutting proceeds on the
decrypted file. The AC3 companion is unlocked in the same pass.
How the mp4 join works (and why it differs from .avi)
- In
.mp4, H.264 SPS/PPS live only in the container (avcC), never inline in the
bitstream. mkvmerge's--append(used for.avi) collapses all segments to a
single parameter-set header, so the stream-copied interior and the re-encoded
edges cannot coexist — the result freezes or shows artefacts. - For
.mp4the video segments are therefore joined differently: each segment is
remuxed to MPEG-TS with theh264_mp4toannexbbitstream filter (TS carries
SPS/PPS inline per segment), then joined with ffmpeg's concat demuxer, which
preserves every segment's parameter sets. The joined video is then muxed with
the audio by mkvmerge (a plain mux, no append). Verified frame-accurate with
clean seams on LQ/HQ/HD.
Changed
otrtoolis now a fallback used only whenotr_cli_decoder.pyis absent, and
only for.otrkey; a.otr2file with no new decoder gives an actionable error.- Numeric locale forced to
LC_NUMERIC=C(withoutLC_ALL=C) so cutlists with
fractional seconds parse correctly under locales that use a comma decimal
separator (de_DE, fr_FR, …), while leaving UTF-8 character handling — and
therefore non-ASCII filenames — untouched. A stray inheritedLC_ALLthat
would override this is neutralised, preserving the charset viaLANG.
Fixed
--concat(joining two already-cut videos) now uses the same MPEG-TS +
ffmpeg concat join as the internal segment join, instead of mkvmerge
--append. Appending two mp4-derived_cut.mkvfiles with differing H.264
parameter sets would drop the second file's SPS/PPS and freeze playback after
the first part; the TS/concat join preserves both.- Audio drift on
.mp4files whose container starts at a non-zero timestamp
(observed on LQ, ~21 ms). The snap-gap calculation now subtracts the
first-frame PTS before converting mkvmerge split timestamps to frame indices,
so a constant start offset no longer fakes a 1-2 frame "snap" that triggered
snap-correction and desynced audio. LQ now takes the same clean gap=0 path as
HD/HQ. - A trailing boundary encode that is legitimately skipped (computed duration
≤ 0 after snap-correction) no longer leavesfinal_muxlooking for a
non-existent segment file. - Re-downloading a cutlist with
-cnow overwrites the existing file instead of
writing aname.cutlist.1sibling (the download goes through a temp directory,
so the server-provided filename is always used verbatim). - Removed a duplicated
[INFO] Decrypted:line that appeared when decrypting with
otrtool: the per-file detail is now verbose-only, leaving the single
user-facing summary line emitted by the main flow.
1.0.0
Changelog
All notable changes to this project are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
Versions before 1.0.0 were internal development builds and were never published;
their build numbers are kept in the (build N) suffix for continuity.
[1.0.0] - 2026-07-31 (build 83)
First public release.
Added
- Frame-accurate smart-render cutting: lossless stream copy for the interior of
each sequence, re-encoded frames only at the cut boundaries. - Automatic format detection for OTR recordings: HQ, classic HD, New HD
(Main@L3.2) and Full HD (Lavf-muxed, 25 / 50 / 59.94 fps). - Automatic
.avi→.mkvpre-conversion with a dense cue index for the formats
that need it. .otrkeydecryption viaotrtool, for both the video and the AC3 companion.- Automatic detection of the AC3 companion file, including its encrypted
.ac3.otrkeyform. - Cutlist parsing that handles blocks carrying both time-based (
Start/Duration)
and frame-based (StartFrame/DurationFrames) keys. -c, --cutlist-id— download a cutlist from cutlist.at by id, with detection of
whether it targets the same format (HQ/HD) as the video.-t, --tmdb— prefix the output filename with a TMDB id.--concat— losslessly join two already-cut files after a compatibility check.--force-encode— re-encode in full for sources that cannot be stream-copied.-n, --dry-run— build and validate the render plan without touching media.- Four output verbosity levels:
-q, default,-v,-vv. -V, --versionand-h, --help, -?.- Post-segment frame-count verification (
[CHECK]lines) comparing planned against
actual frame counts. - Documented exit codes: 0 success, 1 usage/input error, 2 external tool failure.
x264is a hard requirement. An earlierffmpeg -c:v libx264fallback was removed
before release: it could not pass the SPS-matching options (--stitchable,
--sps-id,--ref) that keep the encoded boundary frames compatible with the
stream-copied interior, and it seeked by timecode rather than by frame, risking both
seam corruption and frame-count drift. It was never exercised end to end.ffmpeg
itself is still required for the trailing encodes and forffprobe.
Security
- The credentials file is now
~/.config/CutlistDude.confonly; older filenames are
no longer read. - The script refuses to start if that file is group- or world-readable.
- Credentials are masked in all logged commands at every verbosity level.
Development history (pre-release highlights)
These were the substantive problems solved while getting to 1.0.0:
- Cutlist parser rewritten to be driven by the
[CutN]section header. Earlier
versions keyed offDuration=, which appears beforeDurationFrames=in each
block and caused sequences to be emitted twice, or with values carried over from
the previous block. - Frame numbering pinned down empirically: cutlist frame N is file frame
N-1;ffmsindex/x264/ffprobeare 0-based whilemkvmerge --split parts-framesis 1-based. Verified by extracting boundary frames as PNGs. - Duplicate frames at cut boundaries fixed — a 0-based IDR number was being
passed into the 1-basedparts-framesargument. - Off-by-one output length fixed: when a copy snaps to a later IDR it can end one
frame later than planned, so the trailing encode is now derived from the copy's
measured frame count rather than from the plan. Output length now matches the
cutlist exactly. - Multi-cut file corruption fixed: per-segment copy re-runs were all being
renamed to the first segment's filename. - IDR probing removed. Probing with a degenerate
parts-frames:N-(N+1)range
made mkvmerge forward-snap to the next keyframe instead of confirming N, so the
probe advanced one GOP per iteration and never converged on ordinary Lavf HD files.
The initial copy is its own proof: if mkvmerge produced a valid copy starting at
frame N, then N is a usable IDR. - Open-GOP trailing encodes fixed with
-flags +cgop.