| 2026-09-18 |
Cursor marker in recordings + higher encode quality
...
- CDP screencast frames don't include the OS pointer, so the GIF and
WebM encoders now paint a classic white arrow (dark outline) at the
interpolated cursor position — the crop centers on it, so it stays
in frame
- screencast JPEG quality 55 -> 70
- VP8 bitrate ~0.3 bits/px/frame (cap 8 Mbps) for sharper output
- verified with the real built offscreen encoder: synthetic green
frames + known track land the arrow within 3px of the true cursor
Co-Authored-By: Claude Code <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
14 hours ago
|
Video in report details + 768px cursor crop quality
...
- web panel: screen recording now plays in the Details tab (large
video card), removed from the Attachments thumbnails to avoid
showing it twice
- screencast cap raised 1280 -> 2560 so wide viewports keep the
cursor crop at native resolution (user viewport 2552 was scaled
down to 1280, halving the video size)
- crop raised 512 -> 768 CSS px; GIF fallback stays at 512
- VP8 bitrate now scales with output size (~0.18 bits/px/frame,
capped at 4 Mbps) instead of a fixed 1 Mbps
- e2e ffprobe assertion updated to the 768px cap
Co-Authored-By: Claude Code <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
15 hours ago
|
Crop recordings in the JPEG's pixel space, not the device space
...
Page.startScreencast frames are scaled to fit maxWidth/maxHeight, but the
frame metadata's deviceWidth/deviceHeight keep the pre-scale device size.
On viewports wider than the 1280px cap the crop was computed in the wrong
coordinate space: shifted toward the bottom-right and, for a cursor there,
hanging off the actual image — drawImage clipped it and the video showed a
squashed corner plus letterbox. Decode the first frame to size the output
and crop each frame by its real bitmap dimensions instead.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
15 hours ago
|

Project switcher in popup, pending-recording composer, cursor-crop video
...
- Popup: project dropdown (list_projects + settings_save defaultProjectId);
switching refreshes the last-report card and panel link immediately.
- Recording stop no longer submits blindly: the buffer goes pending and a
composer opens in the tab with title (prefilled) + description, Save
(Ctrl+Enter, copies the share link) or two-step Discard; unanswered
pending recordings auto-save after 10 minutes, and starting a new
recording auto-saves a pending one. Composer survives navigation.
- WebM is now a square cursor-following crop (shared cursorCropRect helper
with the GIF path), source dimension raised to 1280 so the 512px crop is
native-resolution at DPR 1; full-frame 800px stays as fallback.
- e2e: second project + popup switcher asserts, composer save (typed
title/description verified on server), keyboard-driven discard flow,
ffprobe square-video assertions (512x512 VP8).
Co-Authored-By: Claude Code <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
16 hours ago
|
| 2026-09-17 |

Record silent WebM screen video instead of GIF during recordings
...
The recorder now captures continuous screencast frames via the CDP
screencast API and encodes them into a silent WebM (VP8, ~15 fps, capped
at 800px wide) uploaded as recording.webm. WebCodecs VideoEncoder is not
exposed to service workers, so encoding runs in an offscreen document
(chrome.offscreen) fed by base64 frame batches over a runtime port; the
result is verified with a local <video> playback probe and falls back to
the cursor-following GIF when encoding or verification fails (Firefox,
old Chrome, broken output).
Root cause of the earlier corrupt output: webm-muxer silently produces a
broken file when the first chunk's timestamp is non-zero — media
timestamps now start at the first frame and the muxer uses
firstTimestampBehavior: "offset".
The e2e now validates the uploaded recording with ffprobe (vp8 codec,
positive duration) and still covers the GIF fallback path, console-step
dump, navigation survival and replay.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|