Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
349 commits
Select commit Hold shift + click to select a range
e1fb5e4
improve: use keyed prefetch buffer for faster frame lookup
richiemcilroy Feb 13, 2026
3eacadb
improve: prune stale prefetched frames using ordered map
cursoragent Feb 13, 2026
9980169
improve: prune stale prefetched frames using ordered map
richiemcilroy Feb 13, 2026
bde144b
improve: include comparison gate status in published matrix summaries
cursoragent Feb 13, 2026
f2efab8
improve: include comparison gate status in published matrix summaries
richiemcilroy Feb 13, 2026
576f1fd
improve: tighten warmup timing and skip pruning in keyed prefetch path
cursoragent Feb 13, 2026
634e18f
improve: tighten warmup timing and skip pruning in keyed prefetch path
richiemcilroy Feb 13, 2026
ab756a9
improve: report candidate-only coverage in benchmark comparisons
cursoragent Feb 13, 2026
a0e2a17
improve: report candidate-only coverage in benchmark comparisons
richiemcilroy Feb 13, 2026
0a19cdb
improve: include candidate-only count in published comparison summary
cursoragent Feb 13, 2026
16f7170
improve: include candidate-only count in published comparison summary
richiemcilroy Feb 13, 2026
53f21e1
improve: add strict candidate-only gating for matrix comparisons
cursoragent Feb 13, 2026
7b8a79d
improve: add strict candidate-only gating for matrix comparisons
richiemcilroy Feb 13, 2026
0202484
improve: require contiguous prefetch coverage for warmup readiness
cursoragent Feb 13, 2026
9f94a26
improve: require contiguous prefetch coverage for warmup readiness
richiemcilroy Feb 13, 2026
b7652b7
improve: surface comparison coverage policies in published summaries
cursoragent Feb 13, 2026
b1b534e
improve: surface comparison coverage policies in published summaries
richiemcilroy Feb 13, 2026
af068d9
improve: emit finalize summary json artifacts for automation
cursoragent Feb 13, 2026
a7ad109
improve: emit finalize summary json artifacts for automation
richiemcilroy Feb 13, 2026
d6e0f6d
improve: optimize contiguous prefetch warmup scan
cursoragent Feb 13, 2026
e0dc3ef
improve: optimize contiguous prefetch warmup scan
richiemcilroy Feb 13, 2026
5fd803b
improve: include git metadata in finalize summary artifacts
cursoragent Feb 13, 2026
91055a8
improve: include git metadata in finalize summary artifacts
richiemcilroy Feb 13, 2026
ba37061
improve: publish finalize summary metadata in matrix reports
cursoragent Feb 13, 2026
c1e1f85
improve: publish finalize summary metadata in matrix reports
richiemcilroy Feb 13, 2026
1434554
improve: aggregate multi-run comparison metrics by key
cursoragent Feb 13, 2026
c332ada
improve: aggregate multi-run comparison metrics by key
richiemcilroy Feb 13, 2026
19b0083
improve: defer contiguous warmup scans until first frame arrival
cursoragent Feb 13, 2026
efc29ab
improve: defer contiguous warmup scans until first frame arrival
richiemcilroy Feb 13, 2026
cc1cd3f
improve: add minimum sample gating for benchmark comparisons
cursoragent Feb 13, 2026
7f15843
improve: add minimum sample gating for benchmark comparisons
richiemcilroy Feb 13, 2026
703e397
improve: cache warmup contiguous coverage between buffer updates
cursoragent Feb 13, 2026
bc1d20f
improve: cache warmup contiguous coverage between buffer updates
richiemcilroy Feb 13, 2026
766dabf
improve: expose comparison gate diagnostics for automation
cursoragent Feb 13, 2026
625efa6
improve: expose comparison gate diagnostics for automation
richiemcilroy Feb 13, 2026
87fa391
fix: apply minimum sample gating only to comparable metrics
cursoragent Feb 13, 2026
b911d5d
fix: apply minimum sample gating only to comparable metrics
richiemcilroy Feb 13, 2026
ee2c5a9
improve: include comparison diagnostics in finalize and publish summa…
cursoragent Feb 13, 2026
1b105c7
improve: include comparison diagnostics in finalize and publish summa…
richiemcilroy Feb 13, 2026
2fb1b74
improve: add parse-error gating and parse stats to matrix comparisons
cursoragent Feb 13, 2026
ffc84f2
improve: add parse-error gating and parse stats to matrix comparisons
richiemcilroy Feb 13, 2026
d770bc4
improve: invalidate warmup contiguous cache on structural buffer changes
cursoragent Feb 13, 2026
51f9832
improve: invalidate warmup contiguous cache on structural buffer changes
richiemcilroy Feb 13, 2026
35d5a5e
improve: include comparison file stats in finalize summary output
cursoragent Feb 13, 2026
3f99687
improve: include comparison file stats in finalize summary output
richiemcilroy Feb 13, 2026
33f15fe
improve: stabilize comparison artifact ordering for reproducibility
cursoragent Feb 13, 2026
59ef247
improve: stabilize comparison artifact ordering for reproducibility
richiemcilroy Feb 13, 2026
9fadd0f
improve: add comparison count rollups to finalize summaries
cursoragent Feb 13, 2026
c87ca9e
improve: add comparison count rollups to finalize summaries
richiemcilroy Feb 13, 2026
05bbd0a
improve: add optional zero-comparison gating for matrix compare flows
cursoragent Feb 13, 2026
8048eb1
improve: add optional zero-comparison gating for matrix compare flows
richiemcilroy Feb 13, 2026
6bc816e
improve: handle seek updates during playback warmup
cursoragent Feb 13, 2026
46413ab
improve: handle seek updates during playback warmup
richiemcilroy Feb 13, 2026
1b7a2a5
improve: add skipped-file gating for comparison workflows
cursoragent Feb 13, 2026
7567a1f
improve: add skipped-file gating for comparison workflows
richiemcilroy Feb 13, 2026
baace4f
improve: add skipped-file reason breakdown to comparison diagnostics
cursoragent Feb 13, 2026
e98a64e
improve: add skipped-file reason breakdown to comparison diagnostics
richiemcilroy Feb 13, 2026
fa6d23a
improve: scale warmup idle polling with frame budget
cursoragent Feb 13, 2026
b2c8a7d
improve: scale warmup idle polling with frame budget
richiemcilroy Feb 13, 2026
297b9b4
improve: avoid duplicate prefetch decodes on small rebases
cursoragent Feb 13, 2026
ff55bcf
improve: avoid duplicate prefetch decodes on small rebases
richiemcilroy Feb 13, 2026
68a0128
improve: reduce prefetch lock contention with local inflight tracking
cursoragent Feb 13, 2026
f19a985
improve: reduce prefetch lock contention with local inflight tracking
richiemcilroy Feb 13, 2026
2b2ea79
improve: batch warmup prefetch queue consumption
cursoragent Feb 13, 2026
ed3efe5
improve: batch warmup prefetch queue consumption
richiemcilroy Feb 13, 2026
0965dec
improve: scale prefetch idle polling with frame budget
cursoragent Feb 13, 2026
ba334da
improve: scale prefetch idle polling with frame budget
richiemcilroy Feb 13, 2026
c801652
improve: bound behind-prefetch dedupe tracking window
cursoragent Feb 13, 2026
e4a5319
improve: bound behind-prefetch dedupe tracking window
richiemcilroy Feb 13, 2026
3fcb14e
improve: switch editor playback to streaming audio and live seek
richiemcilroy Feb 13, 2026
796e617
improve: lazy-initialize avassetreader pool and refresh findings
richiemcilroy Feb 13, 2026
b2b4804
improve: add scrub and startup metrics to playback benchmark
richiemcilroy Feb 13, 2026
eea5e69
docs: add cross-platform playback benchmark matrix
richiemcilroy Feb 13, 2026
97bd11c
improve: add playback startup latency telemetry logs
richiemcilroy Feb 13, 2026
127f727
improve: extend decode benchmark with json startup metrics
richiemcilroy Feb 13, 2026
a848479
improve: support fragmented inputs in decode benchmark
richiemcilroy Feb 13, 2026
232608d
improve: coalesce timeline seek commands during scrubbing
richiemcilroy Feb 13, 2026
0f6795e
improve: clean up scheduled timeline raf tasks on unmount
richiemcilroy Feb 13, 2026
42017c5
improve: add json export support to playback benchmark runner
richiemcilroy Feb 13, 2026
b459535
improve: add playback benchmark json aggregation script
richiemcilroy Feb 13, 2026
fd2b6c7
improve: use latest-only watch channel for playback seeks
richiemcilroy Feb 13, 2026
bf7aa98
improve: add matrix helper for playback benchmark runs
richiemcilroy Feb 13, 2026
5995626
docs: add playback matrix runbook for hardware validation
richiemcilroy Feb 13, 2026
1370bd6
improve: add playback matrix coverage validation script
richiemcilroy Feb 13, 2026
59d1e6f
improve: include full runner context in benchmark command metadata
richiemcilroy Feb 13, 2026
e30027f
improve: add playback benchmark npm aliases and cli passthrough
richiemcilroy Feb 13, 2026
bcbb5f4
improve: drop duplicate same-frame seek updates
richiemcilroy Feb 13, 2026
bed0925
improve: validate per-machine matrix runs in helper script
richiemcilroy Feb 13, 2026
3ca8913
improve: emit matrix validation json artifacts
richiemcilroy Feb 13, 2026
43db499
improve: emit seek settle telemetry in playback loop
richiemcilroy Feb 13, 2026
225de24
improve: add playback matrix status report generator
richiemcilroy Feb 13, 2026
b7d0737
improve: support scenario subset runs in matrix helper
richiemcilroy Feb 13, 2026
8fe2d5a
improve: add one-shot playback matrix finalization command
richiemcilroy Feb 13, 2026
055cf42
improve: add matrix artifact publisher into benchmark history
richiemcilroy Feb 13, 2026
ed40518
improve: tune frame wait and add startup threshold checks
richiemcilroy Feb 13, 2026
afa9ea5
improve: add matrix bottleneck analysis for fps optimization
richiemcilroy Feb 13, 2026
d83dc86
improve: scale playback frame polling with frame budget
richiemcilroy Feb 13, 2026
79dd6d6
improve: include bottleneck analysis in matrix finalization
richiemcilroy Feb 13, 2026
a5ef5aa
improve: adapt playback catch-up skipping to sustained lag
richiemcilroy Feb 13, 2026
34f45b5
improve: allow bottleneck attachment in matrix summary publishing
richiemcilroy Feb 13, 2026
f9e371c
improve: scale playback warmup buffering with fps
richiemcilroy Feb 13, 2026
56235f5
improve: support publish-target in matrix finalization
richiemcilroy Feb 13, 2026
3c4e004
improve: scale prefetch windows with playback fps
richiemcilroy Feb 13, 2026
78b1266
improve: emit structured bottleneck artifacts in matrix analysis
richiemcilroy Feb 13, 2026
2b7ae23
improve: scale prefetch decode parallelism for high-fps playback
richiemcilroy Feb 13, 2026
df142fc
improve: skip no-op playhead state updates in tauri commands
richiemcilroy Feb 13, 2026
2afdbd6
improve: add baseline comparison gating for playback benchmarks
richiemcilroy Feb 13, 2026
5b1807c
improve: discard stale prefetched frames after live seeks
richiemcilroy Feb 13, 2026
baba6e6
improve: clear prefetched buffer immediately on live seek
richiemcilroy Feb 13, 2026
43f298d
improve: avoid buffering stale prefetched frames behind playhead
richiemcilroy Feb 13, 2026
4becc57
improve: support multi-input benchmark comparison gating
richiemcilroy Feb 13, 2026
bee50f5
improve: add baseline compare gate to matrix finalization
richiemcilroy Feb 13, 2026
61d10d7
improve: key in-flight frame tracking by seek generation
richiemcilroy Feb 13, 2026
d140e69
improve: publish baseline comparison artifacts in matrix summaries
richiemcilroy Feb 13, 2026
9b4e9b9
improve: separate prefetch and decode in-flight tracking
richiemcilroy Feb 13, 2026
7b26c21
improve: gate benchmark comparisons on candidate coverage gaps
richiemcilroy Feb 13, 2026
65148e5
improve: run finalize comparison before publish attachment
richiemcilroy Feb 13, 2026
e6a5548
improve: emit structured comparison artifacts for matrix gating
richiemcilroy Feb 13, 2026
6924c38
improve: use keyed prefetch buffer for faster frame lookup
richiemcilroy Feb 13, 2026
5498a51
improve: prune stale prefetched frames using ordered map
richiemcilroy Feb 13, 2026
75add0b
improve: include comparison gate status in published matrix summaries
richiemcilroy Feb 13, 2026
b13aa6c
improve: tighten warmup timing and skip pruning in keyed prefetch path
richiemcilroy Feb 13, 2026
56557c2
improve: report candidate-only coverage in benchmark comparisons
richiemcilroy Feb 13, 2026
1cd997c
improve: include candidate-only count in published comparison summary
richiemcilroy Feb 13, 2026
ae13562
improve: add strict candidate-only gating for matrix comparisons
richiemcilroy Feb 13, 2026
dc516ba
improve: require contiguous prefetch coverage for warmup readiness
richiemcilroy Feb 13, 2026
47d7947
improve: surface comparison coverage policies in published summaries
richiemcilroy Feb 13, 2026
25435cf
improve: emit finalize summary json artifacts for automation
richiemcilroy Feb 13, 2026
afbd5d1
improve: optimize contiguous prefetch warmup scan
richiemcilroy Feb 13, 2026
3effc17
improve: include git metadata in finalize summary artifacts
richiemcilroy Feb 13, 2026
9c465a6
improve: publish finalize summary metadata in matrix reports
richiemcilroy Feb 13, 2026
4455c5f
improve: aggregate multi-run comparison metrics by key
richiemcilroy Feb 13, 2026
4896872
improve: defer contiguous warmup scans until first frame arrival
richiemcilroy Feb 13, 2026
4860d74
improve: add minimum sample gating for benchmark comparisons
richiemcilroy Feb 13, 2026
f4a3cb8
improve: cache warmup contiguous coverage between buffer updates
richiemcilroy Feb 13, 2026
4bbfa59
improve: expose comparison gate diagnostics for automation
richiemcilroy Feb 13, 2026
0d6f995
fix: apply minimum sample gating only to comparable metrics
richiemcilroy Feb 13, 2026
913e6fd
improve: include comparison diagnostics in finalize and publish summa…
richiemcilroy Feb 13, 2026
2219362
improve: add parse-error gating and parse stats to matrix comparisons
richiemcilroy Feb 13, 2026
b05da47
improve: invalidate warmup contiguous cache on structural buffer changes
richiemcilroy Feb 13, 2026
63ba3f6
improve: include comparison file stats in finalize summary output
richiemcilroy Feb 13, 2026
7f0778b
improve: stabilize comparison artifact ordering for reproducibility
richiemcilroy Feb 13, 2026
f12e5c5
improve: add comparison count rollups to finalize summaries
richiemcilroy Feb 13, 2026
5d56b00
improve: add optional zero-comparison gating for matrix compare flows
richiemcilroy Feb 13, 2026
3d20258
improve: handle seek updates during playback warmup
richiemcilroy Feb 13, 2026
cd2f465
improve: add skipped-file gating for comparison workflows
richiemcilroy Feb 13, 2026
fbc5fe4
improve: add skipped-file reason breakdown to comparison diagnostics
richiemcilroy Feb 13, 2026
16550d2
improve: scale warmup idle polling with frame budget
richiemcilroy Feb 13, 2026
eae4930
improve: avoid duplicate prefetch decodes on small rebases
richiemcilroy Feb 13, 2026
7e368c6
Merge origin/cursor/playback-performance-and-sync-dec3
richiemcilroy Feb 13, 2026
58d2fb5
Merge origin/cursor/playback-performance-and-sync-dec3
richiemcilroy Feb 13, 2026
2215938
improve: cache clip-offset lookups in decode scheduling
cursoragent Feb 13, 2026
7ca0f42
improve: cache clip-offset lookups in decode scheduling
richiemcilroy Feb 13, 2026
8ebe171
improve: cache clip-offset lookups in decode scheduling
richiemcilroy Feb 13, 2026
e9f609f
improve: add clear() method to FrameCache for better encapsulation
richiemcilroy Feb 13, 2026
39f9465
improve: add clear() method to FrameCache for better encapsulation
richiemcilroy Feb 13, 2026
51df1ca
fix: use saturating_add in trim_prefetch_buffer to prevent overflow
richiemcilroy Feb 13, 2026
2b600a3
fix: use saturating_add in trim_prefetch_buffer to prevent overflow
richiemcilroy Feb 13, 2026
246fd2e
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
20bf8ce
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
179984a
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
caa8771
fix: make AudioResampler::reset() non-panicking
richiemcilroy Feb 13, 2026
9f110e4
fix: make AudioResampler::reset() non-panicking
richiemcilroy Feb 13, 2026
d03cf49
fix: make AudioResampler::reset() non-panicking
richiemcilroy Feb 13, 2026
af1de59
fix: clamp targetFrame to prevent out-of-range seekTo during timeline…
richiemcilroy Feb 13, 2026
684b0ed
fix: clamp targetFrame to prevent out-of-range seekTo during timeline…
richiemcilroy Feb 13, 2026
78eb47d
fix: clamp targetFrame to prevent out-of-range seekTo during timeline…
richiemcilroy Feb 13, 2026
0ab9cda
fix: cap dynamic_prefetch_ahead to PREFETCH_BUFFER_SIZE to avoid wast…
richiemcilroy Feb 13, 2026
3149a66
fix: cap dynamic_prefetch_ahead to PREFETCH_BUFFER_SIZE to avoid wast…
richiemcilroy Feb 13, 2026
9f4d607
fix: cap dynamic_prefetch_ahead to PREFETCH_BUFFER_SIZE to avoid wast…
richiemcilroy Feb 13, 2026
18a0d7d
fix: escape backslashes and pipes in markdown table cells for CI repo…
richiemcilroy Feb 13, 2026
cc9c79f
fix: escape backslashes and pipes in markdown table cells for CI repo…
richiemcilroy Feb 13, 2026
9b9335c
fix: escape backslashes and pipes in markdown table cells for CI repo…
richiemcilroy Feb 13, 2026
c62eec6
fix: rename skipped_no_metrics to skipped_no_usable_metrics for consi…
richiemcilroy Feb 13, 2026
fea600f
fix: rename skipped_no_metrics to skipped_no_usable_metrics for consi…
richiemcilroy Feb 13, 2026
67f58a2
fix: rename skipped_no_metrics to skipped_no_usable_metrics for consi…
richiemcilroy Feb 13, 2026
59892cf
improve: dedupe playback frame-request watch updates
cursoragent Feb 13, 2026
ba37eb3
improve: dedupe playback frame-request watch updates
richiemcilroy Feb 13, 2026
8da4cbf
improve: dedupe playback frame-request watch updates
richiemcilroy Feb 13, 2026
f0e7760
improve: avoid duplicate keyed lookups on prefetch insert
cursoragent Feb 13, 2026
35c5a41
improve: avoid duplicate keyed lookups on prefetch insert
richiemcilroy Feb 13, 2026
6461262
improve: avoid duplicate keyed lookups on prefetch insert
richiemcilroy Feb 13, 2026
2fd740e
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
83da539
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
cfa718f
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
99a1063
fmt
richiemcilroy Feb 14, 2026
45059ca
fmt
richiemcilroy Feb 14, 2026
81ad88a
fmt
richiemcilroy Feb 14, 2026
baacc39
improve: centralize change-aware frame request signaling
cursoragent Feb 14, 2026
45265df
improve: centralize change-aware frame request signaling
richiemcilroy Feb 14, 2026
a8abcf5
improve: centralize change-aware frame request signaling
richiemcilroy Feb 14, 2026
4a94a8d
improve: short-circuit frame waits when seeks are pending
cursoragent Feb 14, 2026
3664636
improve: short-circuit frame waits when seeks are pending
richiemcilroy Feb 14, 2026
12a4a2f
improve: short-circuit frame waits when seeks are pending
richiemcilroy Feb 14, 2026
a846a89
improve: skip stale waits and decode fallback on pending seeks
cursoragent Feb 14, 2026
e8a0910
improve: skip stale waits and decode fallback on pending seeks
richiemcilroy Feb 14, 2026
8f2d0e5
improve: skip stale waits and decode fallback on pending seeks
richiemcilroy Feb 14, 2026
55df9a5
improve: batch prefetch buffer trims during queue drains
cursoragent Feb 14, 2026
f87f62e
improve: batch prefetch buffer trims during queue drains
richiemcilroy Feb 14, 2026
0ddd232
improve: batch prefetch buffer trims during queue drains
richiemcilroy Feb 14, 2026
4766b55
improve: preserve prefetch ramp on small forward rebases
cursoragent Feb 14, 2026
cc18f5a
improve: preserve prefetch ramp on small forward rebases
richiemcilroy Feb 14, 2026
6cd720a
improve: preserve prefetch ramp on small forward rebases
richiemcilroy Feb 14, 2026
a8d52a5
improve: gate behind-prefetch scans per playback frame
cursoragent Feb 14, 2026
004e281
improve: gate behind-prefetch scans per playback frame
richiemcilroy Feb 14, 2026
5ddf604
improve: gate behind-prefetch scans per playback frame
richiemcilroy Feb 14, 2026
1a12a55
improve: dedupe playback frame-request watch updates
richiemcilroy Feb 13, 2026
c8cccf0
fix: escape backslashes and pipes in markdown table cells for CI repo…
richiemcilroy Feb 13, 2026
09f2b57
improve: dedupe playback frame-request watch updates
richiemcilroy Feb 13, 2026
6ce10a3
fix: escape backslashes and pipes in markdown table cells for CI repo…
richiemcilroy Feb 13, 2026
21c57c9
improve: dedupe playback frame-request watch updates
richiemcilroy Feb 13, 2026
796e839
fix: escape backslashes and pipes in markdown table cells for CI repo…
richiemcilroy Feb 13, 2026
9673152
improve: avoid duplicate keyed lookups on prefetch insert
richiemcilroy Feb 13, 2026
74fe6c8
fix: rename skipped_no_metrics to skipped_no_usable_metrics for consi…
richiemcilroy Feb 13, 2026
358812a
improve: avoid duplicate keyed lookups on prefetch insert
richiemcilroy Feb 13, 2026
9331188
fix: rename skipped_no_metrics to skipped_no_usable_metrics for consi…
richiemcilroy Feb 13, 2026
34b063d
improve: avoid duplicate keyed lookups on prefetch insert
richiemcilroy Feb 13, 2026
e52e799
fix: rename skipped_no_metrics to skipped_no_usable_metrics for consi…
richiemcilroy Feb 13, 2026
b6d0506
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
f9a2ed9
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
472e79c
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 13, 2026
ade9d8b
fmt
richiemcilroy Feb 14, 2026
d797e3f
fmt
richiemcilroy Feb 14, 2026
dc7d73e
fmt
richiemcilroy Feb 14, 2026
e808b16
improve: centralize change-aware frame request signaling
richiemcilroy Feb 14, 2026
e34446b
improve: centralize change-aware frame request signaling
richiemcilroy Feb 14, 2026
27dd799
improve: centralize change-aware frame request signaling
richiemcilroy Feb 14, 2026
d53082b
improve: short-circuit frame waits when seeks are pending
richiemcilroy Feb 14, 2026
ee3ee2d
improve: short-circuit frame waits when seeks are pending
richiemcilroy Feb 14, 2026
5e8ffd6
improve: short-circuit frame waits when seeks are pending
richiemcilroy Feb 14, 2026
51044cf
improve: skip stale waits and decode fallback on pending seeks
richiemcilroy Feb 14, 2026
7f796ff
improve: skip stale waits and decode fallback on pending seeks
richiemcilroy Feb 14, 2026
3c81ece
improve: skip stale waits and decode fallback on pending seeks
richiemcilroy Feb 14, 2026
75892b7
improve: batch prefetch buffer trims during queue drains
richiemcilroy Feb 14, 2026
09e8307
improve: batch prefetch buffer trims during queue drains
richiemcilroy Feb 14, 2026
dad0f79
improve: batch prefetch buffer trims during queue drains
richiemcilroy Feb 14, 2026
94fdebe
improve: preserve prefetch ramp on small forward rebases
richiemcilroy Feb 14, 2026
09bb2f0
improve: preserve prefetch ramp on small forward rebases
richiemcilroy Feb 14, 2026
6d0b272
improve: preserve prefetch ramp on small forward rebases
richiemcilroy Feb 14, 2026
6b4f0c9
improve: gate behind-prefetch scans per playback frame
richiemcilroy Feb 14, 2026
4beb9af
improve: gate behind-prefetch scans per playback frame
richiemcilroy Feb 14, 2026
c6e1116
improve: gate behind-prefetch scans per playback frame
richiemcilroy Feb 14, 2026
d632a0f
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 14, 2026
83cfbad
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 14, 2026
2788856
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 14, 2026
fbcd20e
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 14, 2026
6e05540
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 14, 2026
977414e
improve: batch prefetch trims in in-flight wait buffering
cursoragent Feb 14, 2026
1fea346
improve: batch prefetch trims in in-flight wait buffering
richiemcilroy Feb 14, 2026
0cbac24
Merge branch 'cursor/playback-performance-and-sync-dec3' of https://g…
richiemcilroy Feb 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 46 additions & 10 deletions apps/desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1915,11 +1915,29 @@ async fn set_playhead_position(
editor_instance: WindowEditorInstance,
frame_number: u32,
) -> Result<(), String> {
editor_instance
.modify_and_emit_state(|state| {
state.playhead_position = frame_number;
})
.await;
let state_changed = {
let state = editor_instance.state.lock().await;
state.playhead_position != frame_number
};

if state_changed {
editor_instance
.modify_and_emit_state(|state| {
state.playhead_position = frame_number;
})
.await;
}
Comment on lines +1918 to +1929
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

locks state twice (lines 1919, 1932) - second lock held during seek() call which may briefly block - consider reading both playhead_position and playback_task in single lock scope to reduce hold time

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src-tauri/src/lib.rs
Line: 1918:1929

Comment:
locks `state` twice (lines 1919, 1932) - second lock held during `seek()` call which may briefly block - consider reading both `playhead_position` and `playback_task` in single lock scope to reduce hold time

How can I resolve this? If you propose a fix, please make it concise.


let playback_handle = if state_changed {
let state = editor_instance.state.lock().await;
state.playback_task.clone()
} else {
None
};

if let Some(handle) = playback_handle {
handle.seek(frame_number);
}

Ok(())
}
Expand Down Expand Up @@ -2539,11 +2557,29 @@ async fn is_camera_window_open(app: AppHandle) -> bool {
#[specta::specta]
#[instrument(skip(editor_instance))]
async fn seek_to(editor_instance: WindowEditorInstance, frame_number: u32) -> Result<(), String> {
editor_instance
.modify_and_emit_state(|state| {
state.playhead_position = frame_number;
})
.await;
let state_changed = {
let state = editor_instance.state.lock().await;
state.playhead_position != frame_number
};

if state_changed {
editor_instance
.modify_and_emit_state(|state| {
state.playhead_position = frame_number;
})
.await;
}

let playback_handle = if state_changed {
let state = editor_instance.state.lock().await;
state.playback_task.clone()
} else {
None
};

if let Some(handle) = playback_handle {
handle.seek(frame_number);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seek dedupe uses stale state

Medium Severity

seek_to and set_playhead_position now skip handle.seek(...) when state.playhead_position already equals frame_number. But playhead_position is not advanced by playback frames, so it can be stale. This drops valid seeks to a previously requested frame while playback has moved, making scrubbing/rewind requests intermittently ignored.

Additional Locations (1)

Fix in Cursor Fix in Web


Ok(())
}
Expand Down
85 changes: 60 additions & 25 deletions apps/desktop/src/routes/editor/Timeline/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
createSignal,
Index,
type JSX,
onCleanup,
onMount,
Show,
} from "solid-js";
Expand Down Expand Up @@ -89,7 +90,6 @@ export function Timeline() {
editorState,
projectActions,
meta,
previewResolutionBase,
} = useEditorContext();

const duration = () => editorInstance.recordingDuration;
Expand Down Expand Up @@ -221,6 +221,17 @@ export function Timeline() {

let pendingScrollDelta = 0;
let scrollRafId: number | null = null;
let pendingSeekFrame: number | null = null;
let seekRafId: number | null = null;
let seekInFlight = false;
let inFlightSeekFrame: number | null = null;
let lastCompletedSeekFrame: number | null = null;

onCleanup(() => {
if (zoomRafId !== null) cancelAnimationFrame(zoomRafId);
if (scrollRafId !== null) cancelAnimationFrame(scrollRafId);
if (seekRafId !== null) cancelAnimationFrame(seekRafId);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unmount doesn’t cancel pending seek pipeline

Low Severity

onCleanup only cancels current RAF IDs, but it does not invalidate flushPendingSeek while an async commands.seekTo is in flight. After unmount, the finally block can schedule another RAF and continue issuing seeks from a disposed Timeline instance.

Additional Locations (1)

Fix in Cursor Fix in Web


function flushPendingZoom() {
if (pendingZoomDelta === 0 || pendingZoomOrigin === null) {
Expand Down Expand Up @@ -266,41 +277,65 @@ export function Timeline() {
}
}

async function handleUpdatePlayhead(e: MouseEvent) {
function scheduleSeek(frameNumber: number) {
if (
frameNumber === pendingSeekFrame ||
frameNumber === inFlightSeekFrame ||
frameNumber === lastCompletedSeekFrame
) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seek dedupe blocks valid repeat seeks

Medium Severity

scheduleSeek drops requests when frameNumber === lastCompletedSeekFrame. Because lastCompletedSeekFrame is never cleared on normal playback progress, a later seek back to a previously completed frame can be ignored even after the playhead moved away. This makes timeline scrubbing intermittently no-op in Timeline/index.tsx.

Additional Locations (1)

Fix in Cursor Fix in Web

return;
}
pendingSeekFrame = frameNumber;
if (seekRafId === null) {
seekRafId = requestAnimationFrame(flushPendingSeek);
}
}
Comment on lines +280 to +292
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deduplicates seeks against lastCompletedSeekFrame which is only set on success (line 311) - if seekTo throws (line 313), lastCompletedSeekFrame stays stale, and retrying the same frame later gets incorrectly rejected as duplicate on line 284

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/routes/editor/Timeline/index.tsx
Line: 280:292

Comment:
deduplicates seeks against `lastCompletedSeekFrame` which is only set on success (line 311) - if `seekTo` throws (line 313), `lastCompletedSeekFrame` stays stale, and retrying the same frame later gets incorrectly rejected as duplicate on line 284

How can I resolve this? If you propose a fix, please make it concise.


async function flushPendingSeek() {
seekRafId = null;

if (seekInFlight || pendingSeekFrame === null) {
if (pendingSeekFrame !== null && seekRafId === null) {
seekRafId = requestAnimationFrame(flushPendingSeek);
}
return;
}

const frameNumber = pendingSeekFrame;
pendingSeekFrame = null;
seekInFlight = true;
inFlightSeekFrame = frameNumber;

try {
await commands.seekTo(frameNumber);
lastCompletedSeekFrame = frameNumber;
} catch (err) {
console.error("Failed to seek timeline playhead:", err);
} finally {
seekInFlight = false;
inFlightSeekFrame = null;
if (pendingSeekFrame !== null && seekRafId === null) {
seekRafId = requestAnimationFrame(flushPendingSeek);
}
}
}

function handleUpdatePlayhead(e: MouseEvent) {
const { left } = timelineBounds;
if (
zoomSegmentDragState.type !== "moving" &&
sceneSegmentDragState.type !== "moving" &&
maskSegmentDragState.type !== "moving" &&
textSegmentDragState.type !== "moving"
) {
// Guard against missing bounds and clamp computed time to [0, totalDuration()]
if (left == null) return;
const rawTime =
secsPerPixel() * (e.clientX - left) + transform().position;
const newTime = Math.min(Math.max(0, rawTime), totalDuration());

// If playing, some backends require restart to seek reliably
if (editorState.playing) {
try {
await commands.stopPlayback();

// Round to nearest frame to prevent off-by-one drift
const targetFrame = Math.round(newTime * FPS);
await commands.seekTo(targetFrame);

// If the user paused during these async ops, bail out without restarting
if (!editorState.playing) {
setEditorState("playbackTime", newTime);
return;
}

await commands.startPlayback(FPS, previewResolutionBase());
setEditorState("playing", true);
} catch (err) {
console.error("Failed to seek during playback:", err);
}
}
const total = totalDuration();
const maxFrame = Math.max(0, Math.ceil(total * FPS) - 1);
Comment on lines 334 to +336
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: totalDuration() is called twice here. Using the computed total for the clamp keeps it consistent and avoids the extra call.

Suggested change
const newTime = Math.min(Math.max(0, rawTime), totalDuration());
// If playing, some backends require restart to seek reliably
if (editorState.playing) {
try {
await commands.stopPlayback();
// Round to nearest frame to prevent off-by-one drift
const targetFrame = Math.round(newTime * FPS);
await commands.seekTo(targetFrame);
// If the user paused during these async ops, bail out without restarting
if (!editorState.playing) {
setEditorState("playbackTime", newTime);
return;
}
await commands.startPlayback(FPS, previewResolutionBase());
setEditorState("playing", true);
} catch (err) {
console.error("Failed to seek during playback:", err);
}
}
const total = totalDuration();
const maxFrame = Math.max(0, Math.ceil(total * FPS) - 1);
const total = totalDuration();
const newTime = Math.min(Math.max(0, rawTime), total);
const maxFrame = Math.max(0, Math.ceil(total * FPS) - 1);

const targetFrame = Math.min(Math.round(newTime * FPS), maxFrame);
scheduleSeek(targetFrame);

setEditorState("playbackTime", newTime);
}
Expand Down
1 change: 1 addition & 0 deletions crates/editor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ axum = { version = "0.7.5", features = ["ws"] }
ffmpeg.workspace = true
specta.workspace = true
serde = { workspace = true }
serde_json = "1"
sentry.workspace = true
futures = { workspace = true }
tracing.workspace = true
Expand Down
112 changes: 112 additions & 0 deletions crates/editor/PLAYBACK-BENCHMARKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ This document tracks performance benchmarks for Cap's playback and decoding syst
|--------|--------|-----------|
| Decoder Init | <200ms | - |
| Decode Latency (p95) | <50ms | - |
| Startup to First Frame | <250ms | configurable |
| Effective FPS | ≥30 fps | ±2 fps |
| Decode Jitter | <10ms | - |
| Scrub Seek Latency (p95) | <40ms | - |
| A/V Sync (mic↔video) | <100ms | - |
| A/V Sync (system↔video) | <100ms | - |
| Camera-Display Drift | <100ms | - |
Expand All @@ -20,6 +22,7 @@ This document tracks performance benchmarks for Cap's playback and decoding syst

- **Decoder Tests**: Init time, hardware acceleration detection, fallback handling
- **Playback Tests**: Sequential decode, frame retrieval, latency percentiles
- **Scrub Tests**: Random access seek decode latency and seek failure rate
- **Audio Sync Tests**: Mic-video sync, system audio-video sync
- **Camera Sync Tests**: Camera-display drift, frame count alignment
- **Decode Benchmark**: Creation, sequential, seek, and random access performance
Expand All @@ -40,10 +43,12 @@ This document tracks performance benchmarks for Cap's playback and decoding syst
```bash
# Run full playback validation on recordings from real-device-test-runner
cargo run -p cap-recording --example playback-test-runner -- full
cargo run -p cap-recording --example playback-test-runner -- full --startup-threshold-ms 250

# Run specific test categories
cargo run -p cap-recording --example playback-test-runner -- decoder
cargo run -p cap-recording --example playback-test-runner -- playback
cargo run -p cap-recording --example playback-test-runner -- scrub
cargo run -p cap-recording --example playback-test-runner -- audio-sync
cargo run -p cap-recording --example playback-test-runner -- camera-sync

Expand All @@ -52,6 +57,69 @@ cargo run -p cap-recording --example playback-test-runner -- --recording-path /p

# List available recordings
cargo run -p cap-recording --example playback-test-runner -- list

# Emit machine-readable JSON report
cargo run -p cap-recording --example playback-test-runner -- full --json-output /tmp/playback-benchmark.json
```

Aggregate JSON outputs from multiple machines:

```bash
node scripts/aggregate-playback-benchmarks.js --input /path/to/json-results --output /tmp/playback-benchmark-aggregate.md
node scripts/build-playback-matrix-report.js --input /path/to/json-results --output /tmp/playback-matrix-status.md
```

Validate matrix coverage and required formats:

```bash
node scripts/validate-playback-matrix.js --input /path/to/json-results --require-formats mp4,fragmented
node scripts/validate-playback-matrix.js --input /path/to/json-results --require-formats mp4,fragmented --output-json /tmp/playback-matrix-validation.json

# Finalize aggregate + status + validation artifacts
node scripts/finalize-playback-matrix.js --input /path/to/json-results --output-dir /tmp/playback-matrix-final --require-formats mp4,fragmented
node scripts/finalize-playback-matrix.js --input /path/to/json-results --output-dir /tmp/playback-matrix-final --require-formats mp4,fragmented --target-fps 60 --max-scrub-p95-ms 40 --max-startup-ms 250
node scripts/finalize-playback-matrix.js --input /path/to/candidate-results --output-dir /tmp/playback-matrix-final --compare-baseline /path/to/baseline-results --allow-fps-drop 2 --allow-startup-increase-ms 25 --allow-scrub-p95-increase-ms 5
node scripts/finalize-playback-matrix.js --input /path/to/candidate-results --output-dir /tmp/playback-matrix-final --compare-baseline /path/to/baseline-results --allow-missing-candidate
node scripts/finalize-playback-matrix.js --input /path/to/candidate-results --output-dir /tmp/playback-matrix-final --compare-baseline /path/to/baseline-results --fail-on-candidate-only
node scripts/finalize-playback-matrix.js --input /path/to/candidate-results --output-dir /tmp/playback-matrix-final --compare-baseline /path/to/baseline-results --min-samples-per-row 3
node scripts/finalize-playback-matrix.js --input /path/to/candidate-results --output-dir /tmp/playback-matrix-final --compare-baseline /path/to/baseline-results --fail-on-parse-errors
node scripts/finalize-playback-matrix.js --input /path/to/candidate-results --output-dir /tmp/playback-matrix-final --compare-baseline /path/to/baseline-results --fail-on-zero-compared
node scripts/finalize-playback-matrix.js --input /path/to/candidate-results --output-dir /tmp/playback-matrix-final --compare-baseline /path/to/baseline-results --fail-on-skipped-files
node scripts/finalize-playback-matrix.js --input /path/to/json-results --output-dir /tmp/playback-matrix-final --output-json /tmp/playback-matrix-final/playback-finalize-summary.json
node scripts/finalize-playback-matrix.js --input /path/to/json-results --output-dir /tmp/playback-matrix-final --require-formats mp4,fragmented --target-fps 60 --max-scrub-p95-ms 40 --max-startup-ms 250 --publish-target /workspace/crates/editor/PLAYBACK-BENCHMARKS.md

Finalize summary JSON includes generated timestamp, artifact paths, settings, pass/fail flags, and git branch/commit metadata when available.
Finalize summary JSON also carries comparison failure reasons and gate outcomes when comparison is enabled.
Finalize summary JSON includes comparison file stats (including parse error counts) when comparison is enabled.
Finalize summary JSON includes comparison summary counts (compared rows, regressions, missing/candidate-only/insufficient-sample counts) when comparison is enabled.

# Publish matrix artifacts into this benchmark history
node scripts/publish-playback-matrix-summary.js --aggregate-md /tmp/playback-matrix-final/playback-benchmark-aggregate.md --status-md /tmp/playback-matrix-final/playback-matrix-status.md --validation-json /tmp/playback-matrix-final/playback-matrix-validation.json --bottlenecks-md /tmp/playback-matrix-final/playback-bottlenecks.md
node scripts/publish-playback-matrix-summary.js --aggregate-md /tmp/playback-matrix-final/playback-benchmark-aggregate.md --status-md /tmp/playback-matrix-final/playback-matrix-status.md --validation-json /tmp/playback-matrix-final/playback-matrix-validation.json --comparison-md /tmp/playback-matrix-final/playback-comparison.md --comparison-json /tmp/playback-matrix-final/playback-comparison.json
node scripts/publish-playback-matrix-summary.js --aggregate-md /tmp/playback-matrix-final/playback-benchmark-aggregate.md --status-md /tmp/playback-matrix-final/playback-matrix-status.md --validation-json /tmp/playback-matrix-final/playback-matrix-validation.json --finalize-summary-json /tmp/playback-matrix-final/playback-finalize-summary.json

# Analyze bottlenecks from matrix results
node scripts/analyze-playback-matrix-bottlenecks.js --input /path/to/json-results --output /tmp/playback-bottlenecks.md --target-fps 60 --max-scrub-p95-ms 40 --max-startup-ms 250
node scripts/analyze-playback-matrix-bottlenecks.js --input /path/to/json-results --output /tmp/playback-bottlenecks.md --output-json /tmp/playback-bottlenecks.json --target-fps 60 --max-scrub-p95-ms 40 --max-startup-ms 250

# Compare candidate against baseline and flag regressions
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --output /tmp/playback-comparison.md --allow-fps-drop 2 --allow-startup-increase-ms 25 --allow-scrub-p95-increase-ms 5
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results-a --baseline /path/to/baseline-results-b --candidate /path/to/candidate-results-a --candidate /path/to/candidate-results-b --output /tmp/playback-comparison.md
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --allow-missing-candidate
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --fail-on-candidate-only
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --min-samples-per-row 3
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --fail-on-parse-errors
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --fail-on-zero-compared
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --fail-on-skipped-files
node scripts/compare-playback-benchmark-runs.js --baseline /path/to/baseline-results --candidate /path/to/candidate-results --output /tmp/playback-comparison.md --output-json /tmp/playback-comparison.json

Comparison output reports both baseline rows missing in candidate and candidate-only rows not present in baseline.
Comparison table also reports baseline/candidate run counts per row when multiple JSON inputs contribute to the same key.
Comparison JSON summary includes `failureReasons` and `gateOutcomes` fields for automation-friendly gate diagnostics.
Minimum sample gating is applied against metrics that are actually comparable for the row (for example, scrub samples are not required for rows with no scrub metric comparison).
Comparison JSON also includes baseline/candidate file parsing stats and optional parse-error gating support.
Comparison can optionally gate on skipped input files via `--fail-on-skipped-files`.
Comparison file stats now include skipped-file breakdown for `no_reports` and `no_usable_metrics`.
```

#### Decode Performance Benchmark
Expand All @@ -62,6 +130,12 @@ cargo run -p cap-editor --example decode-benchmark -- --video /path/to/video.mp4

# With custom FPS and iterations
cargo run -p cap-editor --example decode-benchmark -- --video /path/to/video.mp4 --fps 60 --iterations 50

# Emit machine-readable JSON with startup/scrub metrics
cargo run -p cap-editor --example decode-benchmark -- --video /path/to/video.mp4 --fps 60 --sequential-frames 180 --random-samples 120 --output-json /tmp/decode-benchmark.json

# Fragmented segment input is supported by passing the display directory
cargo run -p cap-editor --example decode-benchmark -- --video /path/to/segment/display --fps 60 --output-json /tmp/decode-benchmark-fragmented.json
```

#### Combined Workflow (Recording → Playback)
Expand All @@ -74,6 +148,30 @@ cargo run -p cap-recording --example real-device-test-runner -- full --keep-outp
cargo run -p cap-recording --example playback-test-runner -- full
```

### Cross-Platform Validation Matrix

Run these scenarios on each required hardware class and append outputs via `--benchmark-output`.

```bash
cargo run -p cap-recording --example playback-test-runner -- full --fps 60 --benchmark-output --notes "platform=<platform> gpu=<gpu> scenario=full"
cargo run -p cap-recording --example playback-test-runner -- scrub --fps 60 --benchmark-output --notes "platform=<platform> gpu=<gpu> scenario=scrub"
```

Automated helper for machine runs:

```bash
node scripts/run-playback-benchmark-matrix.js --platform macos-13 --gpu apple-silicon --output-dir /tmp/playback-matrix --fps 60 --startup-threshold-ms 250 --input-dir /tmp/cap-real-device-tests
node scripts/run-playback-benchmark-matrix.js --platform windows-11 --gpu nvidia-discrete --output-dir /tmp/playback-matrix-windows-nvidia --fps 60 --startup-threshold-ms 250 --require-formats mp4,fragmented --input-dir /tmp/cap-real-device-tests
node scripts/run-playback-benchmark-matrix.js --platform windows-11 --gpu integrated --output-dir /tmp/playback-matrix-windows-integrated --fps 60 --startup-threshold-ms 250 --scenarios scrub --input-dir /tmp/cap-real-device-tests
```

| Platform | GPU Class | MP4 Full | Fragmented Full | MP4 Scrub | Fragmented Scrub | Notes |
|----------|-----------|----------|-----------------|-----------|------------------|-------|
| macOS 13+ | Apple Silicon | ☐ | ☐ | ☐ | ☐ | |
| Windows 11 | NVIDIA discrete | ☐ | ☐ | ☐ | ☐ | |
| Windows 11 | AMD discrete | ☐ | ☐ | ☐ | ☐ | |
| Windows 11 | Integrated baseline | ☐ | ☐ | ☐ | ☐ | |

---

## Benchmark History
Expand Down Expand Up @@ -106,6 +204,19 @@ cargo run -p cap-recording --example playback-test-runner -- full
| **P50/P95/P99** | Latency percentiles | Sorted distribution |
| **Effective FPS** | Actual decode throughput | frames / elapsed_time |
| **Jitter** | Decode time variance (std dev) | sqrt(variance) |
| **First Decode** | Decode latency for first successful frame | elapsed from first frame request |
| **Startup to First** | Time from playback test start to first decoded frame | elapsed since playback test start |

### Scrub Metrics

| Metric | Description | How Measured |
|--------|-------------|--------------|
| **Seek Operations** | Total random seek attempts | Fixed operation count per segment |
| **Successful Seeks** | Seeks returning a decoded frame | Count of non-None seek decodes |
| **Failed Seeks** | Seeks returning no frame | Count of None seek decodes |
| **Avg Seek Time** | Mean random seek decode latency | Avg of seek decode times |
| **P50/P95/P99 Seek** | Seek latency percentiles | Sorted seek time distribution |
| **Max Seek Time** | Worst seek decode latency | Max of seek decode times |

### Audio Sync Metrics

Expand Down Expand Up @@ -188,5 +299,6 @@ When analyzing benchmark results, focus on:
## Related Documentation

- [Recording Benchmarks](../recording/BENCHMARKS.md) - Recording performance tracking
- [Playback Matrix Runbook](./PLAYBACK-MATRIX-RUNBOOK.md) - Cross-platform evidence collection workflow
- [cap-rendering/decoder](../rendering/src/decoder.rs) - Decoder implementation
- [cap-video-decode](../video-decode/) - Platform-specific decoders
Loading
Loading