Kvazaar: an open source HEVC encoder that takes raw YUV and nothing else
An open-source HEVC encoder
At a glance
- What is it?
- Kvazaar is a C implementation of an HEVC encoder released under the 3-clause BSD licence, built for research and development use in HEVC coding rather than as a general purpose conversion tool. It reads raw YUV or Y4M, writes an HEVC bitstream, and its own README says plainly that it is still under development.
- Who is it for?
- Adopt Kvazaar when you are working on HEVC coding itself, need a reference encoder you can build and patch, and are prepared to feed it raw YUV rather than containers. Do not reach for it to transcode arbitrary media files, since the documented path assumes you have already decoded to YUV420 with ffmpeg or libav.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 23 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
An encoder for people working on HEVC
Kvazaar is an open source HEVC encoder licensed under the 3-clause BSD. It is written in C, it lives in the Ultravideo organisation, and the project points at ultravideo.fi for more information about the encoder.
The README sets expectations in a sentence worth quoting early, because it shapes every decision you make with the tool: Kvazaar is still under development, and speed and RD-quality will continue to improve. RD-quality is the rate distortion quality of the codec, the measure of how much quality you keep at a given bitrate, and the sentence says plainly that the encoder is not the finished article in either dimension.
That makes the project a fit for a particular kind of user. Someone working on HEVC coding itself, someone who needs a reference implementation to compare against, someone who wants to read the code and patch it. It is a less natural fit for a production transcoding pipeline, and the rest of this article is largely about the mechanics that show why.
The project is also reachable in the ordinary ways. There is a Linux build badge for the Kvazaar tests workflow and an AppVeyor build status for Windows, and the maintainers are on Libera.Chat in the #ultravideo channel and on Discord.
Raw YUV in, HEVC out, resolution stated by hand
The example in the README is short:
kvazaar --input BQMall_832x480_60.yuv --output out.hevcTwo parameters are mandatory, the input and the output. The subtlety is resolution. If the resolution is not in the filename, or when the input is piped, the input resolution must also be given, for example with `--input-res=1920x1080`.
That is the shape of the whole tool. There is no container demuxing, no audio handling, no scaling. The encoder wants planar YUV frames, and it wants to know the picture size.
The defaults assume the common cases: the default input format is 8-bit yuv420p for 8-bit content and yuv420p10le for 10-bit content. Format and bitdepth can be selected explicitly with `--input-format` and `--input-bitdepth`, where the format options are P420, P422, P444 or P400 and the bitdepth range is 8 to 16. The input file format itself is auto detected from the file ending, and the help message lists y4m, which skips frame headers, and yuv as the two options.
Frame rate is another required piece of information in practice: `--input-fps` takes a numerator over a denominator and defaults to 25, and the source scan type defaults to progressive, with tff and bff available for interlaced material.
Presets cover the speed and quality range
Speed and compression quality are selected with `--preset`, or by setting the options manually. The preset list runs from ultrafast through superfast, veryfast, faster, fast, medium, slow, slower and veryslow to placebo, and medium is the default.
That default is worth pausing on. A tool whose default is the middle of the speed range makes a sensible choice for someone exploring, because the extremes in either direction are usually special cases. ultrafast is for getting an encode out quickly, placebo is for spending as long as it takes to get the best rate distortion result for a given configuration, and the interesting engineering usually happens in between.
The help output also shows the parameters that presets adjust. The quantization parameter `-q, --qp` defaults to 22 and sets the base quality level of the encode. `-p, --period` sets the period of intra pictures and defaults to 64, with 0 meaning only the first picture is intra, 1 meaning every picture is intra, and N meaning every Nth picture is intra. `-r, --ref` sets the number of reference frames in the range 1 to 15 and defaults to 4.
For anyone who has read HEVC specifications, these are the knobs you expect, and for anyone who has not they are a good way to see that an encoder exposes its coding structure rather than hiding it.
GOP structure, including the low delay variant
The `--gop` option controls the group of pictures structure and defaults to 16, which the help message describes as a B-frame pyramid of length 16. A value of 0 disables it, and 8 selects a B-frame pyramid of length 8.
The third form is the interesting one, `lp-<string>`, described as a low-delay P and B frame GOP, with the example `lp-g8d4t2` pointing to a section of the README. Low delay matters for live and interactive use, where the encoder cannot afford to buffer frames in order to produce a better B-frame structure. The README's table of contents lists the LP-GOP syntax as a separate section, which tells you the syntax is more than a single flag.
Other structural parameters follow the same pattern. `--vps-period` controls how often the video parameter set is re-sent, with 0 meaning only with the first frame and N meaning with every Nth intra frame. `--intra-qp-offset` adjusts the quantization parameter for intra frames relative to the rest of the stream.
There are also switches for verification and debugging that make Kvazaar usable in a research setting: `--hash` writes a decoded picture hash in one of none, checksum or md5 form, `--psnr` calculates PSNR for frames and is enabled by default, `--debug` outputs the internal reconstruction, and `--info` adds encoder information as an SEI message. The statistics prefix option writes bits, lambda, distortion and quantization parameter per coding tree unit, and the help message notes these files are meant for debugging and are not written unless the prefix is defined.
Building the encoder with autotools
The README has a build section for each platform it targets, and the table of contents lists the variants: required libraries, range extensions for 4:2:2 and 4:4:4, Autotools, Autotools on MinGW, OS X, Visual Studio, Docker, and a visualisation option marked Windows only.
The repository layout follows a standard GNU arrangement, with configure.ac, Makefile.am, an autogen.sh script, m4/ for the macro files, src/ for the encoder source, bin/ for the command line tool, build/, tools/, doc/ and docs.doxy for the documentation, tests/ for the test suite, examples/ for sample data and rdcost-weight-tool/ for the rate distortion cost tooling.
The examples directory holds a README, a fast coefficient table and a region of interest file, which tells you that the encoder supports region of interest driven coding. There is also a greatest directory in the repository and a LICENSE.EXT.greatest file, alongside the .gitmodules entry, so the unit test framework is carried as a submodule with its own licence file. That is worth noting for anyone shipping the project: the 3-clause BSD terms cover Kvazaar itself, and the third party code it pulls in carries its own conditions.
Two build integrations are configured in the repository, GitLab CI through .gitlab-ci.yml and AppVeyor for Windows, alongside the GitHub Actions workflow for the Linux tests.
The Docker build turns the repository into one encoder image
The Dockerfile in the repository builds Kvazaar from the git checkout, and it is worth reading because it shows the intended deployment shape. The base image is ubuntu:20.04, and the build dependencies are declared in one environment variable:
FROM ubuntu:20.04
MAINTAINER Marko Viitanen <[email protected]>
# List of needed packages to be able to build kvazaar with autotools
ENV REQUIRED_PACKAGES automake autoconf libtool m4 build-essential git pkgconfThe build runs autogen.sh, then configure with `--disable-shared`, then make and make install, all in a single layer. After the install the image removes the build packages and the apt caches so that the resulting image does not carry the toolchain. The entry point is the encoder itself.
The usage comments at the top of that file describe the intended pipeline, and they are the clearest statement of what Kvazaar is for. The idea is to use libav or ffmpeg to input almost any format and convert it to YUV420 for Kvazaar, with audio disabled, and then pipe the raw video into the container and write an HEVC binary out. The example passes the resolution explicitly because the pipe hides it from the filename, and it uses the ultrafast preset with several threads.
So the division of labour is explicit. ffmpeg or libav handles decoding, container parsing and format conversion; Kvazaar handles the HEVC coding itself. If you were hoping for a single command that takes an MP4 and returns an MP4, this is not it.
Where Kvazaar stops, and what to check before building
The boundaries are clear enough to plan around.
The first is scope. Kvazaar encodes. It does not demux, decode, resize, or mux, and there is no library wrapper for another language in the repository beyond the Kvazaar library that the build produces for linking. Any pipeline around it is your code or ffmpeg.
The second is the maturity statement. The README says the project is still under development and that speed and RD-quality will continue to improve, so a configuration tuned against one build may not behave the same against a later one.
The third is that features can be compiled out. The selective encryption options are marked as requiring crypto support to be enabled at compile time, with the default off. If you want encrypted coefficient or motion vector data, that is a build flag decision rather than a runtime flag, and the help message is explicit that the runtime option alone does nothing.
Finally, the release cadence. The releases listed are v2.3.0 on 2024-01-17, v2.3.1 on 2024-04-10 and v2.3.2 on 2025-09-17, and the help message in the README identifies itself as Kvazaar v2.3.2 2025-09-16, so the documented binary and the newest tag are close together. The last push was on 2026-09-30, so the default branch carries work that is not in a tagged release, and the branch is master.
For an organisation that wants to pin and audit, build from the v2.3.2 tag rather than from the branch tip, and check the licence of the code you are bundling alongside it.
Editorial conclusion
Adopt Kvazaar when you are working on HEVC coding itself, need a reference encoder you can build and patch, and are prepared to feed it raw YUV rather than containers. Do not reach for it to transcode arbitrary media files, since the documented path assumes you have already decoded to YUV420 with ffmpeg or libav. Before you start, confirm the licence terms for your distribution, note that crypto support must be enabled at compile time, and check the release you build against: v2.3.2 was released on 2025-09-17 and the last push was on 2026-09-30.
Frequently asked questions
How do I run Kvazaar to encode a YUV file to HEVC?
The minimal invocation is kvazaar --input BQMall_832x480_60.yuv --output out.hevc. If the resolution is not in the filename or you pipe the input, you also have to pass it, for example with --input-res=1920x1080.
Which input formats and bit depths does Kvazaar accept?
The default input format is 8-bit yuv420p, and yuv420p10le for 10-bit content. Format and bitdepth are selectable with --input-format, which accepts P420, P422, P444 and P400, and --input-bitdepth, which accepts 8 to 16.
What presets does Kvazaar offer and which one is the default?
The presets run from ultrafast, superfast, veryfast, faster and fast through medium, slow, slower and veryslow to placebo. Medium is the default.
Does Kvazaar decode video files or handle audio?
No. It takes raw YUV or Y4M input and writes an HEVC bitstream. The Dockerfile comments recommend using ffmpeg or libav to convert almost any input format to YUV420 first, with audio disabled.
What licence is Kvazaar released under?
Kvazaar is licensed under the 3-clause BSD licence, and the repository also carries a LICENSE.EXT.greatest file for the greatest unit test framework that it pulls in as a submodule.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ultravideo-kvazaar)Was this useful?