cavif encodes PNG and JPEG to AVIF without leaving Rust
AVIF image creator in pure Rust
At a glance
- What is it?
- The kornelski/cavif-rs project is a command line AVIF encoder built on rav1e and avif-serialize, so it needs no C toolchain to produce AVIF files. It is fast, deliberately lossy, and it gives you a quality and speed dial instead of a lossless mode.
- Who is it for?
- Adopt cavif when you need to batch convert PNG or JPEG assets to AVIF on a machine where installing a C AV1 toolchain is the part you want to avoid, and when lossy output at a chosen quality is acceptable. Do not adopt it for archival work, for assets that must stay lossless, or for images where the default clearing of colour in fully transparent pixels matters, since --dirty-alpha exists for that reason and is marked not recommended.
- 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 48 days ago.
- What is it written in?
- Mainly Rust, 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
Pure Rust means no system AV1 encoder to install
The project description is short and the reason it matters is specific. cavif is an AVIF image creator written in Rust, and it is built on rav1e, the Rust AV1 encoder, and avif-serialize, the Rust AVIF container writer, both reached through the ravif crate. Because the whole pipeline stays in Rust, there is no external binary to install, no libaom to compile, no C toolchain in the build path. That is a real operational difference from the other common route to AVIF, which is a native encoder shipped as a system package or a build from source with its own dependencies. The Cargo.toml makes the stack explicit: clap 4.6.6 for the command line with default-features off and features for colour, suggestions, wrap_help, std and cargo; imgref for image references; load_image for decoding input; rgb for pixel handling; rayon 1.12.0 for parallelism; and ravif 0.13 pulled from a local path with default-features off and the threading feature enabled. The repository even vendors ravif as a workspace member under ravif/, so the encoder dependency lives in the tree rather than being fetched from a registry.
One command converts a PNG, and the output lands next to the input
The usage section is short because the default does the obvious thing. You run the binary in a terminal, and the README notes you do not need to type the path since terminals accept file drag and drop.
cavif image.pngThat produces image.avif. Quality is adjustable on a 1 to 100 scale.
cavif --quality 60 image.pngThe advanced usage form shows the full argument shape.
cavif [OPTIONS] IMAGES...Multiple images can be given in one invocation, and the README says encoding is multi threaded, so the more the better. The multi threading is not incidental: the Cargo.toml enables the threading feature on ravif and pulls in rayon, so the parallelism is in the encoder rather than in a wrapper loop that spawns processes.
There is no lossless mode, and the README says so plainly
This is the single most important constraint for anyone choosing a tool. The --quality option is documented as quality from 1 (worst) to 100 (best) with a default of 80, and the README states that the numbers are only a rough approximation of the JPEG quality scale, with a link to a page on fair codec comparison. Then comes the blunt part: there is no lossless compression support, and 100 just gives unreasonably bloated files. So the tool's whole design assumes you are willing to throw pixels away. For web imagery, icons with photographic detail, and texture atlases that is a reasonable assumption. For a scanned document, a medical image, a design master or anything you may need to recompress later, it is a disqualifying one, and no flag will change it. The quality knob runs from 1 to 100 but only ever buys you a different point on the lossy curve, never a lossless one.
Speed 1 to 10 trades size for time, with stated breakpoints
The second dial is --speed, described as encoding speed between 1 (best, but slowest) and 10 (fastest, but a blurry mess), with a default of 4. The README is unusually specific about where the trade-off lies, which makes it easy to pick a setting. Speeds 1 and 2 are said to be unbelievably slow but make files roughly 3 to 5 percent smaller. Speeds 7 and above degrade compression significantly and are not recommended. So the usable band is narrow. Values 3 to 6 are the reasonable working range around the default of 4, 1 and 2 are for a final archive pass when size matters more than your afternoon, and 7 through 10 are for previews. Because encoding is multi threaded, the wall clock cost of the slow settings is partly mitigated by throwing several images at the tool at once, which is exactly what the README recommends.
Three colour space flags exist for the cases the defaults get wrong
The remaining options are described as additional options that tweak AVIF colour space, with the note that the defaults in cavif are chosen to be the best and these options should be used only when you know it is necessary. --dirty-alpha preserves the RGB values of fully transparent pixels, and it is marked not recommended, because by default the irrelevant colour of transparent pixels is cleared to avoid wasting space. That default costs you nothing and saves bytes, unless you have a workflow that composites those pixels later. --color=rgb encodes in RGB instead of YCbCr, which makes colours closer to lossless but makes files larger, and is meant for cases where you need to avoid even the smallest colour shift. --depth=8 encodes at 8-bit colour depth instead of 10-bit, giving a slightly worse quality to compression ratio in exchange for more compatibility. The other three options are about file handling rather than pixels: --overwrite replaces files when an .avif already exists, since by default existing files are left untouched, -o path writes to a chosen path or, with multiple inputs, treats the path as a directory, and --quiet suppresses all output during conversion.
Installing from a release zip or from crates.io, both documented
There are two documented routes and the README treats them separately. The first is the release download, linked from the project page. The pre-built zip includes a portable static executable with no dependencies that runs on any Linux distro, and it also includes executables for macOS and Windows. For a build from source you need Rust 1.90 or later, preferably installed through rustup, and then two commands in a terminal.
rustup update
cargo install cavifThe Cargo.toml enforces the same floor on anyone depending on the crate rather than the binary: rust-version is set to 1.90 and the edition is 2024. That is a hard constraint for CI images and older toolchains, and it is worth checking before you schedule a rebuild.
The release profile trades debuggability for a small binary
Two entries in Cargo.toml tell you what the shipped executable prioritises. The release profile sets opt-level = 3, panic = "abort", debug = false, lto = true and strip = true. Link time optimisation and symbol stripping are the usual choices for a distributed binary, and panic = abort means the program will not unwind on a panic, which reduces binary size but changes the failure behaviour of any code that relied on catching one. The dev profile is deliberately not unoptimised: opt-level is 1 with debug = 1, and there is a dev profile package wildcard setting opt-level = 2 for all dependencies, so even a debug build of this tool runs its dependencies with some optimisation. The default feature set is asm, which maps to ravif/asm, and an obsolete static feature is still present in the manifest. Those are the details that matter if you are profiling an encode or if a native assembly path is a problem on your platform, because the Cargo.toml does not document an explicit way to turn the asm feature off. On upkeep, the Cargo.toml version field reads 1.8.1 while the most recent release tag is v1.8.0, dated 2026-08-30, and the last push was on 2026-09-05, so expect the tag and the manifest to move independently for a while.
Editorial conclusion
Adopt cavif when you need to batch convert PNG or JPEG assets to AVIF on a machine where installing a C AV1 toolchain is the part you want to avoid, and when lossy output at a chosen quality is acceptable. Do not adopt it for archival work, for assets that must stay lossless, or for images where the default clearing of colour in fully transparent pixels matters, since --dirty-alpha exists for that reason and is marked not recommended. Verify first by running cavif --quality 60 on a real asset and comparing it against another encoder, then check the file sizes and colour shift yourself, since the README warns that the quality numbers are only a rough approximation of the JPEG scale.
Frequently asked questions
How do I install cavif?
The README points to the latest release download, and says the pre-built zip includes a portable static executable with no dependencies that runs on any Linux distro, plus executables for macOS and Windows. To build from source you need Rust 1.90 or later and run rustup update followed by cargo install cavif.
Can cavif produce lossless AVIF files?
No. The README states there is no lossless compression support, and that a quality value of 100 just gives unreasonably bloated files. The quality option runs from 1 (worst) to 100 (best) with a default of 80.
What does the --speed option do in cavif?
It sets encoding speed between 1 (best, but slowest) and 10 (fastest, but a blurry mess), with a default of 4. The README says speeds 1 and 2 are unbelievably slow but make files around 3 to 5 percent smaller, while speeds 7 and above degrade compression significantly and are not recommended.
How do I convert several images at once with cavif?
Pass multiple files in one invocation, using the form cavif [OPTIONS] IMAGES.... Encoding is multi threaded according to the README, so it says the more images the better. You can also set -o path, which is interpreted as a directory when multiple input files are given.
Why does cavif change the colour of fully transparent pixels?
By default the irrelevant colour of transparent pixels is cleared to avoid wasting space. The --dirty-alpha option preserves the RGB values of fully transparent pixels, but the README marks it as not recommended.
What licence is cavif released under?
The crate and repository are licensed under BSD-3-Clause, and the licence is recorded in Cargo.toml alongside the LICENSE file in the repository root. The package description is Encodes images in AVIF format (image2avif converter) using a pure-Rust encoder.
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/kornelski-cavif-rs)Was this useful?