From 3b42a0ae51e9399683a6236cda66ec0a9efe70a1 Mon Sep 17 00:00:00 2001 From: Aakarsh Singh Date: Thu, 13 Aug 2026 03:20:00 +0700 Subject: [PATCH] fix(rendering): drive keyboard overlay from recording_time so it follows cuts and start offset The keyboard overlay picked active segments with raw output time (frame_number / frame_rate) while keyboard events are stamped on the recording clock and video frames are mapped through the timeline. Result: overlays lag every recording by the encoder start offset (display.start_time, ~0.5s when the encoder is slow to start), and detach entirely after cuts or trims. Use segment_frames.recording_time instead - the same clock the cursor layer already uses - which travels with the decoded frame through get_frame_mapping and therefore follows cuts, trims and timescale, and includes the recording->first-frame offset. The parameter was already passed to prepare() and ignored. Related to #2115 (findings 3 in the report). Co-Authored-By: Claude Fable 5 --- crates/rendering/src/layers/keyboard.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/rendering/src/layers/keyboard.rs b/crates/rendering/src/layers/keyboard.rs index 97cf4206381..6269f1646fd 100644 --- a/crates/rendering/src/layers/keyboard.rs +++ b/crates/rendering/src/layers/keyboard.rs @@ -278,7 +278,7 @@ impl KeyboardLayer { pub fn prepare( &mut self, uniforms: &ProjectUniforms, - _segment_frames: &DecodedSegmentFrames, + segment_frames: &DecodedSegmentFrames, output_size: XY, constants: &RenderVideoConstants, caption_layout: Option, @@ -304,7 +304,12 @@ impl KeyboardLayer { return; } - let current_time = uniforms.frame_number as f64 / uniforms.frame_rate as f64; + // Keyboard segments are authored on the recording clock. Use the same + // clock the cursor layer uses: recording_time travels with the decoded + // frame through the timeline mapping, so the overlay follows cuts and + // trims, and includes the recording→first-video-frame start offset + // that raw output time (frame_number / frame_rate) lacks. + let current_time = segment_frames.recording_time as f64; let settings = &keyboard_data.settings; let active_segment = find_active_keyboard_segment(