RV565 · free tool · runs in your browser
Video in your display's own pixels, ready for your microcontroller.
Turn an MP4 or WebM into an RV565 clip or an Arduino clip.h: RGB565 for ST7789 and ILI9341 TFTs, 18-bit RGB666, 4-bit grayscale for SSD1322 OLEDs, 1-bit for SSD1306 OLEDs and e-paper, and more. Files use RV565 format version 7, or version 6 for the released RV565 1.x library on ESP32-S3, other ESP32 chips and the Raspberry Pi Pico 2. No upload, no account.
- Arduino · Library Manager → RV565
- Python · pip install rv565
- GitHub · elixpo/rv565
Preview
The converted clip plays here, decoded from the RV565 file exactly as the board will, shown in RGB.
Your video never leaves this device. Conversion runs in your browser; there is no upload and no account.
From video to screen
Three steps to video on a microcontroller.
- 01
Convert
Drop a video here. Pick the frame size, the pixel format your display takes and the frame rate; the page writes an .rv565 file and a clip.h for Arduino.
- 02
Install RV565
Arduino IDE → Library Manager → search “RV565”, or arduino-cli lib install RV565. ESP-IDF and the Pico SDK are supported too; on a computer, pip install rv565 gives the same tools. The released 1.x library plays version 6 files: tick “Version 6 file” before converting.
- 03
Play
Open the ESP32S3_Player example, replace clip.h with yours, and upload. Large clips can live in a flash partition instead.
Questions
Frequently asked.
Is my video uploaded anywhere?
No. The video is decoded by your browser, converted to your display's pixel format on a canvas and compressed with the browser's built-in zlib. Nothing leaves your device, and there is no account or sign-up.
What is the RV565 format?
A small video container for microcontrollers whose frames decode straight to the display's native pixels, so the board runs no colour conversion. Version 7 declares one of nine pixel formats (RGB565 in either byte order, RGB444, RGB666, RGB888, 8- and 4-bit grayscale, and 1-bit monochrome in rows or SSD1306-style pages) and a codec (zlib or stored). Frames are keyframes, XOR deltas from the previous frame, repeats, or partial deltas that carry only the bands of rows that changed (each predicted from the previous frame, optionally shifted to follow motion), so the board sends only those rows to the display. A keyframe comes at least every K frames, so seeking stays fast. Version 6, the format the paper arXiv:2610.35935 measured, is the RGB565 + zlib + every-frame-a-keyframe case. Both are specified in the RV565 repository.
Which boards and displays work?
The released RV565 1.x library plays version 6 files on ESP32-S3 (measured at 24 FPS with zero missed frames), on other ESP32 chips, and experimentally on the Raspberry Pi Pico 2, with ST7789 SPI panels such as 320×240, 240×240 and 135×240 modules; it also works with TFT_eSPI and LovyanGFX. Version 7 adds the formats for ILI9341/ILI9488 18-bit panels, grayscale OLEDs such as the SSD1322, 1-bit OLEDs such as the SSD1306, and e-paper; version 7 files need RV565 2.0 on the board. Until your player is on 2.0, tick “Version 6 file”.
What frame size and frame rate should I choose?
For a colour TFT on an ESP32-S3, 180×135 at 24 FPS in RGB565 with zlib is the setting measured in the paper: the board scales it to a 320×240 panel and holds 24 FPS without missed frames, and the page predicts missed frames for that setting. Larger frames look sharper but need more memory and time per frame. For an OLED or e-paper panel, choose its native resolution and the matching grayscale or monochrome format; those frames are small, so higher rates are cheap.
How long can a clip be?
Up to 30 seconds and 200 MB of input per conversion, to keep the browser responsive. For longer clips use the rv565 command-line tool (pip install rv565), which reads the source video with an installed FFmpeg.
Can I convert without a browser?
Yes. The rv565 package is published on PyPI: pip install rv565, then rv565 encode input.mp4 clip.rv565 --size 180x135 --fps 24, and rv565 c-array clip.rv565 clip.h for Arduino. With pip install "rv565[pillow]", Pillow's Image.open reads .rv565 files too.