Skip to content
brorn
No. 024 · Other apps

screen.cast

Shows the screen coming in through the HDMI capture card on my computer and, live, on the iPad. That's all.

Live
Period
2026-10 → now
Platforms
Linux PC · iPad (browser)
Role
Solo: design, build, ship
Tech
Fig. 1 · Live on the iPad

§1The problem

The capture card only opens in one program at a time, so several apps fought over it, and there was no simple way to watch the captured screen on the iPad.

§2What I built

  • Two pagesOne page on the computer that opens the capture card and streams; one on the iPad that only watches.
  • Shared capture cardFive virtual copies of the capture card, one per app, kept alive by a relay.
  • TuningFine adjustment of latency and image quality.

§3The hard parts

5 entries
  1. 01

    One reader per virtual device

    The virtual driver only accepts one reader per device: solved with one copy per app and a single encode shared by all of them.

  2. 02

    Black screen with no error

    The capture card changes the JPEG size mid-stream and Chrome drops it; and the wrong colour format arrives but doesn't decode. Measured by counting real frames.

  3. 03

    Blurry text when the HDMI signal changes

    Detected by reading the ffmpeg log and reopening the input.

  4. 04

    Latency from ~290 ms to ~90 ms

    By limiting the encoder's threads and sending each packet immediately.

  5. 05

    Orphan processes holding the capture card

    Solved with signal handling and shutting down child processes.

§4Result

relay latency (was ~290 ms)
~90 ms
virtual copies of one capture card
5

Running on my computer; the virtual copies serve several apps at the same time. Relay latency is ~90 ms (my own measurement, compared with reading the capture card directly). The stream goes up to 1080p at 30 fps, without sound.

§5Stack

  • Plain Node + WebSocket
  • WebRTC (H.264)
  • ffmpeg
  • v4l2loopback (Linux)
  • Shell script
  • pm2
  • Tailscale