Skip to content

Releases: Eureka175/1KeyTranscoder

1KeyTranscoder v0.8.0 — 音频输出接入生产管线 · 格式感知 · 外挂音频

Choose a tag to compare

@Eureka175 Eureka175 released this 16 Sep 07:44

1KeyTranscoder v0.8.0 — 音频输出接入生产管线 · 格式感知 · 外挂音频

v0.8.0 把 v0.7.1 建立的 PCM 音频管线真正接进生产输出,并补上三件此前
只靠"调用方自觉"的事:输入格式判定输出编码继承外挂音频
全部仍然是音频域内部的能力,视频编码后端与元数据保留管线一行未改

基线 v0.7.1(tag v0.7.1 = e613b07)。
详细设计与实测证据见仓库
docs/release_notes_v0.8.0.md
docs/design/architecture.md §6.2–§6.6。

Included

  • Audio format-aware alignment — 输入是 PCM 还是 compressed 由 ffprobe 的
    codec_name 唯一判定pcm_* = uncompressed,其余 = compressed):
    PCM 输入默认允许进入 alignment,compressed 输入默认原样保留
    alignment: disabled 可显式关闭。reference 仍然从不自动猜 —— 必须由
    sync.reference 显式给出,否则"允许对齐"不会产生任何 offset。
  • Compressed audio re-encode for alignment — 显式要求 compressed 输入对齐时
    输出 §5 的 warning,并走 decode → PCM → align → 重编码,输出 codec 保持
    来源 codec。实测:注入 480 样本延迟的 Opus 目标估计出 480、AAC 目标
    1504(480 + AAC 解码 priming 1024),两者对齐后互相关残差 0 —— 这正
    是"禁止在压缩包上伪造时间戳平移"的量化理由。
  • External audio discovery — 同一目录下按确定性文件名规则发现外挂录音:
    音频主干必须以视频主干精确开头,且其后的第一个字符必须是结束 / - / _
    只扫描视频所在目录与音频扩展名白名单。排序完全确定(精确主干 → 数字序号 →
    其它后缀),数字段按数值比较(clip001_2clip001_10 之前),前导零
    归一化但仍是不同候选,同分用完整文件名 lexical order 收尾。多个候选全部
    纳入
    没有候选不报错
  • External audio mapping — 外挂音频严格遵循最终 mapping:source(跟随每个
    输入的流结构,默认)/ independent(一声道一条流)/ grouped(n)(连续 n 声道
    一条流,跨文件继续成组)。4CH + grouped(2) → 2×stereo,8CH + grouped(2)
    → 4×stereo,3CH + grouped(2)2CH + 1CH(奇数剩余保留,不丢弃也不复制)。
    不变量:Σ 输出声道 == 有效映射声道,否则报错而不是静默丢声道。
  • AAC / Opus manual bitrate — 输出编码优先级链
    manual override > source-derived defaults > encoder default:PCM 输入默认
    PCM 输出,compressed 输入保持来源 codec + 来源 bitrate,手动 format /
    bitrate 覆盖之(AAC 128k/192k/256k、Opus 64k/96k/128k …)。lossless 输出带
    bitrate 明确拒绝,不静默忽略。codec 继承按输出流进行,因此一条 AAC 外挂
    录音与一条 PCM 源可以在同一份输出里各自保持自己的 codec。
  • Mapping preservation — alignment 与重编码只移动样本时间轴,绝不改变声道
    身份、流顺序或声道集合;原视频音频的输出结构由既有输出单元决定,不被 mapping
    策略改写。整条完整源流仍然 -map + stream copy(不解码、不重编码),只有必须
    重建的流才渲染 + 编码,两者可在同一次输出里混用。
  • Regression coverage--level unit 590 PASS / 0 FAIL
    --level full 856 PASS / 0 FAIL(unit 590 + toolchain 16 + full 250)。
    相对 Phase 4C 基线(unit 511 / full 728)新增 128 条断言、0 条 FAIL、
    0 条被删除。

Fixed

  • alignment 与 stream copy 不能混用-map 没有"时间原点"可言,而有 offset 的
    声道是按统一 timeline 重新取样的(window 起点可能不是 0)。两者混在一个容器里
    就是两条流各有各的原点 —— 表现出来恰好是"对齐没生效"。现在一旦产生非零
    offset,整份输出共用一份 render window,每条输出流都由 render 产出,组数与
    每组声道保持不变。
  • AAC 容器由裸 ADTS 改为 MP4 家族(.m4a:实测 PCM → AAC(ADTS) → 解码
    会让内容整体后移 1024 个样本(编码器 priming,ADTS 无法携带),"为重编码对齐"
    会被这一步吃掉;MP4 容器把 priming 写进 edit list,实测位置一致。
    同时 _probe_audio() 不再把 nb_frames 当样本数 —— MP4 家族的音频流报的是
    packet 数(AAC 一包 1024 样本)。

CLI

  • 没有新增参数:全部能力通过既有的 --audio-plan JSON 触达,新增四个
    可选键:alignment / sync / mapping / external(schema 版本仍为 1,
    因为这是加法式扩展;未知键依旧一律拒绝)。
  • 不指定 --audio-plan 时默认音频路径完全不变-map 0 + -c:a copy)。
  • --audio-plan 仍只在经典软件路径(--encoder x265 / svtav1)生效;硬件后端
    与 Sony/DJI 保留管线明确报错(rc=2)而不是静默忽略,与 --channel-sync
    互斥(同样 rc=2)。

Package

自包含 Windows x64 包(与 v0.6.1 同一套打包脚本 release/build_release.py):

1KeyTranscoder-v0.8.0-win64-selfcontained.zip
  sha256  7eb98a8077bda09f5c7e074198e83fc84aee0782204580923a52de5fe0f5c0ba
  522 file records · 内含 release-manifest.json(逐文件 size + sha256)
  runtime: ffmpeg/ffprobe 9.0.1 · NVEncC 9.31 · QSVEncC 8.26 · MP4Box 26.02

包完整性由 release/verify_package.py 复核:62/62 checks PASS(含逐文件
sha256 对账、开发产物不得入包、运行时版本可复现)。

Not implemented

drift correction:  not implemented
resampling:        not implemented
loudness:          not implemented

也仍然没有:自动多文件同步(外挂音频只按文件名规则发现,不做内容匹配)、
codec 能力 / quality preset / VBR 策略框架、多 mixer sink 的输出结构、
硬件后端与 Sony/DJI 保留管线上的音频计划、P5。

Unchanged

  • video encode backendencoders/core/scaling.pycore/hwdecode.py
    相对 v0.7.1 零改动,视频基本流 sha256 在每种音频处理下都和默认路径一致
    (回归逐案断言)。
  • metadata backend / Sony / DJI preservationpreservation/ 相对 v0.7.1
    零改动
  • sync algorithmcore/channel_sync.py / core/sync_estimate.py /
    core/sync_fix.py / core/mp4_channel_sync.py 零改动;arbitrary-reference
    回归全部通过。
  • default audio path — 未启用 --audio-plan 时行为与 v0.7.1 完全一致。

1KeyTranscoder v0.7.1

1KeyTranscoder v0.7.1 Pre-release
Pre-release

Choose a tag to compare

@Eureka175 Eureka175 released this 15 Sep 11:20

1KeyTranscoder v0.7.1 — 音频处理架构与 PCM 管线

v0.7.1 focuses on the audio processing architecture and PCM pipeline.
全部为内部能力层:不新增 CLI,默认音频路径与输出行为未改变

基线 v0.7.0(hardware-decode integration,已并入 main)。
详细设计与完整测试矩阵见仓库 docs/release_notes_v0.7.1.md

Included

  • Audio modelAudioSource / AudioStream / AudioChannel / AudioTrack /
    AudioPlan / AudioSyncResult(纯数据层,零项目内依赖,JSON 往返稳定)
  • Source / stream / channel selection and mapping — 三维身份
    {source_id}:s{stream}:c{channel}AudioPlannerAudioOutputTrack
    AudioMapSpec(dry-run,不执行 ffmpeg)
  • Unified timeline / EOF / offset handlingAudioTimeline 是时长·EOF·offset
    唯一权威RenderPolicy.UNION、确定性静音补位、timeline = source − offset
  • PCM routingAudioPCMReader(ffmpeg → canonical float32,分块读取,
    identity channelmap 防隐式重排)+ AudioRouter(1:1 纯样本搬运)
  • WAV exportWavExporter(PCM16/24/32 + float32,WAVE_FORMAT_EXTENSIBLE
    header 按实际字节回填)
  • PCM mixing and clipping policiesAudioMixer(N→1、线性 gain、float32 累加、
    MixStats 检波、ClipPolicy = detect / hard_clip / error
  • Regression coverage — 既有自动化回归套件 509 PASS / 0 FAIL
    (unit 390 + toolchain 16 + full 103)

Unchanged

  • default audio copy pathAudioPlan = None-map 0 + -c:a copy
    Sony/DJI 仍由 GPAC 复制音频;生产代码对 audio_* 模块零 import
  • hardware decodeencoders/preservation/ 相对 v0.7.0 零改动
  • video path1kt.py / core/batch_hw.py 零改动
  • x265 scalingencoders/x265.pycore/scaling.py 零改动
  • channel_sync algorithm — 算法、阈值、schema 零改动(模型只读取其报告 JSON)

相对 v0.7.0 的唯一非音频改动是 core/probe.py-show_entries 增加
stream_tags(纯增量,既有键与 CSV 字段白名单不变)。


RC1 修正与冻结(v0.7.1-rc1 之前)

29. 修正:混音图的 silence_samples 统计(F1)

AudioRenderResult.silence_samplesmixing 图下恒定错误地报"全程静音"。

原因:run_audio_render()mixing_timeline() 的产物传给了
_count_faithful_mix(),而混音 timeline 的输出声道身份是 mix0/mix1
该函数却按声道(camera:s0:c0)去 lookup,必然全部 miss → total = 0
silence_samples = frames × output_channels

1000f + 400f, 1 输出声道 修正前 修正后
routing source A 1ch + source B 1ch(2 输出声道) 600 ✓ 600
mixing A×0.5 + B×0.5(1 输出声道) 1000 0

修正方式:逐输入几何一律查未混音的 base timelinecore/audio_process.py),
并在 _count_faithful_mix() docstring 里写明该前提。
未改动AudioMixer / AudioTimeline / EOF policy / 实际 PCM 输出 /
混音 timeline 的 mixN 输出身份 / routing 行为。

回归:l1.p3b.silence_samples 走 base timeline (混音图不恒报满)
l1.p3a.silence_samples (routing 1000f+400f, 2 输出声道) = 600
(已验证:撤掉修正后前者立刻 FAIL,detail 恰为 silence=1000 total=1000。)

30. 修正:effective_mapping 提升为公开入口(F6)

core/audio_plan._effective_mapping()core/audio_timeline.py 直接 import,
形成 Timeline → Plan私有名跨层依赖

  • core/audio_plan.py_effective_mappingeffective_mapping(公开,
    进入 __all__);参数、返回值、mapping 语义完全未变
  • 保留 _effective_mapping = effective_mapping 作为兼容别名(同一实现,
    不是第二套);
  • core/audio_timeline.py / core/audio_process.py 一律引用公开名;
  • 项目代码中私有旧名只剩别名那一行

未改动任何 JSON、任何测试预期、任何 mapping 行为。

31. 冻结:输出权威的分工(F5)

输出音频集合与顺序的唯一权威 = AudioTimeline
    routing 图: output_channel_ids = 源声道身份      (camera:s2:c2)
    mixing  图: output_channel_ids = 合成身份        (mix0 / mix1)

AudioMapSpec = -map / stream-copy / channel-filter 路径的执行规格
    strategy == MIXING  → 该路径**不可直接执行**, 必须转入 PCM processing graph
                        (不是"计划非法")

AudioMapSpec 并未失效:它定义的输出顺序来自 effective_mapping()
AudioTimeline 消费的正是同一个函数,两者不会分叉。详见
docs/design/architecture.md §6.1.11。

32. 冻结:RC 边界(不保证兼容的部分)

以下对象在 v0.7.1-rc1 被显式标注为内部/预留 —— Phase 4 不得依赖

AudioPlan.channel_map / wav_outputs   reserved, 零写入者, 语义未定, 不保证兼容
AudioOutputSpec.kind                  当前唯一合法值 "wav"; Phase 4B 可替换为枚举
AudioMixer.output_format              internal (仅服务面向 WAV 的混音)
AudioMixer.frames()                   INTERNAL (契约与 AudioRouter.frames() 不一致)
AudioMixer.render_to()                INTERNAL (当前无调用者)
AudioPCMReader.read()                 not thread-safe (共享 handles + 绝对 seek;
                                      当前串行调用无问题, Phase 5/6 并行化须重新设计)
AudioPlan.notes                       stable string only, 非机器可读元数据契约

reason codes 中有两个 reserved、当前生产路径不可达

audio_sync_offset_invalid       _effective_offset() 对非法 offset 静默回退 0
audio_pcm_format_unsupported    audio_pcm 解码路径无此拒绝; 该字符串目前由
                                core/audio_wav 以字面量形式发出

二者不是 active runtime error,不得据此编写分支逻辑。

序列化字段策略(自 v0.7.1 起):

新增字段: 默认可选, 为默认值时不写出 (旧 JSON 缺失该键必须照常工作)
删除字段: 必须递增 AUDIO_MODEL_VERSION; 不做 migration framework
未知键 / 未知 enum: 一律容错 (忽略 / 回退安全默认) —— 宁可"未知", 不可"猜"

详见 docs/design/architecture.md §6.1.12 / §6.1.13。


Deferred(未包含)

v0.7.1 明确不包含以下内容(仍属后续 Phase):

- selective MP4 retention
- audio encoding/mux
- automatic cross-file synchronization
- drift correction
- resampling(采样率不一致仍直接拒绝)
- loudness normalization / LUFS / AGC / limiter / compressor / EQ /
  reverb / noise reduction / spectral processing / time-stretch / pitch shift
- 新音频 CLI(--audio-* 全部未开放)
- 多 bus 同时渲染(当前一次渲染只消费第一个 MixBus)

与仓库 docs/release_notes_v0.7.1.md §20 / §27 的"未实现"边界逐条一致;
§28 的总体清单(✅ = 本版已交付)如下:

WAV 导出 ✅(P3A)
PCM Routing ✅(P3A)
PCM Mixing ✅(P3B)
Selective MP4 retention ❌
音频编码 + mux 进 MP4 ❌
自动跨文件时间轴对齐 ❌
漂移校正 ❌

其余明确边界(重采样、loudness normalization / LUFS / AGC / limiter /
compressor / EQ / reverb / noise reduction / spectral processing /
time-stretch / pitch shift、新音频 CLI)见仓库
docs/release_notes_v0.7.1.md §20 / §27。

1KeyTranscoder v0.7.0 (hardware decode integration)

Choose a tag to compare

@Eureka175 Eureka175 released this 13 Sep 02:58

1KeyTranscoder v0.7.0 — Release Notes

发布类型:milestone release(Hardware Decode integration)· GitHub Pre-release
基线:main @ b3245b7main 未被本版修改
本版 tag 所在分支:feature/hardware-decode-integration
本版不是 1.0.0,也不代表完整 release capability。
--hw-decode 的默认值仍是 off,默认路径行为与集成前逐 token 相同

1. Highlights

说明
Hardware decode 接入 新增 --hw-decode off|auto|require(默认 off)与可选的 --hw-decode-verify(sequence 级闸门)。硬解是显式 opt-in 路径,不是新的默认行为
Capability routing 只有落在 runtime-proven allowlist 内的组合才允许走硬解;其余一律 not_proven → 软解(见 §4)
Integrity gate 硬解产物必须通过帧完整性闸门:五方帧数对账 + reader 身份断言count 级,启用硬解时始终开启);--hw-decode-verify 再加逐帧有序 fingerprintsequence 级,opt-in,代价是每文件多一次编码)
Fallback / reason codes 闸门不过 ⇒ 丢弃硬件产物 → WARNING + reason code → 同格式档软解重跑;回退上限 1 次(MAX_HW_DECODE_FALLBACKS),超出即 FATAL,不无限重试(见 §5)
Binary provenance 绑定 硬解使用 provenance 校验过的 patched build(sha256 绑定);build 缺失或 hash 不符时给 reason code,绝不静默改用 shipped build
默认行为零变化 HD-B05 逐 token 断言:policy=off(不传任何开关)产出的 argv 与集成前完全一致(首部仍 --avsw
验证规模 integration matrix 83/83 PASS(P0 61/61,0 FAIL / 0 BLOCKED / 0 SKIP);既有全量回归 tests/full_autotest.py --level full 248 PASS / 0 FAIL

2. 版本号

VERSION                    0.6.2  ->  0.7.0
python 1kt.py --version    1KeyTranscoder 0.7.0

VERSION 是唯一版本来源(core/version.py),1kt.py --version
release/build_release.pyrelease/verify_package.py 均从该文件读取,
不存在第二处硬编码版本。本版未改动任何编码/解码行为、默认后端或默认硬解策略

3. Integration 判定(机器可读闸门)

Branch:        feature/hardware-decode-integration
Base:          main @ b3245b7   (main 未被修改)
Commits:       da27e28 .. f819eb4

Test Matrix:   Total 83 | PASS 83 | FAIL 0 | BLOCKED 0 | SKIP 0
               P0 61/61 · P1 21/21 · P2 1/1
既有回归:      tests/full_autotest.py --level full -> 248 PASS / 0 FAIL (570.3s)

Final status:  READY FOR REVIEW      Blockers: (无)

判定规则未放宽:任何 P0 FAIL/BLOCKED ⇒ 最终状态必须 BLOCKED
SKIPBLOCKED 不计入通过。最终 0 个 P0 FAIL / 0 个 P0 BLOCKED。

分类覆盖:A toolchain 9 · B routing 10 · C frame integrity 13 · D temporal 9 ·
E preservation 7 · F fallback 8 · G existing features 9 · H resume/retry 5 ·
I concurrency 5 · J production/long-run 6 · K golden baseline 2。

矩阵的自动化状态为 100% auto —— 没有"需要人工播放视频检查"的条目。

4. 路由契约

policy = off | auto | require            默认 off(= v0.6.2 行为,零变化)

eligible(backend, codec, chroma, depth) :=
        在 runtime-proven allowlist 内
    AND 不在 known_refusals 内
    AND 请求未携带时间 seek
    AND 该组合未被本运行 memo 标记为不可用

off      -> reader = avsw                    (不出任何提示)
auto     -> eligible ? avhw : avsw           (降级必须出声:WARNING + reason code)
require  -> eligible ? avhw : ERROR          (绝不静默降级)

runtime-proven allowlist(初始内容,全部经 research + 本次 integration 实测):

backend codec chroma depth 依据
nvenc hevc 4:2:0 10 N−3 → N(30/330/10170 帧),与 --avsw 字节相同
nvenc h264 4:2:2 10 N−2 → N(195 帧),与 --avsw 字节相同
qsv hevc 4:2:0 10 N−3 → N,逐帧 SHA-256 与 --avsw 相同

known_refusals:qsv + h264 + 4:2:2 + 10bit
avqsv: codec h264(yuv422p10le) unable to decode by qsv. rc=−31、无 reader、无输出)。

allowlist 之外一律 not_proven → 软解(8-bit / All-I / 1080p / AV1 / VFR /
HEVC 4:2:2 等均未纳入)。这是"不把未实测 profile 静默塞进硬件路径"的落实,不是遗漏。

5. 帧完整性闸门与 reason codes

失败动作:丢弃硬件产物 → 出声(WARNING + reason code)→ 同格式档软解重跑。

两级闸门分别对应两类缺陷:

  • count 级:工具 rc == 0 且产物非空;reader 身份断言(请求 avhw
    却构造出 avsw 即 silent software fallback,判 FAIL);五方对账
    container_expected 为参考真值,encoder_input / output_stream /
    independent_decoded 任一不等即 FAIL;reader 自报只记录、永不作参考
  • sequence 级(--hw-decode-verify opt-in):硬解与软解结果逐帧有序
    fingerprint 比对,抓计数不变的错序/替换/重复。

Reason codes(互不相同、可审计):
policy_off · proven_combination · not_proven · capability_refused ·
reader_unavailable · device_unavailable · startup_failed ·
decode_failed · count_mismatch · sequence_mismatch ·
seek_not_equivalent · require_unmet · integrity_ok

端到端实测(真实 CLI,节选):

[HWDEC] decode tool: ...\tools\avhw\NVEncC_9.31_avhw\NVEncC64.exe
        (patched build verified by sha256 dcf6d7a63143c777)
DECODE_ROUTE | backend=nvenc codec=hevc 4:2:0/10bit policy=auto -> HARDWARE
        (reader=avhw, reason=proven_combination)
INTEGRITY | integrity gate [OK] reason=integrity_ok
        counts={tool_rc:0, reader_identity:'avcuvid', encoder_input:360,
                container_expected:360, container_method:'isobmff-stsz', ...}

6. Validation

结果
Integration test matrix 83/83 PASS(P0 61/61 · P1 21/21 · P2 1/1;0 FAIL / 0 BLOCKED / 0 SKIP,累计约 3.3 h)
既有全量回归 tests/full_autotest.py --level full248 PASS / 0 FAIL(570.3 s)
Golden baseline(软件基线自洽性) HD-K01 / HD-K02 PASS:6 条 fixture 的软件基线在独立重跑下逐字节重 derive
真实语料 Sony testsets/20260904/*.MP4 取样 10 短 / 10 中 / 10 长;DJI action4 4K + 语料内 DJI 片段
工具链身份 每次运行前校验 binary sha256 + 补丁 sha256 + --version 字段,不符即 FAIL(不是 warning)

矩阵执行过程中抓到 3 个真实问题(1 个生产缺陷:_encoded_ok() 曾接受被截断的
intermediate;1 个研究线未记录的行为差异;1 个集成缺陷:find_hw_tool 目录 glob
可能按排序捞到 patched build),final regression 又打回本 session 自己引入的 3 个缺陷 ——
全部先定位根因再修被测对象或判定逻辑,并重跑同一测试确认。

7. 边界声明(引用本版结论时必须带上)

  • QSVEncC 补丁: Runtime-proven on QSVEncC 8.26 pinned revision; not yet a
    general claim for later releases.
    (8.27–8.30 存在且未检验)
  • NVEncC 补丁: 仅在 9.31(2cb9d810c045202548b98ff130b12bc764eb39ea)上验证。
  • research build 不可分发: 两个 patched binary 都是 research build
    (avs/vpy reader 关闭、CUDA MSBuild shim、FFmpeg 动态链接、QSVEncC 的 OneVPL
    单独构建)。release/build_release.pyTOOL_DIRS 白名单不含 tools/avhw/
    因此发布安装中 --hw-decode auto 会以 not_proven 降级软解、require 会明确
    失败 —— 这是设计行为,不是缺陷。
  • 跨 binary 性能不可比: patched 与 stock 工具链不同(CUDA 13.1/MSVC 14.51 vs
    CUDA 11.8/MSVC 14.44),跨 binary 只比正确性,不比性能。
  • 矩阵通过 ≠ 全新声明: 通过范围是 Sony XAVC HS(HEVC Main10 4:2:0)、
    Sony XAVC S(H.264 4:2:2 10-bit)、DJI(HEVC Main10 4:2:0),
    以及 x265 / synthetic / MKV 控制组。
  • FramePosList::setPocAndFix 独立 metadata-table 缺陷,本版未研究、未修复
    consumer 侧缓解措施是"永不把 reader 自报当成帧数"(已落实为设计)。

8. Known Limitations

# 限制 影响
1 QSVEncC 版本边界(仅 pinned 8.26) 8.27–8.30 未检验,不纳入通过范围
2 research build 不可分发 发布包中不含 patched binary ⇒ 发布安装里 --hw-decode auto 降级软解
3 allowlist 是封闭的 8-bit / All-I / 1080p / AV1 / VFR / HEVC 4:2:2 均 not_proven → 软解
4 --seek 两 reader 不等价 已由路由守卫覆盖(production 不使用 seek)
5 --frames N 三段语义 是 reader 共有行为,与硬解无关
6 单 GPU 主机 多 GPU / --device 选择未验证
7 --seek 差异机制未解释 不影响生产路径
8 4-way 4K 并发上限与机制 本版无吞吐判据(实测 118.61 fps 与 research 的 8.01 fps 规格不同,不可比)
9 遥测完整性 CPU time / GPU util / VRAM 采样;平台未报告时记 null
10 raw-pipe 架构未采用 按 research 建议,FFmpeg CPU raw-pipe 不作为 production primary architecture

仍未完成,不得视为已解决:

  • Audio Drift(P2 漂移分类 / resample)—— NOT STARTED
  • patched hardware binary 仍为 research build,不可分发 ⇒ 发布形态下硬解不可用(§7)
  • 是否把 hardware decode 设为默认 —— 未决定,需矩阵全绿 + production benchmark 之后另行决策;
    本版未改变默认值(仍 off
  • 其余 P2 follow-ups:--seek 机制解释、QSVEncC 8.27–8.30 复验、pipeline patch 反馈上游、
    多 GPU 验证、allowlist 扩展(8-bit / 1080p / VFR)、--hw-decode-verify 作为常规开关的成本评估、
    4-way 4K 并发上限机制、FramePosList::setPocAndFix 上游报告

9. Backward Compatibility

  • VERSION / --version1KeyTranscoder 0.7.0
  • 档位 JSON 与命令行无破坏性变更;未传 --hw-decode 时命令行逐 token 与
    v0.6.2 相同
    ,reader 恒为 avsw
  • 默认后端选择(能力优先 NVENC → QSV → x265)与 --no-hw-autoselect 语义未变;
  • 新增开关仅两个:--hw-decode {off,auto,require}(默认 off)与 --hw-decode-verify(opt-in);
  • 硬解失败不会改变输出格式档:回退是在同一格式档上用软解重跑。

10. Package

本版没有自包含发布包(no binary asset)。

Archive —(本版不提供)
原因 1 本版 tag 位于 feature/hardware-decode-integration,而 release/build_release.py 的分支守卫要求 main
原因 2 硬解所需 patched binary 是 research build,按设计不入包(§7)
最后一个带自包含包的版本 v0.6.11KeyTranscoder-v0.6.1-win64-selfcontained.zip

从源码使用:git checkout v0.7.0,需要 Python 3.11+,并按 README.md §依赖
准备 tools/(ffmpeg/ffprobe 9.0.1、NVEncC 9.31、QSVEncC 8.26、GPAC)。

11. 相关文档

复现矩阵:

python -m tests.hwdecode.harness provenance      # 工具链身份(不符 = FAIL)
python -m tests.hwdecode.harness check-matrix    # 文档与 matrix.json 漂移检查
python -m tests.hwdecode.inventory               # 生成 control fixtures + 语料盘点
python -m tests.hwdecode.harness run --phase 1   # ... 依次到 --phase 6
python -m tests.hwdecode.harness summary         # 汇总闸门

1KeyTranscoder v0.6.1

1KeyTranscoder v0.6.1 Pre-release
Pre-release

Choose a tag to compare

@Eureka175 Eureka175 released this 11 Sep 15:50

1KeyTranscoder v0.6.1

bugfix release(无功能新增、无破坏性变更)。基线 v0.6.0,上游分支 main

Highlights

  • Channel Sync P1 —— --channel-sync 自动轨间延时补偿:GCC-PHAT 两阶段测量 → 相位斜率精估 → 轨道级质量门 → 纯整数样本移位 → 复检;锚点按 CH3 > CH4 > CH1 > CH2 回退;轨道级部分成功(坏轨原样保留,不拖累健康轨)
  • AV1 mainline —— SVT-AV1(软件)/ NVENC-AV1 / QSV-AV1 三后端与 HEVC/x265 同处 main,共用一个入口与一套 Sony/DJI 元数据保留管线
  • AV1 + channel-sync —— AV1 后端与 --channel-sync / --channel-sync-transparent 组合路径已验证
  • AV1 color metadata fidelity —— 源素材未声明色彩描述时,AV1 输出不再凭空带上 bt709
  • Streaming memory fix(本版核心修复) —— --channel-sync 长素材内存无上限增长已修复
  • Transparent / Sony / DJI preservation —— --channel-sync-transparent 剪辑前预处理;Sony XAVC(rtmd/nrtm/uuid)与 DJI(djmd/dbgi/tmcd)元数据原生保留

Fixed — --channel-sync 长素材内存无上限增长

10 分钟 / 4 轨 / 48 kHz 素材上峰值 RSS 曾达 605–713 MB随时长线性增长(每分钟 +50~137 MB)。

根因np.memmap 并不等于低内存 —— 映射本身几乎不占内存(增量 +0.0 MB),但每个被触碰的 file-backed 页都计入进程 WorkingSet 并长期保留,而实现确实顺序触碰了每条轨的每一个字节:_track_health() 分块扫描整轨算 RMS → 每轨恰好 +110 MB(4 轨 +440 MB);shift_stream()np.memmap(mode="w+") 写整轨 → 输出脏页常驻。阶段探针实测 719.0 MB 峰值中约 61% 来自整轨映射页驻留

修复:新增 RawStream 有界窗口读取器(seek+read,1 MiB 对齐块 + 4 槽 LRU,每流约 4 MiB)取代整文件映射;shift_stream() 输出改普通文件句柄;estimate_pair() / recheck_residual() 拆为「所有权包装 + 纯计算」。

算法语义未变:块寻址落在与 memmap 相同的文件偏移,dtype 映射、f32→f64 转换点与 RMS 平方和归约顺序均未变;GCC-PHAT 数学、delay 方向、搜索窗、置信度/aligned/drift_min_ms 阈值、锚点优先级、low_confidence/insufficient_frames 判定与报告字段一行未改;未引入 resample / time-warp / fractional sinc / 新依赖。

Performance(本次实测)

规格:  600 s / 4 audio tracks / 48 kHz / --channel-sync / 单线程 (--jobs 1)
输入:  LONG-CS-AUDIO.mp4 (600.02 s, 4× pcm_s24be 单声道, 真实 A7M5 素材流拷贝拼接)

Peak RSS:  153-288 MB      (目标 <= 512 MB)   PASS
Runtime:   45.3-52.7 s     (目标 < 60 s)      PASS

同步正确性:status=applied / scope=partial / 锚点 CH3;CH1 shift_samples=1051(= 冻结标定值 +21.8958 ms @​48 kHz);复检残差 +0.0180 ms(≤0.05 ms 门限);CH2 复检超差 → 安全 untouched 未误修;4 条音轨完整、输出可解码。

时长扫描(v0.6.0 → v0.6.1):60 s 151.6→208.1、150 s 356.7→228.8、300 s 468.3→208.5、450 s 579.7→264.6、600 s 605.4→209.3 MB —— RSS 不再随时长增长

Validation

结果
137 段真实 A7M5 baseline 已对齐 111 / 实际修正 11 / 测量失败 15 完全复现;逐文件报告 JSON 137/137 字节相同
Full short regression --level full228 PASS / 0 FAIL(573 s)
Package integrity 54/54 PASS(SHA256 / sidecar / manifest 对账 / ZIP CRC / 455 文件逐文件 hash / 无开发残留)
Clean-room cold-start 77/77 PASS(版本 1KeyTranscoder 0.6.1;x265 / SVT-AV1 / QSV-AV1 / NVENC-AV1 / channel-sync / transparent / Sony preservation / AV1+channel-sync,全部 rc=0、可解码、音轨 4/4)
600 s channel-sync benchmark 20/20 PASS(RSS 288.3 MB / 46.4 s)

Package

Archive 1KeyTranscoder-v0.6.1-win64-selfcontained.zip
Size 575,571,948 B (548.9 MiB)
SHA256 1c3685cf7e23ea9e227d5f42b36ce1978fa4c68206c84e348882153f09b39d31
内置运行时 ffmpeg/ffprobe 9.0.1(libsvtav1 v4.2.0 / libx265 / libvmaf)、NVEncC 9.31、QSVEncC 8.26、GPAC 26.02
不含 .git/work/testsets/docs/logs/dist/release/__pycache__/

需要 Python 3.11+ 与对应 GPU 驱动;解压即用。校验:
certutil -hashfile <zip> SHA256 或对照 .sha256 附件。

Known Limitations

  • SVT-AV1 无场景关键帧scd 只管码率分配)、mbr 为软上限(非 VBV 硬钳)
  • AV1 仅 MP4 容器,统一 4:2:0 输出
  • --channel-sync 只做整数样本移位:无 resample、无 fractional sinc、无 time-warp;真实慢漂移(39–76 ppm)判 non_constant 并拒绝修正
  • --channel-sync 仅支持 48 / 96 kHz 线性 PCM≥3 条独立单声道轨
  • --channel-sync 长程性能仅在 4 轨 / 48 kHz / 单线程规格下实测
  • --channel-sync-transparent 成功路径保留 .1ktwork/(4× audio_*.mov + 报告 JSON,10 分钟约 330 MB),属既有行为

仍未完成,不得视为已解决:Sony 10 分钟长程验证 · DJI 10 分钟长程验证 · --jobs auto 长程验证 · --experimental-multihw 长程验证 · P2 漂移分类与 resample(NOT STARTED)。

Compatibility

档位 JSON 与命令行无破坏性变更--channel-sync 的阈值、默认值、报告字段与 JSON 结构完全不变;--channel-sync 关闭时输出与 v0.6.0 行为一致。


完整发布说明见仓库 docs/release_notes_v0.6.1.md

1KeyTranscoder v0.5.1 (av1 · 软件+硬件 AV1)

Choose a tag to compare

@Eureka175 Eureka175 released this 01 Sep 13:38

1KeyTranscoder v0.5.1 — av1 分支 (软件 + 硬件 AV1)

自包含 win64 包: 项目代码 + ffmpeg/ffprobe 9.0.1 (libsvtav1 v4.2.0/libx265/libvmaf) + NVEncC 9.31 + QSVEncC 8.26 + GPAC 26.02。

本次增量 (相对 v0.5.0):

  • full 检查新增 PSNR/SSIM 质量抽样 (同 main 线 v0.4.2)
  • 环境版本记录 logs/env_versions.json/.csv (含 SVT-AV1 库版本实测)
  • 档位重排 (用户判定标准: 每档质量≥x265 同档且码流更低则不动): UHQ preset 1 (1.07fps 对齐 x265 UHQ) / HQ crf 26 / SMALL crf 30 (双素材质量更高+码流更低) / FAST crf 30; 详见 docs/evaluation/av1_calibration.md §5
  • Sony/DJI AV1 保留管线 (rtmd/nrtm/uuid/djmd 保真, 不打 XAVC tag, brand av01)
  • 历史档案归档至 olddocs/
  • 自动化测试 143/143 × 2 轮

用法见包内 RELEASE_NOTES.txt。Gyroflow (可选) 请从 gyroflow.xyz 单独安装。

第三方组件版权归各项目所有 (许可文本随包保留)。

1KeyTranscoder v0.4.2 (main · HEVC/265)

Choose a tag to compare

@Eureka175 Eureka175 released this 01 Sep 13:38

1KeyTranscoder v0.4.2 — main 分支 (HEVC/265 线)

自包含 win64 包: 项目代码 + ffmpeg/ffprobe 9.0.1 (libx265/libvmaf) + NVEncC 9.31 + QSVEncC 8.26 + GPAC 26.02。

本次增量 (相对 v0.4.1):

  • full 检查新增 PSNR/SSIM 质量抽样: sha256 确定性 10 取 1、仅 ≤60s 短视频、setpts=N 帧索引对齐、防花屏阈值 (psnr 25dB/ssim 0.80/垃圾帧≤2%),Sony/DJI/经典三路径 (经典路径交付前拦截); 阈值经各档位 JSON quality_check 节可调
  • 环境版本记录: 每批次 logs/env_versions.json/.csv (ffmpeg/NVEncC/QSVEncC/GPAC/Gyroflow + GPU 驱动)
  • 历史档案归档至 olddocs/ (backup/、x265_archive.py、sony_poc.py)
  • 自动化测试 109/109 × 2 轮

用法见包内 RELEASE_NOTES.txt。Gyroflow (可选, --check advanced/full 消费端校验) 请从 gyroflow.xyz 单独安装。

第三方组件版权归各项目所有 (许可文本随包保留)。

1KeyTranscoder v0.3.0-beta

Pre-release

Choose a tag to compare

@Eureka175 Eureka175 released this 28 Aug 13:23

1KeyTranscoder v0.3.0-beta

First beta release of the integrated 1KeyTranscoder pipeline.

Changes

  • 1keytransc.py is now the single main entry point.
  • Integrated GPAC-based container reconstruction.
  • Integrated Sony metadata preservation.
  • Preserves Sony RTMD timed metadata tracks.
  • Preserves Sony NRTM metadata and Lens Profile when present.
  • Preserves NonRealTimeMeta XML.
  • Preserves Sony PROF, USMT, and other vendor-specific UUID structures.
  • Preserves Sony metadata track relationships such as tref/cdsc.
  • Uses GPAC-native timeline reconstruction in the normal pipeline.
  • Added source-aware x265 pixel-format handling.
  • Audio is preserved by stream copy.
  • Original basenames are retained.
  • Output extension is standardized to .MP4.
  • Gyroflow validation passed on Sony A7M5 and A7M4 real-world test outputs.

Validated Sources

Sony A7M5

  • 4K 59.94p
  • 10-bit 4:2:0 HEVC
  • Sony RTMD metadata
  • Lens / stabilization metadata
  • 4-track mono PCM audio

Sony A7M4

  • 4K 29.97p
  • 10-bit 4:2:2 H.264 source
  • HEVC Rext output
  • Sony RTMD metadata
  • Sony vendor UUID structures

Current Scope

This beta primarily targets Sony camera footage and the current x265 workflow.

DJI Action 4 support and NVENC integration are planned next.

Known Limitations

  • Sony Catalyst compatibility has not been independently validated.
  • Audio is currently copy-only.
  • Unsupported audio/container combinations fail explicitly instead of being automatically re-encoded.
  • DJI metadata preservation is not yet implemented.
  • Additional camera-specific metadata backends are not yet implemented.