Skip to content

Add video recording commands (start-video, stop-video)#4

Open
simonw wants to merge 4 commits into
mainfrom
claude/rod-video-recording-jRyfu
Open

Add video recording commands (start-video, stop-video)#4
simonw wants to merge 4 commits into
mainfrom
claude/rod-video-recording-jRyfu

Conversation

@simonw
Copy link
Copy Markdown
Owner

@simonw simonw commented Feb 10, 2026

Records video of Chrome sessions by capturing CDP screencast frames
during each rodney command execution. No background process needed -
frames are captured automatically while commands run and accumulated
across invocations.

  • start-video: enables recording flag in state, creates frames dir
  • stop-video: assembles frames into MP4 via ffmpeg (with graceful
    fallback), cleans up frames dir
  • Screencast capture hooks into withPage() and cmdOpen() transparently
  • Variable framerate video assembly using frame timestamps
  • 9 new tests covering start/stop/capture/accumulation/assembly

https://claude.ai/code/session_018GfJUXfG9azF393kRTQPss

Records video of Chrome sessions by capturing CDP screencast frames
during each rodney command execution. No background process needed -
frames are captured automatically while commands run and accumulated
across invocations.

- start-video: enables recording flag in state, creates frames dir
- stop-video: assembles frames into MP4 via ffmpeg (with graceful
  fallback), cleans up frames dir
- Screencast capture hooks into withPage() and cmdOpen() transparently
- Variable framerate video assembly using frame timestamps
- 9 new tests covering start/stop/capture/accumulation/assembly

https://claude.ai/code/session_018GfJUXfG9azF393kRTQPss
GIF is now the default output format for stop-video (no ffmpeg needed).
Uses Go stdlib image/gif with Plan9 palette and Floyd-Steinberg dithering.

Frame deduplication: consecutive identical frames (after quantization
to 256 colors) are merged into a single GIF frame with extended
duration. This significantly reduces file size for sessions with
static page moments between commands.

Format is auto-detected from file extension:
- .gif: pure Go encoding with deduplication (default)
- .mp4: ffmpeg assembly with variable framerate (requires ffmpeg)

4 new tests covering GIF encoding, dedup verification, stdlib
decode validation, and extension-based format detection.

https://claude.ai/code/session_018GfJUXfG9azF393kRTQPss
When stop-video is called with a .mp4 extension but ffmpeg isn't
installed, automatically fall back to producing a .gif instead of
silently failing. Prints a message to stderr informing the user.

https://claude.ai/code/session_018GfJUXfG9azF393kRTQPss
@simonw
Copy link
Copy Markdown
Owner Author

simonw commented Feb 10, 2026

I tried this:

go build .
./rodney start 
./rodney start-video
./rodney open https://datasette.io/
./rodney click a
./rodney sleep 3                   
./rodney stop-video out.gif

And got this:

out

The sleep 3 did not work.

cmdSleep now connects to the active page when video recording is on,
so screencast frames are captured during the sleep period. Also adds
a LoopCount assertion to the GIF stdlib decode test.

https://claude.ai/code/session_018GfJUXfG9azF393kRTQPss
@simonw
Copy link
Copy Markdown
Owner Author

simonw commented Feb 10, 2026

I thought it wasn't looping but turns out it had a 25s hold on the last frame:

⏺ Here are the frame durations for out.gif:                                                         
  ┌───────┬────────────────┐                                                                        
  │ Frame │    Duration    │                                                                        
  ├───────┼────────────────┤                                                             
  │ 0     │ 160ms          │                                                                        
  ├───────┼────────────────┤                                                                        
  │ 1     │ 20ms           │                                                                        
  ├───────┼────────────────┤                                                                        
  │ 2     │ 80ms           │                                                                        
  ├───────┼────────────────┤
  │ 3     │ 25,040ms (25s) │                                                                        
  ├───────┼────────────────┤                                                                        
  │ 4     │ 100ms          │                                                                        
  └───────┴────────────────┘                                                                        
  Total: 5 frames

  Frame 3 stands out with a 25-second duration — it's likely the "final" frame that holds on screen
  before the GIF loops. The other frames are very short (20–160ms), making the animation itself
  quite fast before pausing on that long frame.

@simonw
Copy link
Copy Markdown
Owner Author

simonw commented Feb 10, 2026

Looks like the 25s delay is because the tool was using the timestamps of when commands were run to modify GIF lengths. I said:

I don't want the GIFs to go based on the timestamps of when the commands were run, if I spend a while thinking in between typing commands I don't want that thinking time reflected in the GIF - I want to use the sleep command to deliberately insert pauses instead

@simonw
Copy link
Copy Markdown
Owner Author

simonw commented Feb 10, 2026

alex-pezarro-portswigger added a commit to alex-pezarro-portswigger/rodney that referenced this pull request Apr 20, 2026
Resolve conflicts by:
- Combining State struct so Logs/LoggerPID/Label (existing) coexist
  with VideoRecording/VideoDir (new)
- Keeping RODNEY_HOME + activeStateDir (--local/--global) lookup
  while adding stateDirOverride for test isolation used by pr-4 tests
- Restoring missing closing braces on TestLogs_FormatLogLevel and
  TestLogs_WriteJSONLine that git's merge algorithm elided because
  similar section delimiters appeared on both sides
- Merging imports and keeping both sides' video tests plus the
  existing cookie/logs/label tests

Also includes the per-frame-duration cap fix from the review feedback:
idle time between rodney command invocations no longer leaks into
the GIF/MP4 output as a long hold on the last frame.
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.

2 participants