Visual Binary Storage System — encode any file into a lossless grayscale video, and decode it back perfectly.
Inspired by the "YouTube Infinite Storage Glitch", Bitplane deterministically maps raw file bytes onto 1920×1080 grayscale video frames (one byte per pixel) and reconstructs the original file from those frames with zero data loss.
Deployed at: https://bitplane.duckdns.org/
- The uploaded file is saved to an isolated UUID job workspace.
- A metadata frame (frame 0) is written containing the original filename, file size, and total payload frame count, serialized as JSON with a 4-byte length prefix.
- The file is split into chunks of up to 2,073,596 bytes (
1920 × 1080 − 4), each wrapped as a payload frame with a 4-byte frame index prefix. - Each frame is rendered as a 1920×1080 grayscale
BufferedImage(one byte per pixel) and written to disk as a PNG. - FFmpeg assembles all PNGs into a lossless
output.mp4usinglibx264rgbwith-crf 0 -preset veryslow. - The video is streamed back to the browser and the workspace is deleted.
Compatibility note: The
libx264rgbcodec is not supported by Windows Media Player or macOS QuickTime. Use VLC to play the encoded video.
- The uploaded
.mp4is saved to an isolated workspace. - FFmpeg extracts all frames as PNGs into an
extracted_frames/directory. - All frames are loaded into memory as
BufferedImageobjects and wrapped in anImageFrameSet. - The metadata frame is decoded to recover the original filename, file size, and expected frame count.
- Payload frames are deserialized, sorted by frame index, validated, and concatenated into a single byte array truncated to the exact original file size.
- The reconstructed file is written to the workspace, then streamed back to the browser with its original filename, and the workspace is deleted.
| Frame | Wire Format |
|---|---|
| Metadata | [4 bytes: JSON length][N bytes: UTF-8 JSON] |
| Payload | [4 bytes: frame index (int)][remaining: payload bytes] |
For a 5 MiB file:
- Frame capacity:
1920 × 1080 = 2,073,600bytes - Payload per frame:
2,073,600 − 4 = 2,073,596bytes - Payload frames needed:
ceil(5,242,880 / 2,073,596) = 3
| Layer | Technology |
|---|---|
| Language | Java 21 |
| Backend framework | Spring Boot (WebMVC + Thymeleaf) |
| Video processing | FFmpeg (libx264rgb, -crf 0) |
| Image processing | Java AWT / BufferedImage / ImageIO |
| Frontend | Thymeleaf templates + Tailwind CSS v4 (CDN) |
| Build | Maven (mvnw wrapper) |
| Code formatting | Spotless + Palantir Java Format |
| Containerization | Docker (multi-stage) + Docker Compose |
| CI | GitHub Actions |
| Execution tracking | io.github.sathwikhbhat:api-execution-tracker |
Each request gets an isolated UUID job directory under data/temp/. Cleanup is two-layered:
- Immediate: The controller streams the response and deletes the workspace in a
finallyblock. - Scheduled fallback:
WorkspaceCleanupServiceruns every 5 minutes and removes any workspace older than 10 minutes as a safety net for crashes or OOM kills.
- Java 21
- FFmpeg on
$PATH - Maven (or use the included
mvnwwrapper)
./mvnw spring-boot:runThe app starts on http://localhost:8080.
docker compose up --buildFFmpeg is installed automatically inside the Docker image. The app is available at http://localhost:8080.
./mvnw spotless:apply./mvnw clean verifynpx prettier --write "src/**/*.html"GitHub Actions runs on every push to main and on all pull requests:
- Checkout code
- Set up JDK 21 Temurin with Maven cache
mvn clean verify: builds, checks Spotless formatting, and runs tests
Improperly formatted Java will fail the CI build.
See ARCHITECTURE.md for a detailed breakdown of the encode pipeline, decode pipeline, video layer, and workspace lifecycle.
