Automated AV1/Opus encoding toolchain for MKV files featuring VFR handling, loudnorm audio downmixing, and av1an integration.
Find a file
pat-e a592b9f466 feat: pin xav on Windows with a one-group affinity mask
Windows 11 and Server 2022 start xav suspended, set the process
affinity mask, then resume so SVT workers inherit it. taskset stays
Linux-only. The mask covers at most 64 logical CPUs; any beyond
that stay free, and -w follows the masked CPUs.
2026-09-29 23:20:37 +02:00
cropdetect docs: drop PATH symlink notes from cropdetect readme 2026-09-18 21:06:37 +02:00
docs feat: pin xav on Windows with a one-group affinity mask 2026-09-29 23:20:37 +02:00
.gitignore chore: remove unused directory from git tracking 2026-09-03 13:15:17 +02:00
aom_opus_encoder.py feat: share subtitle font cleanup and log kept, dropped, and missing fonts 2026-09-24 20:32:14 +02:00
LICENSE.md Add files via upload 2026-03-10 12:25:37 +01:00
README.md feat: pin xav on Windows with a one-group affinity mask 2026-09-29 23:20:37 +02:00
svt_opus_encoder.py feat: share subtitle font cleanup and log kept, dropped, and missing fonts 2026-09-24 20:32:14 +02:00
xav_automation.py feat: pin xav on Windows with a one-group affinity mask 2026-09-29 23:20:37 +02:00

AV1 Encoding Scripts

Batch-encode .mkv files to AV1 video and Opus audio. Drop the MKVs in a folder, run one of the scripts, get completed/, original/, and failed/ plus per-file logs.

Script Encoder Notes
svt_opus_encoder.py SVT-AV1-Essential via av1an Auto SDR/HDR and 1080p/4K. Default CRF 30, tune SSIM.
aom_opus_encoder.py aom-psy101 via av1an Same prep path as SVT. Default cq-level 25, two-pass.
xav_automation.py xav + SVT-AV1-Essential Native autocrop/chunking. Packet-CFR probe before HandBrake. CRF 30 always (not Essential’s 35 above 1080p).
cropdetect/cropdetect.py ffmpeg cropdetect Safe crop for mixed AR (flashbacks, IMAX). Own readme.

Put the scripts (or symlinks) on your PATH, cd to a directory of .mkv files, and run the script you want:

svt_opus_encoder.py
# or: aom_opus_encoder.py
# or: xav_automation.py

Requires in PATH: ffmpeg, ffprobe, mkvmerge, mkvextract, mkvpropedit, opusenc, mediainfo, HandBrakeCLI. Av1an scripts also need av1an, ffmsindex, and VapourSynth. xav needs xav built with SVT-AV1-Essential. Linux also needs taskset (util-linux) to pin the encode off the last two logical CPUs. On Windows 11 and Windows Server 2022 the same pin is a process affinity mask, with no extra tool. That mask names at most 64 logical CPUs; any beyond that stay free. Python fonttools is optional (Arch: python-fonttools, otherwise pip install fonttools). Without it, unused-font cleanup is skipped and every font stays attached.

Common flags: --no-downmix, --autocrop (av1an scripts), --crf / --preset / --tune / --grain where the encoder supports them, --norm-i / --norm-tp (defaults −18 LUFS / −1.5 dBTP), --nofontsclean / -nfc (keep every attached font). xav_automation.py also has --workers, --lp, --reserve-threads, and --no-taskset.

Audio: AAC/Opus remuxed; everything else loudnorm → Opus. Output folders: completed/, original/, failed/, conv_logs/. Encodes resume from .prep.mkv / temp-*.mkv when present.

Subtitle fonts: On the final mux, a font attachment is kept only when a remaining ASS/SSA track names it. Every other attachment stays. --nofontsclean / -nfc copies every font. The encode log records one line each for fonts kept, dropped, and missing. Kept and dropped use the font’s full name, not the attachment filename, so the same font matches across MKVs that attach it under different file names. Missing names are the ones written in the subtitles. A semicolon separates names, because a comma can be part of a font name. (none) means that list is empty.

    - FONT_CLEAN kept: Arial Bold; Noto Sans CJK JP
    - FONT_CLEAN dropped: Comic Sans MS
    - FONT_CLEAN missing: Open Sans

How it works and why (HandBrake vs remux, VFR, downmix, folders): Encoding guide
Encoder flags, loudnorm, CFR probe, av1an/xav command lines: Parameters

MIT — see LICENSE.md.