crates/export/EXPORT-FINDINGS.md
SELF-HEALING DOCUMENT: This file is designed to maintain complete context for export performance work. After any work session, UPDATE this file with your findings before ending.
When your context resets, do this:
EXPORT-BENCHMARKS.md for latest raw benchmark datacargo run -p cap-export --example export-benchmark-runner -- quick
After completing work, UPDATE these sections:
Last Updated: 2026-02-16
| Metric | Target | 720p | 1080p | 4K | Status |
|---|---|---|---|---|---|
| MP4 Render FPS (30fps) | >= 30 fps (1080p), >= 15 fps (4K) | 276-306 fps | 249-286 fps | 106-175 fps | PASS |
| MP4 Render FPS (60fps) | >= 30 fps | - | 284 fps | - | PASS |
| Export Completion | No errors | 3/3 | 4/4 | 2/2 | PASS |
| Preset | Estimated Size | Actual Size | Error (%) | Notes |
|---|---|---|---|---|
| MP4 720p/30fps/Maximum | 36.22 MB | 35.79 MB | +1.2% | |
| MP4 720p/30fps/Social | 18.52 MB | 18.93 MB | -2.2% | |
| MP4 720p/30fps/Web | 10.26 MB | 12.13 MB | -15.4% | Slight underestimate at low BPP |
| MP4 1080p/30fps/Maximum | 80.46 MB | 80.27 MB | +0.2% | |
| MP4 1080p/30fps/Social | 40.64 MB | 41.19 MB | -1.3% | |
| MP4 1080p/30fps/Web | 22.06 MB | 23.37 MB | -5.6% | |
| MP4 1080p/60fps/Maximum | 128.25 MB | 127.65 MB | +0.5% | |
| MP4 4K/30fps/Maximum | 319.39 MB | 319.82 MB | -0.1% | |
| MP4 4K/30fps/Social | 160.11 MB | 161.26 MB | -0.7% |
Average size estimation error: 3.0% (calibrated from real-world recording data)
The size estimation uses BPP with encoder-matched FPS tapering and measured efficiency:
MP4 formula:
effective_fps = min(fps, 30) + max(fps - 30, 0) * 0.6
video_bitrate = width * height * bpp * effective_fps
audio_bitrate = 192,000 bps
encoder_efficiency = 0.5
total_size = (video_bitrate + audio_bitrate) * encoder_efficiency * duration / 8
BPP values (unchanged, used by both encoder and estimation):
The effective_fps tapering matches the H.264 encoder's get_bitrate() function in crates/enc-ffmpeg/src/video/h264.rs. The encoder_efficiency = 0.5 accounts for H.264 achieving better compression than the theoretical BPP * pixels calculation.
GIF formula:
bytes_per_frame = width * height * 0.5 * 0.07
total_size = bytes_per_frame * total_frames
Time estimation uses observed render FPS from benchmarks:
encoder_efficiency = 0.5 factor + FPS tapering matching the encoder's get_bitrate() logictotal_frames / effective_render_fps using measured FPS (290 for <=1080p, 175 for 4K)--release builds for more representative GIF and overall numbers| File | Purpose |
|---|---|
crates/export/src/lib.rs | ExporterBase, builder pattern, export orchestration |
crates/export/src/mp4.rs | MP4 export pipeline (NV12 render -> H.264 encode -> MP4 mux) |
crates/export/src/gif.rs | GIF export pipeline (RGBA render -> gifski encode) |
crates/rendering/src/lib.rs | render_video_to_channel_nv12() and render_video_to_channel() |
crates/enc-ffmpeg/src/video/h264.rs | H.264 encoder with BPP-based bitrate |
crates/enc-ffmpeg/src/mux/mp4.rs | MP4 muxer |
crates/enc-gif/src/lib.rs | GIF encoder wrapper |
apps/desktop/src-tauri/src/export.rs | Size/time estimation, Tauri export command |
apps/desktop/src/routes/editor/ExportPage.tsx | Export UI, preset options, size display |
crates/export/examples/export-benchmark-runner.rs | Export benchmark runner |
Goal: Run benchmarks against real Cap recording and calibrate estimation algorithm
What was done:
get_bitrate() functionencoder_efficiency = 0.5 factor based on measured actual/estimated ratiosChanges Made:
apps/desktop/src-tauri/src/export.rs: Rewrote size estimation (FPS tapering + encoder efficiency), rewrote time estimation (observed render FPS)apps/desktop/src/routes/editor/ExportPage.tsx: Removed 0.5x/0.7x UI size multiplier hackscrates/export/examples/export-benchmark-runner.rs: Updated estimation functions to match backendBenchmark Results:
Estimation Accuracy:
Stopping point: MP4 estimation is calibrated and accurate. GIF estimation still needs real-world data.
Goal: Create export benchmark infrastructure matching recording/playback pattern
What was done:
export-benchmark-runner.rs with synthetic video generation, multi-preset test matrix, file size tracking, estimation comparisonChanges Made:
crates/export/examples/export-benchmark-runner.rs: New benchmark runnercrates/export/Cargo.toml: Added chrono, tracing-subscriber dev-dependenciescrates/export/EXPORT-BENCHMARKS.md: New benchmark history filecrates/export/EXPORT-FINDINGS.md: New findings document.claude/skills/performance-export/SKILL.md: New performance skillBenchmark Results:
Estimation Accuracy:
Stopping point: Infrastructure is complete. Next steps are:
### Session YYYY-MM-DD (Brief Description)
**Goal**: What you set out to do
**What was done**:
1. Step 1
2. Step 2
**Changes Made**:
- File: description of change (or "None - performance healthy")
**Benchmark Results**:
- Overall: X/Y passed
- Key metrics summary
**Estimation Accuracy**:
- MP4 avg error: X%
- GIF avg error: X%
**Stopping point**: Current state and any follow-up needed