Batch video transcoder for home archival. Scans your movie collection, lets you pick tracks in a TUI, saves a JSON plan, then encodes everything to 10-bit AV1 — NVENC (NVIDIA hardware) for speed, with grainy SD film routed to SVT-AV1 so its grain survives.
- Plan, review, then run — choose tracks and preview in a TUI, save a JSON plan you can inspect or edit before hours of encoding
- Resumable — failed jobs retry on next run, plan updated atomically after each job
- Live progress on every long step — up-front analysis runs the batch in parallel; ffmpeg extraction, eac3to, qaac, mkvmerge and the encoder all stream into one unified progress bar; no more silent multi-gigabyte waits
- 10-bit AV1 output — always main10, no manual quality tuning across SD/720p/1080p/4K
- Film-grain preservation — grainy SD film is auto-detected and encoded with SVT-AV1, which keeps the grain in the bitstream (still hardware-decodable), instead of NVENC, which smooths it into waxy faces; confirm or override per file with
Gin the selector - Soft-telecine aware — detects 2:3 pulldown on NTSC DVDs, encodes the coded film frames and pins the true film rate so playback isn't sped up or desynced
- Disc demux — Blu-ray (BDMV) and DVD (VIDEO_TS) fed straight into the pipeline with playlist/title selection
- Anamorphic SAR fix — detects and corrects wrong sample aspect ratio on DVD sources
- Dolby Vision — Profile 7 FEL (converted to P8.1) and Profile 8 MEL, re-tagged as AV1 Profile 10.1, RPU handled via dovi_tool
- HDR10 passthrough — mastering display, content light level, BT.2020/PQ preserved through encode
- HDR10+ passthrough — per-frame SMPTE ST 2094-40 metadata extracted with hdr10plus_tool and re-injected into the AV1 stream; the extracted JSON is checked against the source frame count and both the encode and the delivered file are verified to carry the metadata, so a partial or dropped track fails the file instead of shipping silently. Re-encoding HDR10+ needs an HEVC source (the extraction path demuxes HEVC); copied/remuxed video is unaffected
- Auto deinterlace — nnedi (neural network); HD interlaced content is always deinterlaced, SD is confirmed with idet before committing
- Smart crop — black bars detected automatically across the timeline
- Target-quality encoding — always on, no flag: before each encode Furnace probes short windows at several quality settings and interpolation-searches the one that hits a perceptual target — QVBR against CVVDP (HDR) or SSIMULACRA2 (SDR) on the NVEnc path, CRF against worst-case SSIMULACRA2 on the SVT-AV1 grain path — then encodes at it, full speed, with no metrics slowing the final pass. The chosen setting is cached to the plan so re-runs skip the search
- mpv preview — audition audio tracks, check subtitles, or preview video right from the TUI before committing
- Per-track downmix — fold 7.1 or 5.1 into stereo or 5.1 from the track selector, useful when the multichannel mix is a fake upmix or the movie is dialogue-heavy
- Satellite files — external audio and subtitle files next to the video are picked up as extra tracks automatically
- Selective ASS font embedding — selected ASS/SSA tracks are parsed for fonts used by rendered dialogue, including style resets and inline font/bold/italic overrides; only matching font attachments are embedded, while removing those subtitles removes their fonts too
- Library inventory —
furnace scanlists each file's encode status, codec, bit depth, HDR class and tracks, and filters by Furnace version to surface re-encode candidates
furnace plan <source> -o <output> --audio-lang rus,eng --sub-lang rus,eng
# -> opens TUI for track selection -> saves furnace-plan.json
furnace run furnace-plan.json
# -> encodes all pending jobs with live progress TUI
- Python 3.13+
- ffmpeg / ffprobe
- MKVToolNix (mkvmerge, mkvpropedit)
- eac3to
- qaac64
- mkclean
- mpv (track preview)
- MakeMKV (DVD demux)
- NVEncC (video encoder)
VapourSynth plugins — required for the SVT-AV1 grain path. The grain path target-quality-searches its CRF by scoring probes with Vship, so these are needed to encode grainy SD film (without them, grain jobs fall back to a fixed CRF with no search). VapourSynth itself installs as a furnace dependency; drop these DLLs into one folder (e.g. C:\Tools\Media\vapoursynth-plugins\) and point bestsource / vship at them in furnace.toml:
- BestSource — source filter;
BestSource.dllfromBestSource-R19.7z - Vship — GPU metric engine (SSIMULACRA2 / CVVDP);
libvship_NVIDIA.dllfromlibvship_NVIDIA.zip(NVIDIA/CUDA build)
The metric reference is deinterlaced/cropped/scaled through the encode's own ffmpeg filtergraph (so it lines up pixel-for-pixel with the encode), which means interlaced grain sources need no separate deinterlace plugin here.
Optional:
- dovi_tool — Dolby Vision RPU handling; only needed for Dolby Vision sources
- hdr10plus_tool — HDR10+ dynamic metadata handling; only needed for HDR10+ sources
uv pip install .Copy furnace.toml.example to furnace.toml and set paths to your tools. Searched in order: --config flag, current directory, %APPDATA%\furnace\.
Plan with dry run (no TUI, just print what would happen):
furnace plan D:\Movies -o E:\Encoded --audio-lang jpn --sub-lang eng --dry-runPlan and encode:
furnace plan D:\Movies -o E:\Encoded --audio-lang rus,eng --sub-lang rus,eng
furnace run E:\Encoded\furnace-plan.jsonDuring planning, Furnace resolves fonts only from the ASS/SSA subtitle tracks kept in the plan. It ignores unused styles, comments and vector drawings, matches embedded TTF/OTF/TTC/OTC faces by family and bold/italic state, and reports missing faces. SRT, PGS and VobSub tracks do not retain font attachments; non-font attachments such as covers are preserved. Plans created before Furnace 2.30.0 should be regenerated so attachment stream indexes are available during extraction.
Copy eligible video streams verbatim instead of re-encoding (audio still processed, container rebuilt):
furnace plan D:\Movies -o E:\Encoded --audio-lang eng --sub-lang eng --copy-videoEligible streams are copied as-is (crop/deinterlace skipped); interlaced and Dolby Vision P7 FEL sources fall back to a normal encode, and the plan report shows passthrough (copy video) or encode (<reason>) per file.
Audio kept in a separate file next to the movie (movie.flac beside movie.mkv) is muxed in as a normal track. Plans created before Furnace 2.40.0 should be regenerated for such movies: earlier versions numbered those tracks with a slot that collided with a real track of the main file, so the stored stream index points at the wrong stream.
In the track selector, l cycles the highlighted track's language through the languages you passed on the command line — --audio-lang for audio tracks, --sub-lang for subtitles — wrapping back to the track's own tag. Use it for und tracks (a separate audio file next to the movie usually carries no language at all) or for a single mistagged track.
Relabel mistagged track languages wholesale (treats every track as unspecified, so l cycles the given languages with no original tag to fall back to):
furnace plan D:\Movies -o E:\Encoded --audio-lang rus,eng --sub-lang rus,eng --ignore-langsInventory a folder and check Furnace-encode status (read-only — never modifies files):
furnace scan D:\MoviesEach video file is listed with its encode status (Furnace vX.Y.Z, not encoded, or unreadable) and its video, audio and subtitle tracks. Filter by encode status to find files needing a (re)encode — the flags union (OR):
furnace scan D:\Movies --not-encoded # no parseable Furnace tag
furnace scan D:\Movies --encoded # encoded by any Furnace version
furnace scan D:\Movies --max-version 1.19.3 # encoded by Furnace <= 1.19.3The table prints to stdout and is redirect-safe (ASCII box, no ANSI, no truncation); the N of M shown summary and any warnings go to stderr, so furnace scan D:\Movies > out.txt yields a clean plain-text file.
