Skip to content

1KeyTranscoder v0.7.1

Pre-release
Pre-release

Choose a tag to compare

@Eureka175 Eureka175 released this 15 Sep 11:20
· 11 commits to main since this release

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。