Recursive, resumable Windows batch transcoder for camera archives, with Sony XAVC / DJI metadata preservation and a structured PCM audio pipeline.
1KeyTranscoder is a command-line batch transcoder for Windows, built for archiving camera
footage at scale. It walks an input tree, transcodes every clip with a hardware (NVEncC /
QSVEncC) or software (x265 / SVT-AV1) backend, and writes a mirrored output tree as
.MP4 files. Batches are resumable: completed work is detected and skipped, failures are
recorded per file and can be re-run selectively.
Its distinguishing feature is metadata preservation. Sony XAVC clips carry per-frame
gyroscope and lens data (rtmd), lens profiles (nrtm) and vendor uuid boxes; DJI
action-camera clips carry djmd motion quaternions, dbgi and tmcd. Both are copied
through the transcode by a dedicated preservation pipeline and verified afterwards
(payload checksums, structure checks, and optional Gyroflow consumer-side quaternion
validation), instead of being silently dropped by a generic transcoder.
It also ships a multi-channel audio delay compensation pass (--channel-sync) for
multi-mic camera layouts, and — since v0.7.1 — an internal PCM audio pipeline
(source/stream/track/channel modelling, routing, WAV export, and N→1 mixing with gain and
clipping policy). v0.8.0 connects that pipeline to the production output: an explicit
--audio-plan JSON can select/reorder channels, ask for format-aware alignment, and pull
in external recordings found next to each clip. Without --audio-plan the default audio
path is unchanged.
Target use case: a single workstation turning multi-hour Sony / DJI shoots into archive copies without losing the motion and lens metadata that post-processing tools (Gyroflow, editors) need.
- Hardware backends: NVEncC (HEVC, AV1), QSVEncC (HEVC, AV1); software backends: SVT-AV1 and x265 (HEVC).
- With no
--encoder, the backend is auto-selected by capability probe: NVENC → QSV → x265.--no-hw-autoselectpins x265. - A mismatch between
--config'sencoderfield and--encoderis a hard error, not a silent override. - Presets
uhq/hq/small/fast/all, defined in per-backend JSON profile files; capability-based downgrade (4:2:2 → 10-bit 4:2:0 → 8-bit 4:2:0) with a loud WARNING, or skipping with--no-downgrade.
- Sony pipeline:
rtmd/nrtm/ vendoruuidpayloads carried through re-encoding with strength-parameterised post-checks. - DJI pipeline:
djmd/dbgi/tmcdcopied natively, payloadsha256recorded, optional Gyroflow per-frame quaternion validation. - Other sources: classic single-pass path (video + audio only), stated explicitly in the log.
--check basic|advanced|fullpost-encode verification, plus PSNR/SSIM sampling atfullon short clips.
- Default audio behaviour is unchanged from earlier releases: streams are copied through
(
-c:a copy; the preservation pipelines copy audio inside the container). --channel-sync: per-file GCC-PHAT delay measurement across independent mono PCM tracks, corrected by integer sample shifts only.--channel-sync-transparent: pre-editing mode that stream-copies video and all non-audio streams and only re-generates audio tracks that need correction.- v0.7.1 adds an internal PCM pipeline: source/stream/track/channel model, channel selection and mapping, unified timeline with EOF/offset handling, float32 PCM reading, routing, WAV export, and N→1 mixing with linear gain and clipping policy. See Audio Processing for scope and boundaries.
- v0.8.0 adds format-aware audio handling on top of that pipeline: PCM input is allowed
to enter alignment by default while compressed input is passed through untouched
(decode → PCM → align → re-encode only when alignment is asked for explicitly), output
codec/bitrate are inherited from the source unless overridden, and external
recordings named after the clip (
clip001.wav,clip001_01.aac, …) are discovered and appended as tracks that follow the same mapping rules.
--jobs 1|N|autoscheduling;--dry-runto probe and print commands without encoding.--retry-list failed_files.jsonto re-run only failed items, optionally on another backend.--experimental-multihw: experimental NVENC + QSV dual-backend pool (video quality consistency across backends is explicitly not guaranteed).- Logging to
error.log/warn.log/total.log/debug.log, batch-scoped environment version records, andlogs/failed_files.jsonfailure detail files. - Progress dashboard plus worker window for interactive runs, or
--headlessfor unattended operation;watchfolder.py/start.batfor polling batches.
--hw-decode off|auto|require, defaultoff(software decode; byte-identical behaviour to v0.6.2).autouses hardware readers only for runtime-proven(backend, codec, chroma, depth)combinations and warns on every downgrade;requireerrors out instead of falling back.- A frame-count integrity gate plus reader-identity assertion is always active when
hardware decode is in use;
--hw-decode-verifyadds per-frame ordered fingerprint comparison. - See Hardware Decode — the patched research binaries are not part of the release package, so hardware decode is unavailable in a release installation by design.
The x265 backend is not one preset with a speed knob. It ships four profiles — uhq,
hq, small, fast — that are four different production strategies, each calibrated
against a different constrained resource:
| Profile | Objective |
|---|---|
uhq |
Quality ceiling / extreme offline — the high-quality reference baseline |
hq |
High-quality final output at a reduced, production-viable computation cost |
small |
Storage efficiency — more computation spent deliberately to make files smaller |
fast |
Production throughput — compression efficiency per unit of encoding time |
They are not a quality ladder: uhq → hq → small → fast does not mean "better →
worse". They were calibrated on real Sony XAVC HS 4K60 10-bit 4:2:0 150 Mbps LongGOP
material plus a corpus of noisy/clean, handheld/stable, indoor/outdoor and long-form
clips, and fast / small were tuned against NVENC UHQ as an external real-world anchor
rather than against an abstract ideal.
Design methodology — goals, computation pruning, the FAST ↔ SMALL relationship, marginal-value parameter decisions and the current parameter set: docs/x265-profile-design.md.
Current release: v0.8.0 (VERSION = 0.8.0, tag v0.8.0).
| Area | Status |
|---|---|
| Core transcoding (NVENC / QSV / x265 / SVT-AV1, HEVC + AV1) | Available |
Sony rtmd / nrtm / uuid preservation |
Available |
DJI djmd / dbgi / tmcd preservation |
Available |
Post-encode verification (--check basic|advanced|full) |
Available |
--channel-sync (integer-sample delay correction, P1) |
Available |
--channel-sync-transparent (video stream copy) |
Available |
Hardware decode (--hw-decode, default off) |
Available in source installs; not usable in the release package (patched binaries excluded by design) |
| Audio model (source / stream / track / channel) | Available (internal layer) |
Audio selection and channel mapping (AudioMapSpec, dry-run) |
Available (internal layer, no CLI) |
| PCM routing (1 output channel ← 1 source channel) | Available (internal layer, no CLI) |
| WAV export (PCM16 / PCM24 / PCM32 / float32) | Available (internal API, no CLI) |
| PCM mixing (N→1, linear gain, clipping detection) | Available (internal API, no CLI) |
| Arbitrary-reference delay correction | Available as an internal API; reachable from the CLI through --audio-plan's sync.reference |
Audio execution-path resolution (NONE / STREAM_COPY / PCM_ROUTE / PCM_MIX) |
Available (Phase 4A; internal API) |
| Selective MP4 audio retention (keep / drop / reorder original audio streams) | Available through the CLI (--audio-plan). Channel-filter and mixing outputs are refused rather than faked as stream copy |
| Audio encoding (AAC / Opus / PCM / FLAC) of routed or mixed PCM | Available through the CLI (--audio-plan) |
| Final output composition (video + encoded audio → MP4) | Wired into the production entry point for the classic software path (1kt.py --encoder x265|svtav1) and the hardware backends (nvenc / qsv / qsv-av1), opt-in via --audio-plan. Sony and DJI preservation reject an audio plan per file rather than ignoring it |
| Format-aware alignment (PCM default on, compressed default off, explicit compressed → decode/re-encode with warning) | Available through the CLI (--audio-plan: alignment, sync.reference) |
Codec / bitrate inheritance (manual > source > encoder default) |
Available through the CLI (--audio-plan: encode) |
External audio discovery (clip001.wav, clip001_01.aac, …) and mapping-driven track layout |
Available through the CLI (--audio-plan: external, mapping) |
| Automatic cross-file synchronization (content matching) | Not implemented |
| Drift correction / resampling / loudness | Not implemented |
Audio CLI flags beyond --audio-plan (--audio-tracks, --audio-map, --audio-codec) |
Not implemented |
The audio model, selection layer, timeline, retention, encoding, format policy and
external-audio handling are unit- and integration-tested. v0.8.0 wires format-aware
alignment, codec inheritance and external audio into the same production entry point,
still opt-in through the single --audio-plan flag (no new CLI argument was added);
the default path is not changed. The only audio surface reachable from 1kt.py is
production.output, and anything below that is an explicit API call such as
core.audio_process.run_audio_render(),
core.audio_retention.build_audio_retention(),
core.audio_encode.encode_audio_from_plan() or
core.output_compose.OutputComposer.compose().
- Windows 10 / 11 (x64). Development and verification are performed on Windows; no other platform is tested.
- Python 3.11+ — no
pipdependencies are required for the core tool.numpy(andscipy, for--channel-sync) is optional: if it is missing, the features that need it are skipped with a WARNING and transcoding is unaffected. - External tools, called as separate executables:
ffmpeg/ffprobe— 9.0.1 (bundled in the release package). The project requires its bundled build; older PATH versions lack the AV1 features used.NVEncC9.31 and/orQSVEncC8.26 — for the hardware backends.- GPAC / MP4Box — container rebuilding and metadata preservation. Behaviour is bound to GPAC 26.02; upgrading requires a regression run.
- Gyroflow (optional) — consumer-side quaternion validation for
--check advanced|full.
- GPU driver matching the hardware backend in use (NVIDIA for NVENC, Intel for QSV).
Every tool path can be overridden: --tool-nvencc, --tool-qsvencc, --ffmpeg,
--ffprobe, --gpac-dir, --gyroflow.
The project's own
tools/directory (ffmpeg / NVEncC / QSVEncC / GPAC) is.gitignored and is the single shared toolchain used by the build and test runs. Keep it in one place and never copy, junction, or symlink it into other working trees; pass explicit paths instead.
The self-contained package bundles ffmpeg/ffprobe 9.0.1, NVEncC 9.31, QSVEncC 8.26 and
GPAC 26.02, so no separate toolchain setup is needed: unzip, install Python 3.11+ and a
GPU driver, and run 1kt.py from the extracted directory.
The currently published package is v0.6.1 — v0.7.0 and v0.7.1 are published as GitHub releases without a binary asset, and their features (hardware decode, the v0.7.1 audio pipeline) are source-only. To use v0.7.1, run from a git checkout:
- v0.6.1 package (SHA256, release manifest)
- All releases: https://github.com/Eureka175/1KeyTranscoder/releases
The package allowlist is defined by release/build_release.py: runtime code plus the
toolchain binaries, and no docs/, testsets/, work/ or dist/ content.
git clone https://github.com/Eureka175/1KeyTranscoder.git
cd 1KeyTranscoder
# Place ffmpeg/ffprobe, NVEncC, QSVEncC and GPAC under tools/, or point at existing
# installations with --ffmpeg / --ffprobe / --tool-nvencc / --tool-qsvencc / --gpac-dir.
python 1kt.py --versionpython 1kt.py --version prints the version from VERSION. No package installation step
is required; the entry points are run directly from the checkout.
Transcode a tree with the auto-selected hardware backend and the default hq preset:
python 1kt.py --input D:\footage --output D:\archiveCommon variations:
# Explicit backend and profile, quality aligned with the NVENC profile
python 1kt.py --input D:\footage --output D:\archive --encoder qsv --config qsv_aligned.json --preset hq
# Every preset (uhq / hq / small / fast)
python 1kt.py --input D:\footage --output D:\archive --encoder nvenc --preset all
# Software backends
python 1kt.py --input D:\footage --output D:\archive --encoder x265 --preset hq
python 1kt.py --input D:\footage --output D:\archive --encoder svtav1 --preset hq
# Per-file multi-channel delay compensation
python 1kt.py --input D:\footage --output D:\archive --encoder nvenc --channel-sync
# Pre-editing pass: stream-copy video, correct only the audio tracks that need it
python 1kt.py --input D:\footage --output D:\archive --channel-sync-transparent
# Unattended run: no dashboard window, everything goes to logs
python 1kt.py --input D:\footage --output D:\archive --headlessBackends: x265, svtav1, nvenc, qsv, nvenc-av1, qsv-av1. --help lists every
flag. Output files keep the source directory structure and are written with an .MP4
extension.
Source routing is automatic and is stated in the log for every file: Sony XAVC clips take
the Sony preservation pipeline, DJI clips take the DJI pipeline, and everything else takes
the classic single-pass path. AV1 backends preserve Sony rtmd / nrtm / uuid payloads
but deliberately do not write the XAVC brand (av01 instead), because XAVC defines only
H.264 and HEVC.
Long-running batches are resumable: re-running the same command skips completed outputs.
--dry-run probes and prints the commands without encoding.
v0.7.1 introduces a structured PCM audio pipeline (core/audio_*.py). Its purpose is to
make audio sources addressable as data — which channel of which stream of which source —
so that selection, mapping, routing, mixing and export can be expressed and tested
independently of any single ffmpeg invocation. v0.8.0 connects that pipeline to the
production output so the same model decides what the delivered .MP4 contains.
Source one physical origin (a media file or an external WAV)
└── Stream one audio stream inside that source
└── Channel one physical channel position (0-based)
Track a logical input track = (stream, set of channels)
Output track a logical output unit, e.g. output 0 ← camera:s2:c2
A channel is identified by all three coordinates — {source_id}:s{stream}:c{channel} —
so identically named channels from different sources never collide. A 4-channel stream
becomes one track, but its four AudioChannel objects remain individually selectable; four
mono streams become four tracks.
- Audio source / stream / track / channel modelling, built from each source's existing ffprobe result (no extra probing).
- Selection (which source channels are kept) and channel mapping (output order), with a dry-run execution spec and per-output traceability.
- Audio timeline (
AudioTimeline) as the single authority for duration, EOF and offsets, with deterministic silence fill for short sources and no hidden resampling. - Float32 PCM reading via ffmpeg with an identity channel map, so channels are never silently reordered or downmixed.
- Routing: 1 output channel ← 1 source channel, no sample arithmetic.
- WAV export in PCM16 / PCM24 / PCM32 / float32.
- Mixing: N source channels → 1 output channel, linear gain (0 dB = 1.0), float32
accumulation, peak and clipping statistics, and an explicit clipping policy
(
detect/hard_clip/error). Mixing does not normalise automatically:1.0 + 1.0 = 2.0is preserved and counted as a clipping event. - Fixed integer sample offsets produced by
channel_syncreports are applied along the unified timeline; delays are not re-estimated here.
| Layout | Representation |
|---|---|
| Single 4-channel stream | 1 source / 1 stream / 1 track / 4 channels |
| 2 × stereo | 1 source / 2 streams / 2 tracks |
| 4 × mono | 1 source / 4 streams / 4 tracks |
| External WAV (mono / stereo / 4CH) | separate source with its own timeline |
| Mixed sources | e.g. camera 4CH + recorder stereo, or camera + external WAV |
- The default production audio path is unchanged. Without
--audio-plan, audio streams are still copied (-c:a copy; container-level copy in the preservation pipelines). - The PCM chain runs only when the plan calls for it; nothing else on the production path enters it.
- Selection and mapping produce a dry-run spec only — no filtergraph is generated and no ffmpeg command is executed by the planning layer.
-map-level specification of "N source channels → 1 output channel" is still rejected asaudio_mix_not_supported, because ffmpeg argv cannot express sample-level summation. That rejection describes the-mappath; the PCM path implements the same semantics incore/audio_mix.py. The two coexist by design.- Not implemented in v0.8.0: resampling, drift correction, loudness normalisation / AGC /
limiter / EQ / noise reduction / time-stretch, automatic (content-based) cross-file
synchronisation, codec capability / quality-preset / VBR policy frameworks, rendering
multiple mix buses in one pass, and audio CLI flags beyond
--audio-plan. - The 4-channel wireless-mic layout assumes independent mono tracks; stereo and mono
layouts are deliberately not aligned by
--channel-sync.
Implementation details — module responsibilities, invariants, reason codes, and the specific internal APIs that are not stable public interfaces — are documented in Architecture §6.1 (v0.7.1) and §6.6 (v0.8.0), and in the v0.7.1 release notes plus the v0.8.0 release notes.
--audio-plan <file.json> is opt-in and the only audio CLI surface. Without it nothing
below is reachable. An empty request (for example only an encode block) is treated as
"not enabled", so the default path is structurally untouched.
Full user guide: docs/audio_plan.md — worked examples,
per-backend support, external-audio naming rules and troubleshooting. The summary below
is deliberately short.
{
"version": 1,
"encode": { "format": "opus", "bitrate": "96k" },
"channels": { "select": ["source:s1:c0", "clip001.wav:s0:c0"] },
"alignment": "auto",
"sync": { "reference": "source:s1:c0" },
"mapping": { "mode": "grouped", "group_size": 2 },
"external": {},
"note": "wireless mic CH1 -> Opus, external recorder appended"
}| Key | Meaning | Default |
|---|---|---|
encode |
Output codec (aac / opus / pcm / flac) and bitrate (lossy only) |
inherited from the source |
channels.select / exclude / map |
Which channels are kept and in what output order | all, input order |
alignment |
auto / enabled / disabled; auto enables alignment for PCM input and leaves compressed input untouched |
auto |
sync.reference |
The channel alignment is measured against. Never guessed — without it, alignment is permitted but nothing is shifted | none |
mapping |
Output stream layout for external audio: source / independent / grouped (+group_size) |
follow each input's own streams |
external |
Discover audio files named after the clip in the same directory and append them | not enabled |
Behaviour worth knowing:
- PCM input keeps PCM output; compressed input keeps its own codec and bitrate. A
manual
encodeoverrides that, per output stream. - Compressed input is never decoded just to align it. Asking for alignment explicitly emits a warning and takes the decode → PCM → align → re-encode path.
- A bitrate on a lossless output is refused, not ignored.
- Mapping is preserved: alignment and re-encoding never reorder, merge or drop
channels. Multi-channel external files are split/grouped only as the
mappingkey asks, and a partial group keeps its remaining channels (3CH+group_size 2→2CH + 1CH). - Once alignment actually shifts samples, every output stream is rendered on one shared window — stream copying cannot express a shift, so it is dropped for that output.
- External audio must be named after the clip:
clip001.wav,clip001_01.aac,clip001-rec.wavmatchclip001.MP4;clip001abc.wavandrandom_clip001.wavdo not. All matches are appended in a deterministic order (exact stem, then numeric index, then other suffixes; numeric runs compare as numbers, soclip001_2precedesclip001_10). --audio-planis supported on the classic software path (--encoder x265/svtav1) and on the hardware backends (nvenc/qsv/qsv-av1, andnvenc-av1where that encoder can be created). On hardware backends the video is still encoded by NVENC/QSV into a video-only artifact and the audio is produced by the independent audio backend; hardware decode stays available. Sony/DJI preservation paths reject an audio plan per file with an explicit error instead of ignoring it, and--audio-plancannot be combined with--channel-sync(exit code 2).- See
docs/audio_plan.mdfor the user guide.
--hw-decode off|auto|require was integrated in v0.7.0 and merged into main on
2026-09-14. The default is off.
| Policy | Behaviour |
|---|---|
off (default) |
Software decode. Hardware decoding is not attempted; behaviour matches v0.6.2 byte for byte. |
auto |
Use hardware readers only when the input matches the runtime-proven allowlist (backend, codec, chroma, depth); otherwise software decode. Every downgrade emits a WARNING with a reason code into the run logs and report. |
require |
Hardware decode is mandatory. If unavailable, the file fails (require_unmet); it never downgrades silently. |
The allowlist is a closed set in which every entry references a measurement. Profiles
outside it resolve to not_proven and software decode. Currently proven: NVENC HEVC
4:2:0 10-bit, NVENC H.264 4:2:2 10-bit, QSV HEVC 4:2:0 10-bit.
When hardware decode is active, a frame-count integrity gate is always enabled: five-way
frame accounting plus a reader-identity assertion read from the tool log (never inferred
from the command line, because QSVEncC silently constructs avsw when hardware is
unavailable). A failing artifact is discarded, reported, and re-run with software decode.
--hw-decode-verify adds sequence-level verification by comparing ordered per-frame
fingerprints of hardware and software decode, at the cost of one extra decode pass.
Temporal windows and hardware decode are mutually exclusive: with a time seek the two
rigaya readers are not equivalent (same frame count and PTS, different pictures), so the
router refuses hardware decode with seek_not_equivalent and uses software decode.
--trim is reader-equivalent and unrestricted. These parameters are not exposed as
1kt.py flags; the router reacts to them when a temporal window is passed to the readers.
Two boundaries matter when reading results:
- Hardware decode is unavailable in a release installation. The patched binaries are a
research build that must not be redistributed; they live under
tools/avhw/, which the release allowlist excludes. In a release package--hw-decode autotherefore downgrades to software decode withnot_proven, andrequirefails. This is designed behaviour, not a defect. - The patches are version-bound. The NVEncC patch is verified only on 9.31
(
2cb9d810); the QSVEncC patch is runtime-proven on the pinned 8.26 revision only (8.27–8.30 untested).
The correctness matrix for this feature is tests/hwdecode/ (83 cases, classes A–K),
with entry points in docs/hardware-decode/README.md. It requires a real GPU and the
patched binaries and is not part of tests/full_autotest.py --level full.
Three levels, run from the repository root:
python tests\full_autotest.py --level unit # L1: pure logic and deterministic logic (about 1-1.5 min)
python tests\full_autotest.py --level toolchain # L2: + tool versions, machine capabilities, flag allowlist (about 1 min, no encoding)
python tests\full_autotest.py --level full # L3: + real pipeline integration and fault injection (about 10-15 min)
python tests\full_autotest.py --level all # same as --level fullThe frozen baseline recorded for the current release (v0.8.0) is:
L1 unit 590 PASS / 0 FAIL
L3 --level full 859 PASS / 0 FAIL (unit 590 + toolchain 16 + full 253)
These numbers are assertion counts from the automated regression suite at the release freeze. They are not a new full production transcoding benchmark: the release was cut without a fresh end-to-end encode/transcode campaign on production material.
Previous baselines, for comparison:
v0.7.1 freeze unit 390 / full 509
after v0.7.1 tag (Phase 4A/4B/4C) unit 511 / full 728
Any change must be re-checked for new failures.
The default audio path is unchanged: without --audio-plan the tool still does
-map 0 + -c:a copy. With an explicit plan (JSON) the classic software path
(x265 / SVT-AV1) and the hardware backends (NVENC / QSV) encode or retain the audio
you select and compose it with the video, which is stream-copied and therefore
bit-identical to the default path.
{
"version": 1,
"encode": { "format": "opus", "bitrate": "96k" },
"channels": { "select": ["source:s1:c0", "source:s2:c0"] },
"external": {}
}Channel ids use the existing audio identity (<source>:s<stream>:c<channel>); external
files use their file name as the source id (clip001.wav:s0:c0). Leaving channels out
(and not asking for external, alignment or mapping) means "select everything",
which makes the plan a default plan: the execution path resolves to NONE and nothing
changes. Unknown keys, unknown versions and unknown formats are errors, and hardware
backends, Sony and DJI preservation reject an audio plan explicitly rather than ignoring
it. See Explicit audio output above for the full
key list and behaviour.
tests/full_autotest.py is a thin compatibility entry point: the CLI, exit code and
report format are unchanged, while the implementation lives in the tests/selftest/
package, split by responsibility.
tests/selftest/
├── runner/ CLI (argparse), suite registry, executor
├── fixtures/ reusable material: deterministic PCM, AudioPlan builders, real media
├── assertions/ reusable audio observation primitives (impulse maps, hashes)
├── suites/ the tests themselves, one module per area
│ ├── core.py color / caps / hw planning / probe / classifier / GPAC
│ ├── codecs.py x265 P0, AV1
│ ├── channel_sync.py delay compensation (pure logic + algorithm)
│ ├── audio_model.py audio track / channel / plan model
│ ├── audio_selection.py sources, selection, channel mapping
│ ├── audio_timeline.py timeline, render policy, EOF, sync offset direction
│ ├── audio_route.py channel routing, WAV export, chunk invariance
│ ├── audio_mix.py PCM mixing, graph equivalence
│ ├── audio_sync.py arbitrary-reference delay correction
│ ├── audio_retention.py Phase 4A: execution path + selective MP4 retention
│ ├── audio_encode.py Phase 4B: PCM → encoded audio (EncodedAudioOutput)
│ ├── production_output.py Phase 4C: --audio-plan through the real 1kt.py entry
│ ├── audio_format.py v0.8.0: format policy, alignment, codec inheritance
│ ├── audio_external.py v0.8.0: external discovery rules + mapping matrix
│ ├── audio_integration.py L3 audio integration on real material
│ ├── pipeline.py L3 full pipeline + fault injection
│ ├── hardware.py L3 channel-sync end to end
│ ├── toolchain.py L2 tool / capability probing
│ └── cli.py CLI contract
├── reporting/ result aggregation and report writing
└── (production coordination lives outside this package: `core/audio_request.py`,
`core/audio_format.py`, `core/audio_external.py`,
`core/audio_output_structure.py`, `production/output.py`)
paths is the only module holding mutable test state (RESULTS / CURRENT_LEVEL).
Legacy names (full_autotest.SUITES, full_autotest.record, …) still forward to the
real implementation, and no suite display name changed, so report filtering by name
keeps working.
Scheduled hardware-decode verification is separate:
python -m tests.hwdecode.harness provenance # binary/patch identity; mismatch = FAIL
python -m tests.hwdecode.harness check-matrix # documentation vs matrix drift check
python -m tests.hwdecode.harness run --phase 1 # A toolchain + B routing
python -m tests.hwdecode.harness summary # aggregate gateTargeted self-checks: python tests\run_selfcheck.py --encoder nvenc|qsv|x265 and
python -m preservation.selfcheck <original> <final> <log_dir>.
1KeyTranscoder/
├── 1kt.py Main CLI entry point (orchestration)
├── watchfolder.py Polling batch entry point
├── start.bat Double-click launcher
├── VERSION Single source of the version number (0.8.0)
├── *.json Encoder profile / scaling configurations
├── core/ Runtime core: pipeline, probing, planning, audio, dashboard
├── encoders/ Encoder backends, capability probing, hardware decode, integrity gate
├── preservation/ Sony / DJI metadata preservation, validation, quality sampling
├── production/ Cross-domain orchestration: audio output → final container
├── release/ Release packaging and package verification tools
├── tests/ Automated test suites (incl. tests/hwdecode/)
├── docs/ Design, evaluation, release and reference documentation
├── logos/ Brand assets
├── licenses/ GNU GPL v3 text (referenced by LGPL-3.0)
├── olddocs/ Archived documents and code snapshots
├── LICENSE GNU LGPL v3 text
└── NOTICE Copyright and SPDX identifier
| Path | Purpose |
|---|---|
1kt.py |
Command-line entry point; argument parsing and per-file orchestration. |
core/ |
Backend-agnostic runtime logic: configuration, probing, source classification, scaling, batching, channel sync, the v0.7.1 audio modules and the v0.8.0 format/external-audio policy modules, logging, dashboard. |
encoders/ |
Backend implementations (NVEncC, QSVEncC, x265, SVT-AV1), capability tables, hardware-decode routing, integrity gate. |
preservation/ |
Sony and DJI preservation pipelines, container/ISO-BMFF handling, validation checkers, quality sampling. |
production/ |
Cross-domain orchestration: turns a video artifact plus an audio plan into the final container. Belongs to neither the audio nor the video domain. |
release/ |
build_release.py (allowlist-based packaging) and verify_package.py. |
tests/ |
full_autotest.py (thin entry point: unit / toolchain / full), the tests/selftest/ runner + fixtures + suites, targeted self-checks, fixtures, and the hardware-decode matrix in tests/hwdecode/. |
docs/ |
Design documents, evaluation reports, release notes, third-party reference archive. |
logos/ |
Primary logo, symbol mark and word mark. |
licenses/ |
GNU GPL v3 text incorporated by reference by LGPL-3.0. |
olddocs/ |
The project's single archive location for superseded documents and code snapshots. |
Local-only directories (tools/, testsets/, work/, logs/, dist/) are not tracked
by git; dist/ holds release artifacts built locally.
- Documentation index — classified index of everything under
docs/. - x265 profile design — why there are four profiles, how each was derived, the FAST ↔ SMALL calibration, the NVENC anchor, and the current parameter set.
- Audio plan user guide — how to use
--audio-plan: worked JSON examples, per-backend support, external-audio naming rules, limitations and troubleshooting. - Architecture — end-to-end data flow, invariants, module map. Start here to understand how the code runs.
- v0.7.1 release notes — the audio model and PCM pipeline, phase by phase.
- v0.8.0 release notes — arbitrary-reference delay correction, Phase 4A/4B/4C output integration, and Phase 5 format-aware alignment + external audio. Published with tag
v0.8.0. - v0.6.1 release notes — channel-sync streaming memory fix and AV1 colour metadata fix.
- Channel-sync P1 design — algorithm, thresholds, degradation rules, fixture calibration.
- Hardware decode deliverables — integration test matrix, final report, patches, toolchain provenance.
- Evaluation reports — per-backend production-readiness and AV1 calibration studies.
- Third-party reference archive — archived vendor documentation and upstream sources.
- Archive status index — read the status banners before citing archived conclusions.
Current release: v0.8.0
- GitHub release v0.8.0 — published with a self-contained Windows package.
- Release notes v0.8.0 — frozen with the tag; the release notes file is not rewritten after publication.
- Self-contained Windows package:
1KeyTranscoder-v0.8.0-win64-selfcontained.zip
(
sha256 7eb98a8077bda09f5c7e074198e83fc84aee0782204580923a52de5fe0f5c0ba, 522 file records, verified byrelease/verify_package.py— 62/62 checks PASS). - v0.8.0 is published as a normal (non-pre-release) GitHub release, so it is the
repository's "Latest release". The entries before it were published with GitHub's
"pre-release" flag set; they are still the releases of their own versions and match
their
VERSIONfiles and tags.
Older releases with downloadable self-contained packages:
| Version | Download | Notes |
|---|---|---|
| v0.6.1 | zip | Channel-sync streaming memory fix; package still available. |
| v0.5.1 | zip | AV1 line (software + hardware AV1). |
| v0.4.2 | zip | HEVC/265 line. |
No package was published for v0.7.0 or v0.7.1; those features are available from a source
checkout of main.
Directions currently defined by the existing design and release documentation. No dates are assigned.
| Stage | Item |
|---|---|
| Later | Automatic cross-file synchronization — deriving delays across files rather than per file. |
| Later | Drift correction — correcting slowly varying offsets (currently detected as non_constant and refused) instead of constant integer shifts. |
| Later | Resampling and loudness handling — deliberately absent; sample rates must match and no dynamics processing exists. |
Selective MP4 audio retention (Phase 4A), audio encode/mux integration (Phase 4B), production integration (Phase 4C) and format-aware alignment plus external audio (Phase 5) are implemented and shipped in v0.8.0; see the v0.8.0 release notes.
- Platform: Windows only; no other platform is tested.
- Audio CLI:
--audio-planis the only audio flag. Everything else in the audio pipeline is reachable only through the internal API. - Audio plan availability:
--audio-planworks on the classic software path (--encoder x265/svtav1) and on the hardware backends (nvenc/qsv/qsv-av1, andnvenc-av1where that encoder can be created). The Sony/DJI preservation pipelines reject it per file rather than ignoring it, and it cannot be combined with--channel-sync. - Alignment: only constant integer sample offsets exist. A reference channel must be named explicitly — the tool never guesses one, so "alignment: auto" on PCM material only makes the pipeline eligible to align. Compressed input requires an explicit request, is decoded and re-encoded, and cannot be aligned by shifting packet timestamps.
- Output structure: external audio follows the
mappingkey exactly. A group that is not a whole input stream is rebuilt from PCM, and once alignment shifts samples every output stream is rendered (stream copying cannot carry a shift). - Offset model: only constant integer sample offsets are supported. Drift correction, resampling and time-stretch do not exist; a slow drift is detected and the track is left untouched rather than corrected.
- Channel sync scope:
--channel-syncrequires at least three independent mono PCM tracks at 48 or 96 kHz with linear PCM sample formats; 44.1 kHz and compressed formats are explicitly refused, and stereo/mono layouts are not aligned by default. The only long-run validated configuration is 4 tracks / 48 kHz / single-threaded;--jobs auto, 10-minute Sony/DJI material and--experimental-multihwlong runs are not validated. - Hardware decode: unavailable in release installations by design; the proven
allowlist is a closed set of three combinations;
--seekis mutually exclusive with it; the measured benefit is CPU headroom, not single-job speedup. - AV1 output: always 4:2:0; Sony sources keep their metadata but do not get an XAVC brand; inputs below 1080p are not processed by default; the 4K60 UHQ preset is a reference setting, not a practical production setting.
- Preservation: non-Sony, non-DJI sources are transcoded without metadata (video and
audio only). For DJI, the MJPEG cover image and
udtaare dropped because GPAC 26.02 cannot address them; this is logged explicitly. - Playback: Sony 4:2:2 output is HEVC Rext, which only NVIDIA 50-series GPUs can hardware-decode; distribute a 4:2:0 copy instead.
- Quality alignment: the QSV profile aligned to the NVENC profile is calibrated, not identical; high-motion material remains roughly 1 dB below NVENC, which is a hardware ceiling rather than a configuration issue.
- Stability of internal interfaces: several v0.7.1 audio objects are explicitly marked
internal or reserved and are not guaranteed to keep their current semantics; the
authoritative list is in
architecture.md §6.1 and
release_notes_v0.7.1.md §32.- Encoder profile values: the numbers in the
*.jsonprofiles are measured calibrations. Changing them requires a test-set regression run.
Issues and pull requests are welcome. There is no contributor guide yet.
- Keep changes reproducible: run
python tests\full_autotest.py --level unitat minimum, and--level fullbefore submitting anything that touches the pipeline. No pull request may introduce a new FAIL. - Changes that touch preservation, container handling or encoder profiles must state the material and tool versions used for verification.
- Do not modify the encoder profile JSON values or the brand/logo assets without an explicit reason recorded in the change.
- Documentation lives in
docs/and follows the classification described in docs/README.md; the root README stays user-facing.
The repository provides three brand assets under logos/. They are used as-is; the files
are not renamed or modified.
Symbol mark plus word mark. Used for the README header, project presentation, release pages and documentation covers.
<p align="center">
<img src="logos/Primary%20Logo.png" alt="1KeyTranscoder Primary Logo" width="360">
</p>Mark only, without text. Intended for application icons, avatars, favicons and other small-size contexts.
<img src="logos/Symbol%20Mark.png" alt="1KeyTranscoder Symbol Mark" width="120">The 1KeyTranscoder wordmark only. Intended for documentation, UI headers and
horizontally constrained layouts.
<img src="logos/Word%20Mark.png" alt="1KeyTranscoder Word Mark" width="280">No monochrome, app-icon, favicon, stacked or motion variants exist in this repository.
GNU Lesser General Public License v3.0 or later (LGPL-3.0-or-later).
- LICENSE — GNU LGPL v3 text.
- licenses/GPL-3.0.txt — GNU GPL v3 text, incorporated by reference by LGPL-3.0.
- NOTICE — copyright and SPDX identifier.
Third-party tools (NVEncC, QSVEncC, GPAC, ffmpeg, Gyroflow) are invoked as separate executables and are distributed under their own licences; they are not part of this project's codebase.
