Follow-up to #133, which added native h264 to iOS stream-video. With that landed, the screenshot-backed formats have no remaining case where they are the right choice for streaming.
Why they go
Measured on a booted iPhone 17 Pro / iOS 27.0, 6-second captures:
--format |
frames |
effective fps |
bytes |
mjpeg |
24 |
4.1 |
11.2 MB |
raw / ffmpeg (PNG) |
26 |
4.5 |
92.8 MB |
h264 |
144 |
24.0 |
1.33 MB |
They also have no first-party consumer. skills/sim-use/SKILL.md never mentions stream-video at all — its 10 video references are all screenshot and record-video — and the Viewer polls /api/snapshot for single frames rather than streaming. The "MJPEG lets a browser preview with a zero-JS <img src>" argument doesn't survive contact with the actual shape of the tool either: sim-use writes a byte stream to stdout, not an HTTP response, so that use already requires standing up a server, at which point <video> + MSE is no harder.
They additionally ship two latent bugs, neither worth fixing on a path that's going away:
Blocked on: Android needs a stream fallback first
This is the real work, and why it wasn't folded into #133.
record-video already falls back to the screencap loop when adb screenrecord is unavailable (old API levels, some devices, rotation mid-capture). stream-video does not. So today, removing mjpeg/raw/ffmpeg from the Android CLI surface would leave those devices with no streaming at all, while recording kept working — an asymmetric capability matrix.
Order of work:
- Give Android
stream-video the same automatic fallback record-video has: catch ScreenrecordUnavailableError, warn on stderr, continue on the screencap loop. Needs an emulator to verify, including a device where screenrecord genuinely fails.
- Mark
mjpeg / raw / ffmpeg deprecated on all three surfaces (top-level, ios, android): note it in --help and warn once on stderr, pointing at h264.
- Remove them in a later release, keeping the Android
screencap loop as an internal fallback only.
Not in scope
bgra stays. It's iOS-only and experimental, but raw unencoded pixels are something H.264 cannot substitute for, and it costs nothing to keep — it now shares streamNative with h264.
Follow-up to #133, which added native
h264to iOSstream-video. With that landed, the screenshot-backed formats have no remaining case where they are the right choice for streaming.Why they go
Measured on a booted iPhone 17 Pro / iOS 27.0, 6-second captures:
--formatmjpegraw/ffmpeg(PNG)h264They also have no first-party consumer.
skills/sim-use/SKILL.mdnever mentionsstream-videoat all — its 10 video references are allscreenshotandrecord-video— and the Viewer polls/api/snapshotfor single frames rather than streaming. The "MJPEG lets a browser preview with a zero-JS<img src>" argument doesn't survive contact with the actual shape of the tool either: sim-use writes a byte stream to stdout, not an HTTP response, so that use already requires standing up a server, at which point<video>+ MSE is no harder.They additionally ship two latent bugs, neither worth fixing on a path that's going away:
--scale 1.0/--quality 80the frame processor passes the capture through untouched while every MJPEG frame header hardcodesimage/jpeg— but iOS screenshots and Androidscreencap -pare both PNG. Diagnosed in fix: emit JPEG frames for default video streams #94; fix: encode stream-video frames once, into the container they claim #130 fixed it and was closed in favour of this direction.ffmpeg -f mpjpegbecause of a leadingHTTP/1.1 200 OKstatus line, plus a boundary value that carries its own--against RFC 2046. That's stream-video --format mjpeg is unparseable by ffmpeg's mpjpeg demuxer #131, which this issue supersedes.Blocked on: Android needs a stream fallback first
This is the real work, and why it wasn't folded into #133.
record-videoalready falls back to thescreencaploop whenadb screenrecordis unavailable (old API levels, some devices, rotation mid-capture).stream-videodoes not. So today, removingmjpeg/raw/ffmpegfrom the Android CLI surface would leave those devices with no streaming at all, while recording kept working — an asymmetric capability matrix.Order of work:
stream-videothe same automatic fallbackrecord-videohas: catchScreenrecordUnavailableError, warn on stderr, continue on thescreencaploop. Needs an emulator to verify, including a device wherescreenrecordgenuinely fails.mjpeg/raw/ffmpegdeprecated on all three surfaces (top-level,ios,android): note it in--helpand warn once on stderr, pointing ath264.screencaploop as an internal fallback only.Not in scope
bgrastays. It's iOS-only and experimental, but raw unencoded pixels are something H.264 cannot substitute for, and it costs nothing to keep — it now sharesstreamNativewithh264.