A small C CLI that transcodes a source video into adaptive bitrate streaming outputs. It uses ffprobe to read metadata, ffmpeg to transcode and extract assets, and gpac to package the final HLS or HLS + DASH outputs.
The tool takes one input video and produces:
- Resolution-specific MP4 variants
- No-audio variants for packaging
- An AAC audio track when the source has audio
- An HLS playlist, or combined HLS + DASH playlists
- A thumbnail image
It skips any resolution that is higher than the source video, so it does not upscale beyond the input.
Logs are written to stderr with timestamps and levels.
I am happy to get any help or contributions to the project.
- Implement the basic functionality by calling ffmpeg (processing) and gpac (packaging) commands.
- Extend the functionality to support gpac filters for more advanced processing.
- Remove the usage of
ffprobeandgpaccommands in favor of using the libraries directly (libgpac, libavformat, libavcodec, and libavutil). - Add more practical test cases for the tool to ensure it works as expected.
- Make sure that the tool can handle large files (10GB+) and long videos (10 hours+).
- Make sure that the tool can handle different video formats (H.264, H.265, VP9, AV1, etc.), Currently it only supports H.264.
- Make sure that the tool handle internal errors correctly specially when calling libraries directly.
- Add more CLI options for more advanced processing (thumbnail generation, audio extraction, etc.).
- Package the tool as a Docker image.
- Package the tool as a static binary for Linux. (this might be not possible at the moment).
Install these tools and make sure they are available in PATH:
ffmpeggpac
The project can be built against either ffmpeg.c or gpac.c through the IMPL variable in the Makefile.
On Windows, you can follow the instructions for installing gpac and ffmpeg from their official websites.
On macOS, a typical setup is:
brew install ffmpeg gpacOn Ubuntu, a typical setup is:
sudo apt-get install ffmpeg gpacWarning: The version of gpac in the default Ubuntu repository is too old. You need to install the latest version from the PPA.
To build the tool:
make buildIMPL options are available:
IMPL=libgpac: Build with the libgpac-backed implementation. (Default, Recommended)IMPL=ffmpeg: Build with the ffmpeg-backed implementation.IMPL=gpac: Build with the gpac-backed implementation.
Run the unit test binary with:
make testThis compiles the test binary and runs a few focused checks for CLI helpers and resolution parsing.
./video-processor <source_video> [options]-d <path>: output directory-t <type>: packaging type, eitherhlsorhls_and_dash-r <list>: comma-separated resolution list-f: force overwrite of an existing output directory
- If
-dis omitted, the output directory is derived from the input file name. - If
-tis omitted, the output type defaults tohls. - If
-ris omitted, all supported resolutions are enabled:240p360p480p720p1080p
- If the output directory already exists, the command fails unless
-fis used.
Process a video with the default settings:
./video-processor sample.mp4Write outputs to a custom directory:
./video-processor sample.mp4 -d output/streamGenerate only selected resolutions:
./video-processor sample.mp4 -r 480p,720p,1080pGenerate both HLS and DASH outputs:
./video-processor sample.mp4 -t hls_and_dashForce overwrite an existing output directory:
./video-processor sample.mp4 -f -d output/streamFor an input named sample.mp4, the output directory will contain artifacts like:
sample/
├── play_240p.mp4
├── play_360p.mp4
├── play_audio.aac
├── playlist.m3u8
├── thumbnail.jpg
├── video_240p/
└── video_360p/
If -t hls_and_dash is used, the main playlist becomes playlist.mpd.
Temporary *_noaudio.mp4 files are removed after packaging.
When -f is provided, an existing output directory is removed before processing starts.
You can open playlist.m3u8 in either mpv or VLC:
mpv sample/playlist.m3u8In VLC, use "Open Network Stream" or open the file directly and point it to sample/playlist.m3u8.
Supported resolution IDs are:
240p360p480p720p1080p
Each preset has its own width, height, CRF, bitrate, maxrate, and buffer settings in src/resolutions.c.
- The CLI keeps the first argument as the input video path.
- If the output directory already exists, the program exits unless
-fis provided. - Resolutions higher than the source height are skipped.
- Audio is extracted only when the source contains an audio stream, and mkv inputs are handled by re-encoding to AAC.
- Logging uses a small stderr logger with
INFO,DEBUG,WARN,ERROR, andFATALlevels. - Packaging is done with external tools instead of native libraries, which keeps the C code small and easy to follow.