Inspiration

Most screen recordings are a poor fit for debugging. They preserve minutes of unchanged pixels, make the useful moments slow to find, and can expose more information than a bug report needs. I wanted a local recorder built around change events: capture the moments where the screen changes, keep the evidence compact, and let the user decide exactly what can leave the machine.

Stutterbox began as that recorder. OpenAI Build Week supplied the missing last mile: turning a selected and redacted event range into a useful report with GPT-5.6.

What it does

Stutterbox records one full keyframe, then stores only lossless changed regions and timestamps inside a hash-linked SQLite .stut container. Playback moves by change event instead of by second, and a heat map makes active stretches easy to find.

For reporting, the user chooses a full session or event range, marks any spatial redactions, selects a bug reproduction report or session summary, and explicitly approves the request. Stutterbox reconstructs up to eight timestamped frames, applies every redaction locally before image encoding, sends that narrow payload to GPT-5.6 through the OpenAI Responses API, and renders structured Markdown that can be copied into an issue or support ticket.

The bundled three-minute judge sample contains 507 change events in a 272 KiB file. The equivalent raw frames would occupy about 1.85 GiB.

How I built it

The desktop application is written in Python and PySide6. mss captures RGB frames, while NumPy and Pillow handle the tile-based perceptual diff, merged change regions, reconstruction, and local redaction. SQLite stores the keyframes, PNG deltas, timestamps, metadata, and a per-frame SHA-256 chain. Opening a recording verifies the container structure and hash chain before playback.

The cloud reporting path is isolated from capture. It deterministically samples an inclusive event range, reconstructs each selected frame locally, applies redactions, encodes the scrubbed images, and builds a constrained GPT-5.6 request. The capture path contains no network calls, and every cloud request requires a visible user action, an API key, and fresh approval.

During Build Week, I used Codex to implement and pressure-test the new reporting path. It helped turn audit findings into regression tests, build deterministic sampling and request assembly, wire the PySide6 report workspace, and repeat the strict typing and release verification passes. I retained the product decisions and reviewed the privacy boundary, sampling rule, prompt contract, failure behavior, and release scope.

Challenges I ran into

Correct frame reconstruction was the first hard problem. A report image can depend on a keyframe followed by hundreds of regional deltas. Event-range selection had to stay inclusive, sample no more than eight frames, preserve both endpoints, and return the same result on every run.

Redaction order was the second. A privacy control has little value if sensitive pixels are serialized before the mask is applied. The pipeline therefore reconstructs the frame, applies every marked rectangle in memory, and only then performs image encoding. Regression tests check that ordering directly.

The desktop workflow also needed useful failure states for missing keys, rejected requests, network errors, malformed recordings, concurrent file mutation, and disk exhaustion. Packaging the complete path for Windows added a final constraint: a judge needed to extract one folder, open the included sample, and exercise the feature without recording a new session.

Accomplishments that I am proud of

  • The 507-event sample is 272 KiB, about 7,147 times smaller than the same session stored as raw frames.
  • Its eight report frames prepare locally in about 0.21 seconds and total 39,107 bytes before Base64 encoding.
  • The release has 78 passing tests and a clean mypy --strict pass across 44 source files.
  • The Windows package includes the application, license notices, and a ready-to-use judge sample.
  • The project keeps stealth capture, hidden autostart, automatic upload, central collection, and productivity scoring outside the upstream product.

What I learned

The quality of a cloud-generated report depends heavily on the local evidence contract. Stable timestamps, deterministic sampling, constrained Markdown, and an explicit uncertainty section gave GPT-5.6 a much cleaner job than an unconstrained video upload would have.

I also learned that change events form a useful semantic index. For low-motion work such as coding, debugging, and support, the moments where pixels change are often the same moments a reviewer needs. That index makes both human review and model input smaller and more focused.

The strongest privacy boundary came from architecture: capture has no network path, redaction happens before serialization, and approval belongs to each request. Those constraints also made the feature easier to test.

What's next for Stutterbox

The next steps are broader capture testing on macOS and Linux, optional Ed25519 signatures for recordings, faster keyboard-driven review, and report-quality evaluation across more debugging and support sessions. The local-first capture model and explicit upload boundary will remain fixed.

Built With

Share this project:

Updates