Skip to content

1.1.0

Choose a tag to compare

@xwitty xwitty released this 05 Sep 21:06
· 2 commits to main since this release

[1.1.0] - 2026-09-05 (build 93)

Added

  • Support for the modern OTR .mp4 formats — 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 .otrkey and the newer .otr2 format. It is auto-detected on
    PATH and next to the script, or configured via OTR_DECODER in the config
    file, and is preferred over otrtool when present. --nicht-warten is passed
    to it so it does not wait/poll.
  • .otr2 recordings 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 .mp4 the video segments are therefore joined differently: each segment is
    remuxed to MPEG-TS with the h264_mp4toannexb bitstream 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

  • otrtool is now a fallback used only when otr_cli_decoder.py is absent, and
    only for .otrkey; a .otr2 file with no new decoder gives an actionable error.
  • Numeric locale forced to LC_NUMERIC=C (without LC_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 inherited LC_ALL that
    would override this is neutralised, preserving the charset via LANG.

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.mkv files 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 .mp4 files 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 leaves final_mux looking for a
    non-existent segment file.
  • Re-downloading a cutlist with -c now overwrites the existing file instead of
    writing a name.cutlist.1 sibling (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.