A headless machine in a closet - a home server, a hypervisor, a NAS - is wonderful right up until it doesn't boot. No ping, no SSH, dead web UI. Is it stuck in the BIOS? Did the kernel panic? Is it politely waiting for someone to press F1 after a RAM change three weeks ago? You can't know without dragging a monitor and keyboard to it.
The grown-up answer is an IP-KVM: a box that captures the machine's HDMI output, pretends to be its USB keyboard and mouse, and puts both in a browser. You see exactly what a monitor would - all the way down to the BIOS and the boot menu - and you type and click as if you were there. The target needs no agent, no OS, not even a working boot. It has no idea its "monitor" and "keyboard" are a little board on the network.
Commercial IP-KVMs are expensive. PiKVM is great but rides the Raspberry Pi supply. Then Espressif shipped the ESP32-P4: a RISC-V chip with a MIPI-CSI camera interface, 32 MB of PSRAM, and USB 2.0 High-Speed. A camera input means you can hang an HDMI-to-CSI bridge off it and capture video - so a full IP-KVM becomes two dev boards and a ribbon cable, with no soldering. That project is ESP-KVM, and it's fully open source (Apache-2.0).
Credit where it's due
This builds directly on Jonathan Rowny's work - jrowny/p4kvm and his Hackaday project ESP32-P4 IP KVM. An IP-KVM on the ESP32-P4 is an obvious thing to want, but he's the one who cracked the genuinely hard part - bringing up the Toshiba TC358743 HDMI-to-CSI bridge and getting frames off the P4's CSI receiver - and put it out in the open. He also named the exact wall this project later climbed: he wanted H.264 but was stuck on MJPEG, because rev-1.3 silicon forces a colour-space detour that the newer revision removes. ESP-KVM is everything built on top of his driver (web console, USB HID, security, virtual media, networking, OTA) - and on rev-3.2 silicon that H.264 wall is gone. Same licence as his.
What you get (all working today)
- Video that follows the target's resolution - a 640x480 BIOS, the boot menu, a 1080p desktop, handled live. Sleep it or swap the HDMI and the stream recovers by itself.
- Two codecs - hardware MJPEG and hardware H.264 (a fraction of the bandwidth).
- Absolute mouse (clicks land where you aim) plus a full keyboard, media keys, one-button macros (Ctrl-Alt-Del, REISUB), and paste-a-string in the target's keyboard layout.
- Touch mode for phones/tablets - a real virtual trackpad and on-screen keyboard - as an installable PWA.
- Multiple viewers, one in control at a time, with takeover.
- Virtual media - boot the target from an ISO/IMG on a microSD card, or from a small rescue image in the device's own flash (no card needed).
- ATX power control (power/reset via optocouplers, power-LED sense) and Wake-on-LAN.
- Networking - Ethernet, or WiFi on boards with an onboard ESP32-C6: station or the device's own access point, with a rescue hotspot and a captive portal so a device whose network is down is still set up from a phone.
- Remote access - native Tailscale, or point it at your own self-hosted Headscale, to join a tailnet directly (no gateway, VPS or port-forward, cert valid over the tailnet); a built-in WireGuard client too.
- Home Assistant over MQTT (auto-discovered sensors plus power/reset/Wake-on-LAN buttons).
- An automation surface - plain REST to grab a JPEG frame and move/click/type, so you can script it or point an AI agent at a real machine it can see and drive.
- Security/ops - HTTPS with a certificate the device issues itself (plus a downloadable CA to trust it, or bring your own), a login, a physical password reset, OTA update with rollback, thermal protection, diagnostics.
The interesting hardware bits
- The MIPI link sets a pixel-clock ceiling. Capture is 2 CSI lanes at 972 Mbit/s = 1.944 Gbit/s, RGB888, so ~81 Mpixel/s - exactly 1080p30. Anything above (1080p60, 1280x1024) is refused in the EDID, because an over-advertised mode doesn't degrade, it just goes black....
Dexif