Skip to content

预览音频跟随音量包络 + 淡入淡出#174

Merged
appergb merged 1 commit into
mainfrom
feat/preview-audio-envelope
Jul 2, 2026
Merged

预览音频跟随音量包络 + 淡入淡出#174
appergb merged 1 commit into
mainfrom
feat/preview-audio-envelope

Conversation

@appergb

@appergb appergb commented Jul 1, 2026

Copy link
Copy Markdown
Owner

概要

预览播放时音频现在跟随音量关键帧自动化 + 淡入淡出。此前是每 tick 设静态 clamp[0,1] 的 clip.volume,忽略自动化与淡变。

变更

  • timelinePlayback.ts:新增 clipVolumeAt(track, clip, frame)——muted→0,否则真实 volumeAt 包络(static × dB 关键帧 × fade),非有限→1,不封顶
  • previewEngine.tssyncFollowers(每 rAF tick)按当前帧采样,el.volume = Math.min(1, gain) 在赋值处 clamp(HTMLMediaElement.volume >1 抛 RangeError);linked-audio 去重静音 + scrub/seek 路径未动。

上游对齐

上游经 CompositionBuilder.emitVolumeEnvelope 采样 Clip.volumeAtAVAudioMix 挂到 AVPlayerItem 驱动真预览——本 PR 在浏览器 [0,1] 限内 1:1 复刻该行为。

延后(非本 PR)

>0dB 增益(gain >1)需 Web Audio GainNode(el.volume 被浏览器限 1)。该路径需处理 tauri asset 协议的 CORS(污染的 MediaElementSource 会静音全部预览音频)+ 真机音频验证(无法 headless 验),故留 TODO(>0dB),真实 gain 已在 pure 函数里备用。

测试

  • clipVolumeAt 6 单测(muted→0 / 静态透传 / dB 关键帧 linearFromDb / fade-in 斜坡 0→0.5→1 / >1 boost 预 clamp 保留 / NaN 守卫)。
  • pnpm build(tsc)绿;pnpm test 215 通过(+6)。

…yback

Preview audio ignored volume automation and fades — it set a static, clamped
clip.volume once per tick. Upstream drives live preview through an AVAudioMix
whose volume ramps sample Clip.volumeAt (static × dB-keyframe gain × fade) per
clip (CompositionBuilder.emitVolumeEnvelope → AVPlayerItem.audioMix). Port that
at the browser's limit: sample volumeAt(clip, frame) every rAF tick.

- timelinePlayback.ts: clipVolumeAt(track, clip, frame) — muted → 0, else the
  true (unclamped) volumeAt envelope; non-finite → 1. 6 tests (mute, static
  passthrough, dB keyframe via linearFromDb, fade-in ramp, >1 boost preserved,
  NaN guard).
- previewEngine.ts: syncFollowers samples clipVolumeAt at the loop's frame; the
  linked-audio-dedup mute is unchanged; el.volume = Math.min(1, gain) clamps at
  the assignment (HTMLMediaElement.volume throws above 1). Scrub/seek paths
  (which only touch currentTime) are untouched.

Deferred: >0 dB boost (gain > 1) needs a Web Audio GainNode — el.volume is
browser-capped at 1. That path needs Tauri-asset CORS handling (a tainted
MediaElementSource would silence all preview audio) + real-machine audio
verification, so it is marked TODO(>0dB) and the true gain is kept available.

Verified: pnpm build (tsc) clean; pnpm test 215 passed (+6).
@appergb appergb merged commit 4256253 into main Jul 2, 2026
2 checks passed
@appergb appergb deleted the feat/preview-audio-envelope branch July 2, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant