Explanation Videos:
YC Hacker News: https://news.ycombinator.com/item?id=47012964
Stores files onto any video or streaming platform (YouTube, Twitch, etc.) by encoding them into lossless video and decoding them back to the original file. Supports both a command-line interface and a graphical user interface.
- File Encoding/Decoding: Encode any file into a lossless video (FFV1/MKV) and then decode it back to the original file
- Live Streaming: Stream-encode files to Twitch/YouTube via RTMP (H.264) and decode them back from the stream or VOD
- Fountain Codes: Uses Wirehair fountain codes for redundancy and repair
- Optional Encryption: Encrypt files with a password using libsodium (XChaCha20-Poly1305)
- Selectable Checksum: Choose between CRC32 (default) and xxHash32 for packet integrity verification
- Batch Processing: Queue multiple files for batch encoding (GUI)
- Progress Tracking: Real-time progress bars and status updates (GUI)
Visit GitHub Releases, and click to download artifacts.
- CMake 3.22
- C++23 compiler
- FFmpeg (with libx264 for streaming)
- libsodium
- OpenMP
- Qt6 (Core and Widgets)
sudo apt update
sudo apt install cmake build-essential pkg-config qt6-base-dev \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev \
libsodium-dev libomp-dev ffmpegWSL: if CMake reports
Could NOT find PkgConfigand the error has Strawberry, WSL is using Windows'pkg-config.exefrom inheritedPATH. Pass-DPKG_CONFIG_EXECUTABLE=/usr/bin/pkg-configto CMake.
sudo dnf install cmake gcc-c++ qt6-qtbase-devel ffmpeg-devel libsodium-devel libgompsudo pacman -S cmake qt6-base ffmpeg libsodium openmpbrew install cmake qt@6 ffmpeg libsodium libompvcpkg install ffmpeg libsodium qt6-base gtest --triplet x64-windowsThen configure with the toolchain file:
cmake -B build -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmakeOr install Qt6 separately via the Qt Online Installer and FFmpeg/libsodium via vcpkg. When using the installer, point CMake at the install prefix:
cmake -B build -DCMAKE_PREFIX_PATH="C:/Qt/XXX/msvcXXX_64"cmake -B build
cmake --build buildThis produces two executables and one shared library:
media_storage— Command-line interfacemedia_storage_gui— Graphical user interfacelibmedia_storage.so/media_storage.dll— Embeddable shared library
Tests use Google Test.
cmake -B build -DBUILD_TESTS=ON
cmake --build build
ctest --test-dir buildOr run the test binary directly for verbose output:
./build/tests/media_storage_tests./media_storage encode --input <file> --output <video> [--encrypt --password <pwd>] [--hash <crc32|xxhash>]
./media_storage decode --input <video> --output <file> [--password <pwd>]
./media_storage stream-encode --input <file> --url <rtmp://...> [--bitrate <kbps>] [--width <w> --height <h>] [--encrypt --password <pwd>]
./media_storage stream-decode --url <stream_url> --output <file> [--password <pwd>]
Stream-decode supports a 30-second retry window, so you can start it before the encoder begins streaming.
Example — stream to Twitch at 1080p:
# Terminal 1: start decoder first (waits for stream)
./media_storage stream-decode --url stream_playback_url --output decoded.bin
# Terminal 2: start encoder
# You must use yt-dlp to get the raw Twitch or YouTube Stream URL
./media_storage stream-encode --input myfile.bin --url rtmp://... --width 1920 --height 1080 --bitrate 8000| Flag | Short | Description |
|---|---|---|
--input |
-i |
Input file path (required for encode) |
--output |
-o |
Output file path (required for decode) |
--url |
-u |
RTMP stream URL (streaming only) |
--bitrate |
-b |
Stream bitrate in kbps (default: 8000 for 1080p) |
--width |
Stream video width (default: 1920) | |
--height |
Stream video height (default: 1080) | |
--encrypt |
-e |
Enable encryption (encode only) |
--password |
-p |
Password for encryption/decryption |
--hash |
-H |
Checksum algorithm: crc32 (default) or xxhash (encode only) |
The checksum algorithm is embedded in each packet's flags, so decode automatically detects which algorithm was used —
no need to specify it again.
./media_storage_gui
-
Encode a file to video:
- Click "Browse..." next to "Input File" to select the file you want to encode
- Click "Browse..." next to "Output File" to choose where to save the video
- Click "Encode to Video" to start the process
-
Decode a video to file:
- Click "Browse..." next to "Input File" to select the video file
- Click "Browse..." next to "Output File" to choose where to save the decoded file
- Click "Decode from Video" to start the process
- Click "Add Files" to add multiple files to the batch queue
- Select an output directory for all encoded videos
- Click "Batch Encode All" to process all files in sequence
- Select a platform (Twitch, YouTube, or Custom)
- Enter your stream key
- Choose a resolution (1080p, 1440p, or 4K), and change bitrate if needed
- Select an input file and click "Stream Encode" to start streaming
- To decode a stream, enter the stream URL and click "Stream Decode"
- The progress bar shows the current operation progress
- Status label displays current operation status
- Logs panel provides detailed information about each step
- All operations run in separate threads to keep the UI responsive
The shared library exposes a C API (media_storage.h) so you can integrate encoding/decoding. Link against
libmedia_storage and include the header:
#include <media_storage.h>
int progress(uint64_t current, uint64_t total, void *user) {
printf("Progress: %llu / %llu\n", current, total);
return 0; // return non-zero to cancel
}
int main(void) {
ms_encode_options_t opts = {0};
opts.input_path = "myfile.bin";
opts.output_path = "myfile.mkv";
opts.hash_algorithm = MS_HASH_CRC32;
opts.progress = progress;
ms_result_t result;
ms_status_t status = ms_encode(&opts, &result);
if (status != MS_OK) {
fprintf(stderr, "Error: %s\n", ms_status_string(status));
return 1;
}
printf("Encoded %llu bytes -> %llu bytes (%llu frames)\n",
result.input_size, result.output_size, result.total_frames);
return 0;
}After installing with cmake --install build, use find_package:
find_package(media_storage REQUIRED)
target_link_libraries(your_app PRIVATE media_storage::media_storage_lib)Or add this repository as a subdirectory:
add_subdirectory(media-storage)
target_link_libraries(your_app PRIVATE media_storage_lib)- Encoding: Files are chunked, encoded with fountain codes, and embedded into video frames
- Decoding: Packets are extracted from video frames and reconstructed into the original file
- Lossless Format: FFV1 codec in MKV container at 3840x2160 (4K), 30 FPS
- Streaming Format: H.264 (libx264) in FLV container via RTMP, with configurable resolution and bitrate
- Encryption: Optional XChaCha20-Poly1305 via libsodium
- Checksums: CRC32-MPEG2 (default) or xxHash32 per packet; algorithm is stored in the packet flags for self-describing decode
- Qt6 not found: Ensure Qt6 development packages are installed
- FFmpeg libraries missing: Install FFmpeg development packages
- libsodium missing: Install libsodium development packages
- OpenMP errors: Install OpenMP development packages
- Cannot open input file: Check file permissions and paths
- Encoding fails: Ensure sufficient disk space for output video
- Decoding fails: Verify the input file is a valid encoded video
- Encode Error: failed to write header: Make sure you have at least FFMPEG version 8 in-order to use FFV1 encoder on mp4. Otherwise, use mkv instead.
- Encoding streams chunks and uses only a few MB of RAM regardless of input file size.
- Decoding holds all decoded chunks in memory before writing the output file.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.