Skip to content

recorder: 新增「BGM 跟随视频剪辑」选项(剪辑策略四条的现状核对) - #4

Open
std-external wants to merge 1 commit into
std-microblock:masterfrom
std-external:feat/clip-options
Open

std-external wants to merge 1 commit into
std-microblock:masterfrom
std-external:feat/clip-options

Conversation

@std-external

@std-external std-external commented Oct 15, 2026 •

Copy link
Copy Markdown

来源:群里(Celeste Coders)对录像「剪辑策略」提的四条需求。先核对了现有实现,再补上确实缺的那条。

现有实现核对(四条里两条仓库本来就有,一条只对节奏敏感房间生效)

需求 现状 位置
是否保留暂停界面 已经有开关:保留暂停画面,默认关 = 暂停期间不录(现状不变),开启后暂停画面进片 Source/QolSettings.cs:331、Source/AutoRecorder.cs:218、:258、UI Source/QolSettingsOverlay.cs:1698
是否保留进房间的第一次尝试(第一次死亡) 已经有开关:保留死亡前的失败尝试,默认关 = 死亡那一段照旧切掉;开启后死亡/复活留在片里不被切 Source/QolSettings.cs:334、Source/AutoRecorder.cs:373、:433、UI Source/QolSettingsOverlay.cs:1699
是否保留 sl 的过场(load 后按第一个键前的冻结段) 本次没做,见下 —
bgm 是否跟随视频一起剪辑 之前只有「节奏敏感房间」(磁带房等)会自动跟随;普通房间的重建 BGM 会跨剪切点连续播放 → 本次新增全局开关 Source/AutoRecorder.cs:972、Source/RecordingTimeline.cs:10、Source/MusicEventReplayRenderer.cs:74

本次改动

新增设置 RecordingBgmFollowsVideo(Source/QolSettings.cs:341;UI 在 Source/QolSettingsOverlay.cs:1705,画质声音页):

  • 默认 false,行为与现在完全一致:只有节奏敏感房间的片段钉在源时间上(RhythmMapDetector.IsRhythmSensitive),其余房间由重建 BGM 跨剪切点连续播放。
  • 打开后每个房间的片段都带上 BgmFollowsVideo,即 BGM 读取真实源时间、跟着画面一起被剪(bgm_follows_video 这条链路本来就通,这里只是把「谁来决定」交给用户)。
  • 只在 BGM 拼接 = 自动对齐与拼接 时显示(Source/QolSettingsOverlay.cs:1683 的 BgmRebuildOnly):跟随游戏现场 模式本来就是随视频裁切,这个开关没有意义。
  • BeginRun(Source/AutoRecorder.cs:529)里同步初始化,避免首个房间快照之前创建的片段漏掉这个标记。

没做的一条:SL 过场

load 后到玩家按第一个键前的冻结段 目前会作为「开头冻结帧」留在新分支的开头(ManualSlPresented 在第一个干净呈现帧就重开分支,Source/AutoRecorder.cs:626-648;这段静止时间 >50ms 会让内容时钟重新锚定,于是成片里就是一帧挂住)。没做它的原因:

  1. 正确的口径是「第一个输入事件」而不是时长(StIntroRespawn 只覆盖 0.6s 的复活表演,SRT 读档后的静止并不走那个状态),可用的实现是在 ManualSlPresented 里加输入门闩:没输入就不重开分支。这样改会让 manualSlSuspended 一直挂着——玩家如果一直不碰键,录像就停在那儿不恢复,需要真实游戏 + SRT 才能验证这个边界。
  2. 现在的 剪辑冻结帧(RecordingRemoveFreezeFrames)已经能把这段剪掉,只是它同时会剪掉别的冻结帧。

所以先把「要一个专门的输入门闩」记在这里,等确认 SRT 读档后的实际时序(尤其读档完成 → 第一次按键之间到底有没有游戏更新)再单独提。如果希望现在就按「有输入才重开分支 + 超时兜底」写,我可以在这个 PR 里补。

行为边界(补:渐进式 BGM 与剪辑方向)

  • 蔚蓝的「配器加入/退出」是同一个音乐事件上的 FMOD 参数(Audio.SetMusicParam:progress/fade/escape/end/calm/boss_pitch),换曲才是 MusicTrigger/AltMusicTrigger。日志把换曲、start/stop/pause/seek 与每次参数变化都记下来(Source/MusicCapture.cs:25-32、:129-135),导出时逐 clip 重放:保留段内的变层点按源时刻重放(MusicEventReplayRenderer.cs:86-90、:150);clip 起点的初始状态取该源时间的最后一条 row(:77、:91-119)——落在被剪掉区间里的变层会在拼接点直接跳到当时状态,不做 ramp、不做层间淡入淡出。
  • clip 是「起点 + 时长」(Source/AutoRecorder.cs:844-857),边界时刻来自事件当时的采集时钟,即从每段起点往后量;唯一从后往前的是死亡回放的尾巴缓冲(CaptureRecentClips 逆序 + RetainTail,AutoRecorder.cs:899-911、Source/RecordingTimeline.cs:13-20)。RecordingBgmFollowsVideo 不决定方向,只决定 forceSync(MusicEventReplayRenderer.cs:74)。
  • 音频 sidecar 长度恒等于 Σ clip.DurationSeconds(MusicEventReplayRenderer.cs:20):比片尾长的音乐被截断、不补静音、不拉伸;源 PCM 丢块按时间戳留缺口(docs/capture-architecture.md:120)。所有边界以采集时钟为准,缺帧映射时退化到量化后的 TimeAt(Source/NativeRoomRecording.cs:64-75)。
  • 拼接点没有 BGM 去爆音:去爆音只作用于 SFX,event-rendered BGM 在那之后才混入(docs/capture-architecture.md:221-223)。

这些行为是哪来的(免得算到本 PR 头上)

时间 commit 内容
2026-08-23 6cefe74 init 录像骨架(AutoRecorder.cs、RecordingTimeline.cs 自仓库 init 即在)
2026-09-11 e9717ca 剪辑控制(剪辑总开关、保留暂停画面、保留失败尝试)
2026-09-11 71c77fe BGM 事件重放:forceSync、ApplyInitial、parameter 行重放(变层点按源时刻重放是这里就有的)
2026-10-15 1489942(本 PR) 只新增 RecordingBgmFollowsVideo(默认 false)+ UI 一行 + 测试,未改 MusicEventReplayRenderer.cs

验证

  • CELESTE_ROOT=<everest/lib-stripped> dotnet build Source/MicroblocksQolUtils.csproj -c Release:成功,0 warning。
  • dotnet run --project Tests/Recorder/Recorder.csproj -- <tmpdir>:162 checks 全绿(本地按已知的 harness 缺口补齐 Tests/Recorder/Stubs.cs 的 stub 后才能编过,这部分只留在本地工作区、不在本 PR 里;本 PR 对 Stubs.cs 只加了新设置字段那一行)。
  • Tests/Recording.Policy 新增 8 项检查(强制开启后普通/节奏房间都跟随、清掉开关后回到按房间判断),编译通过;本机无法运行:只有 lib-stripped(IL 被剥)和 Everest 打过补丁的 Celeste.dll,AreaKey.get_SID() 会抛 InvalidProgramException——master 上同样如此,不是本次改动引入的。
  • 本 PR diff:5 文件 +38/-2(Source/AutoRecorder.cs、Source/QolSettings.cs、Source/QolSettingsOverlay.cs、Tests/Recorder/Stubs.cs、Tests/Recording.Policy/Program.cs)。

…ng clip switches

The recorder already exposes the pause-screen and failed-attempt switches; the
BGM cursor was only pinned to source time for rhythm-sensitive rooms. This adds
an opt-in setting that pins every room's clips to the video, and a policy
regression test for it (plus a stub so the recorder harness still compiles).
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