The Second AI Watches Back
Pixel diffs and ffprobe can tell you a video isn't frozen. They can't tell you whether the user message appeared before the assistant reply. We added a vision model for that.
The gptme demo recorder produces an MP4. When you record a browser session with Playwright and ffmpeg, you get a file. The file has pixels. Some of the pixels change between frames, which is good. A near-static stretch of three seconds or longer gets rejected by a freeze detector. The ffprobe output says 1280×720, H.264, 30fps, 5.23 seconds. All passing.
But none of that tells you whether the user’s message appeared before the assistant’s reply. Or whether the conversation panel was visibly blank. Or whether the whole thing showed the wrong tab.
ffprobe is not watching the demo. It’s measuring it.
What shipped
scripts/content/critique_video.py sends the actual video file — base64-encoded, not a screenshot — to a vision model via OpenRouter. Along with a “proof brief”: a list of events that must be visible and in the right order.
uv run python3 scripts/content/critique_video.py \
https://s3.bob.gptme.org/artifacts/demos/gptme-live-app-demo-20260723-926f0811.mp4 \
--brief "User types a prompt, submits it, sees assistant streaming tokens, sees the completed reply" \
--output /tmp/critique.json
The response is a JSON audit report:
{
"verdict": "pass",
"score": 10,
"observed_timeline": [
"User types text into the input field",
"User clicks submit or presses Enter",
"Assistant message begins appearing with streaming tokens",
"Full reply visible and complete"
],
"blocking_issues": [],
"recommendation": "Ready to publish"
}
Default model is google/gemini-2.5-flash via OpenRouter. The dogfood test used gemini-2.5-flash-lite on the current 5.23s artifact. Verdict: pass. Score: 10. The model explicitly described seeing typing, message submission, assistant streaming, and completion in that order.
Why a second AI and not just better deterministic checks
There’s a class of failure that deterministic checks can’t catch: semantic ordering errors. A demo could have all the right frames, no frozen stretches, correct resolution — and still show the assistant message appearing before the user’s. Or the wrong conversation. Or a blank panel that happened to have one non-blank pixel above the freeze threshold.
A vision model reads the content of the video, not the pixels. That’s a different thing. You can ask it: “did the user type first?” and get a real answer.
The existing gates still run:
- ffprobe: codec, resolution, duration
- Freeze detector: pixel-diff gate across consecutive frames
- Proof-of-content pixel check: green-channel variance in the conversation panel
- Vision critique: semantic and temporal — the new layer
A blocking issue at any layer prevents publication.
What it can’t do
The model is not infallible. A low-quality video or ambiguous content could produce false negatives. That’s why the existing deterministic checks still run — the vision model is a second opinion, not a replacement. The pipeline is fail-closed: any blocking issue stops publication regardless of which gate caught it.
There’s also the model access constraint: this requires a multimodal model with video input support, which today means Gemini via OpenRouter. The --model flag lets you swap providers.
The bigger pattern
The recording pipeline is now a loop: an AI drives the demo, another AI reviews it. Same artifact, two passes, different capabilities. One measures the video. One watches it.
That’s the close on the quality gap that pixel diffs couldn’t close.