Repository navigation
v0.4.0 — Codec expansion
Codec expansion release. HEVC and AV1 join H.264 across NVENC + software paths, with a per-codec preset editor, three quality tiers (Fast / Balanced / Pristine), custom presets that survive an app restart, and a benchmark mode that scores 2–4 candidate profiles on a 10-second sample with size, encode time, and PSNR.
Headline feature: the encoder is no longer a single fixed pipeline. Pick H.264, HEVC, or AV1 — each gets its own hardware path (NVENC) and software fallback (libx264 / libx265 / libsvtav1), its own preset family, and its own quality scale. Save your favourite knob combination as a custom preset and apply it later in one click; spin up a benchmark to see which codec actually wins on your specific source.
Install
- Windows —
Moekoder-0.4.0-win-x64.exe. Still unsigned; SmartScreen will show More info → Run anyway on first launch. - macOS —
Moekoder-0.4.0-mac-arm64.dmg. Still unsigned; after dragging into/Applications, run:to clear the Gatekeeper quarantine.xattr -cr /Applications/Moekoder.app
- Linux — not shipped this release. Still on the roadmap.
If you're upgrading from v0.3.0, the auto-updater on Windows pulls this release in the background; the next launch comes up on v0.4.0. macOS users grab the DMG manually until code-signing lands.
New codecs
- HEVC encode path —
hevc_nvenc(10-bit main10) andlibx265software encoder. NVENC main10 emitsformat=yuv420p10leupstream for the encoder; libx265 inherits source pixel format. - AV1 encode path —
av1_nvenc(RTX 40-series, gated bygpu.probe()'s per-encoder name list) andlibsvtav1software encoder with integer-preset 0..13. - HEVC + MP4 mux flag —
-tag:v hvc1appended on the HEVC + MP4 combination so QuickTime / iOS pick up the stream as HEVC. - Discriminated-union
EncodingSettings— the shape is now tagged oncodec, eliminating illegal combinations (libx265 + AV1, etc.) at compile time. Each branch carries only its valid hardware paths and codec-specific knobs (NVENCpN, libx265 preset family, SVT-AV1 0..13).
Settings → Encoding
A new section in Settings exposes every codec knob in one place:
- Codec radio (H.264 / HEVC / AV1) and hardware-encoder picker, filtered against
gpu.probe()so disabled options aren't even clickable. - Fast / Balanced / Pristine quick-set buttons per codec. Balanced defaults: H.264 CQ 19 / NVENC p4 (the v0.1 default), HEVC CQ 22 / 10-bit, AV1 CQ 28 / 10-bit. Fast drops the CQ ceiling + NVENC p2; Pristine raises the ceiling + p7. Nine presets total.
- CQ slider clamped + labelled per codec (libsvtav1 goes to 63, the rest stop at 51).
- Per-encoder preset knob (NVENC pN / libx265 preset family / SVT-AV1 0..13).
- 10-bit toggle for HEVC + AV1 NVENC.
- Container picker.
Settings persist as a single encoding profile blob in electron-store.
Settings → Custom presets
- Name + save the live encoding profile, apply it later in one click, delete entries.
- Up to 20 presets; names must be unique.
- Each entry carries
version: 1from day one for forward-compat migrations.
Benchmark mode
- Encodes a 10-second sample of a chosen video against 2–4 candidate profiles.
- Reports per-row size, elapsed time, and PSNR (dB).
- Reachable from the Encoding section's "Run benchmark" button.
- Defaults to the user's currently-selected codec at Fast / Balanced / Pristine; an inline codec cycler lets you promote a slot to a different codec to compare across families.
- Temp files live under
<userData>/benchmark/<runId>/and clean up on completion. - One-shot
-lavfi psnrrunner (ffmpeg/psnr.ts) parsesaverage:from stderr with a 60-second hard cap to bound a malformed candidate. - Per-candidate failures surface in the result row rather than rejecting the whole run, so a single bad config doesn't lose the other rows.
- New
benchmark:runIPC with zod-validated tuple schema (max 4 candidates) and dedicated event channels (benchmark:progress,benchmark:log). - New
EncodeJob.clipWindow— optional{ startSec, durationSec }propagates into-ss <start> -t <duration>ahead of-i. Benchmark uses it; Single + Queue routes don't set it.
Changed
EncodingSettingsis now a discriminated union overcodec— every existing call site keeps compiling because the v0.1 H.264 NVENC defaults still satisfy the H.264 branch shape, but new code that touches partial overrides should calldefaultsFor(codec)rather than spreadingBALANCED_PRESETdirectly.- Filter chain pixel format is now codec-aware — NVENC h264 still emits
format=yuv420p; HEVC + AV1 NVENC emitformat=yuv420p10lewhentenBitis set. libx265 + libsvtav1 software branches don't force a pixel format and inherit from the source. - App.tsx prefers the persisted
encodingprofile when present and falls back to the legacy onboarding-derived overrides only when the user hasn't opened the new Encoding section yet — no behavioural change for existing user flows.
Maintenance
- Toolchain bumps — electron 41.2.1 → 42.0.1, vite 7 → 8 +
@vitejs/plugin-react4.7.0 → 6.0.2 (withresolve.dedupe+ droppedminify:'esbuild'for vite 8 compat), vitest 3 → 4 in web + desktop (explicitincludeglob pinned for desktop), zod 3 → 4 in apps/desktop. - Node engine floor raised to
>=22.12.0to satisfy electron 42's runtime requirements. - Security fixes — Phase 1 safe bumps + Phase 2 pnpm overrides clear 4 high-severity CVEs (
fast-uri <3.1.2,ip-address <10.1.1,devalue >=5.6.3 <5.8.1pinned forward).
Tests
14 new vitest tests — 10 in args.test.ts (hevc_nvenc / hevc + libx265 / av1_nvenc / libsvtav1 branches, 8-bit fallback, MKV-strips-hvc1, clipWindow plumbing) and 4 in benchmark.test.ts (sequential runs, candidate failures don't kill the run, candidate cap, zero-candidate no-op). Test count: 190 (was 176).
Known limitations
- Custom preset import / export to JSON file isn't shipped — deferred to v0.5.
- Per-job overrides in the queue still aren't supported — every queue item uses the global
encodingprofile. Lands in v0.5 alongside import/export so the UI work happens together. - Per-codec preflight bitrate estimate isn't shipped; preflight stays pinned to the H.264 number (2500 kbps) and over-reserves disk for HEVC/AV1. Safe direction for a guard.
- AV1 NVENC needs an RTX 40-series GPU. Pre-RTX-40 hardware sees the AV1 NVENC option disabled with a
requires RTX 40-seriestooltip; AV1 software (libsvtav1) is always available. - Benchmark mode runs candidates sequentially. Parallel candidates are tractable (the orchestrator already supports concurrency) but the benchmark deliberately serialises so the timing numbers aren't contaminated by GPU contention.
- Same as v0.3.0: binaries are unsigned, auto-updater is Windows-only, no Linux build.
Source under the Moekoder Source Available License.