AVIF
37c3317fd058; modified for Encode Wiki · CC BY-SA 4.0AVIF is AV1 intra-frame coding stored in a HEIF/ISO-BMFF container. It is the format to reach for when you want the smallest lossy images that every current browser can display, and it also gives you 10- and 12-bit depth, HDR signalling, alpha and animation. It is a poor choice for lossless archival, and encoding is slower than JPEG or WebP.
The container is the same family as HEIC; the payload is the AV1 video codec, so any AV1 encoder can in principle produce AVIF images.
Strengths and weaknesses
Section titled “Strengths and weaknesses”Strengths
- Very good lossy compression on photos and on flat graphics. At low and medium bitrates it beats JPEG and WebP by a wide margin; against JPEG XL it usually produces smaller files at web-delivery quality, while JPEG XL pulls ahead at very high quality and in lossless.
- 8-, 10- and 12-bit, 4:2:0 / 4:2:2 / 4:4:4 / monochrome, wide gamut and HDR signalling (PQ, HLG), ICC or CICP colour, and a separate alpha plane.
- Animation using real inter-frame video coding, which makes it a far better animated format than GIF or animated WebP for most clips.
- Royalty-free, and supported by every current browser.
Weaknesses
- Slower encoding than JPEG, WebP or JPEG XL. libaom at its slowest speeds (
-s 0–3) and on large images takes seconds to minutes per file. - Weak lossless mode. It is usually larger than lossless WebP or JPEG XL, and sometimes larger than PNG.
- No JPEG-style progressive decode: a plain AVIF shows nothing until enough of the file has arrived. Layered “progressive” files exist in the AVIF 1.2 spec and
avifenc --progressivecan write them, but check your target decoders before relying on them. - Smooth gradients can band and fine texture can smear at low bitrates, and 4:2:0 bleeds saturated colour edges and small coloured text.
- Very large images need tiling or a grid, which costs a little efficiency and can leave faint seams.
Support
Section titled “Support”| Platform | Still AVIF | Notes |
|---|---|---|
| Chrome | 85+ | Other Chromium browsers follow their Chromium version |
| Firefox | 93+ | Animated AVIF from Firefox 113 |
| Edge | 121+ | |
| Safari | 16.4+ on macOS, 16.1+ on iOS | Safari 16.1–16.3 on macOS worked only on Ventura |
| Android system decoder | Android 12+ (8-bit) | 10-bit decoding is optional per device |
Browser versions are from MDN’s AVIF data and Android’s supported media formats. Desktop OS thumbnailers, editors and messaging apps are patchier than browsers; see image and audio support for how to check a given file.
Profiles matter less than they used to, but they still bound what a conservative decoder accepts. The Baseline brand (MA1B) is AV1 Main profile (8/10-bit, 4:2:0 or monochrome) at level 5.1 or lower; the Advanced brand (MA1A) is High profile (adds 4:4:4) up to level 6.0. Larger images are built from a grid of tiles.
Encode with avifenc
Section titled “Encode with avifenc”avifenc from libavif is the standard encoder. It takes PNG, JPEG or Y4M input and calls an AV1 backend (libaom, SVT-AV1 or rav1e, whatever your build includes).
avifenc -q 65 -s 4 input.png output.avif-q and -s are the two knobs you will actually turn. The defaults are -q 60 and -s 6. Pick the quality by eye at a fast speed, then encode the final file at -s 4 or slower; speeds below 4 cost a lot of time for a small gain.
| Option | What it does |
|---|---|
-q 0..100 | Colour quality; 100 is lossless AV1 coding. Not comparable between backends or libavif releases. |
--qalpha 0..100 | Alpha quality, inherited from -q unless set. Use --qalpha 100 if the alpha edge must stay clean. |
-s 0..10 | Speed; lower is slower and smaller. Default 6. |
-d 8/10/12 | Output bit depth; follows 8-bit input by default. Use 10 for HDR and high-bit-depth sources. -d 10 is also common for 8-bit sources because it reduces banding in smooth gradients. |
-y 444/422/420/400 | Chroma format. auto gives 4:4:4 for PNG, keeps the subsampling of a JPEG and uses 4:0:0 for greyscale PNG. |
--sharpyuv | Sharper RGB→4:2:0 conversion; only does anything with -y 420. |
-c aom/svt/rav1e | Choose the backend. |
-j N | Worker threads (default all). |
-a KEY=VALUE | Pass a backend option, e.g. -a tune=iq. libaom keys can be limited to one plane with color: or alpha:. |
-l | Lossless: sets RGB-identity, full-range, 4:4:4 defaults. |
--cicp P/T/M, --icc | Signal colour primaries/transfer/matrix or attach an ICC profile. |
Chroma: 4:4:4 or 4:2:0
Section titled “Chroma: 4:4:4 or 4:2:0”avifenc keeps 4:4:4 for PNG input, and libaom handles 4:4:4 well, so the extra chroma usually costs little. Keep it for screenshots, UI, line art and coloured text, where 4:2:0 visibly bleeds colour. Use -y 420 (plus --sharpyuv) when you need the smallest photo files or files that stay within the Baseline brand and AV1 Main profile that hardware decoders support.
Tuning
Section titled “Tuning”Since libavif 1.4.0, avifenc with libaom 3.13 or newer encodes still images (YUV, not RGB-matrix) with tune=iq by default, and maps -q to quantizers with a formula designed for it. tune=iq is libaom’s still-image mode, added in 3.12: it was developed with SSIMULACRA2 as a guide and checked visually, and uses Variance Boost, adaptive CDEF and quantization matrices. Alpha is encoded with tune=psnr, because tune=ssim causes ringing on alpha.
The older recipe of -a tune=ssim -a end-usage=q -a cq-level=… is obsolete: use -q and leave the tune alone. Because tune=iq was shaped around SSIMULACRA2, check comparisons against other tunes by eye as well.
Backends
Section titled “Backends”| Backend | Notes |
|---|---|
| libaom | The default and the usual best choice for stills: full chroma and bit-depth support, tune=iq, and the most intra-coding work behind it. |
| SVT-AV1 | Faster, but libavif’s SVT adapter is 4:2:0 only, 8/10-bit. A PNG defaults to 4:4:4, so -c svt without -y 420 fails with “Only support 420 now”. The libaom -a keys do not apply. |
| rav1e | Works, but is slow for stills and lacks libaom’s still-image tuning. |
libheif’s heif-enc --avif is a second frontend with the same backends and its own defaults (quality 50); its plugin parameter tables are in the reference below. AVIF is also writable from FFmpeg and ImageMagick, which go through libavif or libheif.
Alpha, HDR and animation
Section titled “Alpha, HDR and animation”- Alpha is stored as a separate monochrome AV1 image, so it has its own quality (
--qalpha). Use-ponly if you intend premultiplied (associated) alpha. - HDR: keep the source’s real transfer function and primaries (
--cicp 9/16/9for PQ BT.2020,9/18/9for HLG) and encode at 10 bit or more. Tagging SDR pixels as PQ does not make them HDR. In builds with gain-map support,avifencconverts gain maps embedded in JPEG input (--qgain-map,--ignore-gain-map). - Animation: pass several PNGs with
--fps, or pipe Y4M from FFmpeg:ffmpeg -i in.mp4 -pix_fmt yuv420p -f yuv4mpegpipe - | avifenc --stdin out.avif. Firefox plays animated AVIF from version 113.
Pitfalls
Section titled “Pitfalls”- A lossless AV1 stream does not make the file lossless: RGB→YUV conversion and 4:2:0 are lossy unless you use
-l. avifenccopies Exif, XMP and ICC from PNG and JPEG input and turns the Exif orientation into AVIFirot/imirtransforms. Use--ignore-exif,--ignore-xmpor--ignore-iccto drop them; dropping the ICC profile of a wide-gamut source changes its colours.- Re-encoding an AVIF from a previous lossy AVIF compounds loss; keep the original source.
Other encoders
Section titled “Other encoders”Any AV1 encoder can produce AVIF; see aomenc, SVT-AV1 and rav1e. Rachel Barker’s tinyavif is a minimal AVIF encoder written to show how AVIF and AV1 work, not for production.
Related pages
Section titled “Related pages”- AV1 is the video codec underneath.
- JPEG XL has lossless JPEG recompression and a stronger lossless and high-quality story.
- WebP is the older, faster, 8-bit-only alternative.
- HEIC uses the same container with HEVC.
Full option reference
Section titled “Full option reference”The tables below are the full avifenc and libheif AVIF plugin parameter references. Reading option tables explains the Default column.
avifenc 1.4.2 complete parameter reference
Section titled “avifenc 1.4.2 complete parameter reference”INPUT to —target-size
| Parameter / aliases | Type or accepted values | Default | Purpose and constraints |
|---|---|---|---|
INPUT | path(s) | required | JPEG, PNG or Y4M input. Several inputs make an animated sequence, or the layers/cells with —layered/—grid. |
OUTPUT | path | required, unless —output is used | Output .avif. Taken from the last positional argument unless —output is given. |
--help, -h | action | not requested | Print usage and the compiled-in codec versions. |
--version, -V | action | not requested | Print the libavif and codec library versions. |
--qcolor, -q, --qcolor:u, --qcolor:update, -q:u, -q:update | integer 0–100 | 60 | Colour quality, 0–100. 100 is lossless AV1 coding, though RGB→YUV conversion can still be lossy. The :u forms apply only to the inputs after them. |
--qalpha, --qalpha:u, --qalpha:update | integer 0–100 | same as qcolor | Alpha quality, 0–100. Follows —qcolor unless set. |
--speed, -s | 0–10, default or d | 6 | Encoder speed, 0 (slowest) to 10, or default/d for the codec’s own default. Slower is smaller. |
--jobs, -j | positive integer or all | all detected CPUs | Worker threads, or all. What it controls depends on the codec. |
--no-overwrite | flag | false | Fail instead of replacing an existing output file. |
--output, -o | path | final positional filename | Output path, instead of the last positional argument. |
--lossless, -l | flag | false | Set lossless defaults: quality 100, full range, 4:4:4 and identity matrix. Warns when the input can’t be stored losslessly. |
--depth, -d | D[,extension] | input-dependent | Output bit depth, 8, 10 or 12. A second value (8,8 / 12,4 / 12,8) adds a hidden extension image for 16-bit output. Y4M keeps its own depth. |
--yuv, -y | auto, 444, 422, 420, 400 | auto | Chroma format: auto, 444, 422, 420 or 400. auto keeps a JPEG’s subsampling, uses 400 for greyscale PNG and 444 otherwise; Y4M keeps its format. |
--premultiply, -p | flag | false | Multiply colour by alpha before encoding and mark alpha as premultiplied. Changes pixel values. |
--sharpyuv | flag | false | Sharper RGB→4:2:0 conversion (needs libsharpyuv). No effect on Y4M or non-4:2:0 output. |
--stdin | flag | false | Read one stream (Y4M by default) from standard input. No other input paths are allowed; the output path is still required. |
--input-format | auto, jpg, jpeg, png, y4m | auto for paths; y4m for stdin | Force the input type: jpeg/jpg, png, y4m or auto. Needed only when the extension is misleading. |
--cicp, --nclx | P/T/M integers | 2/2/6 before input-specific handling | Colour primaries/transfer/matrix as three numbers (H.273); 2 means unspecified. Tags the file; samples are not converted. |
--range, -r | full/f or limited/l | full for JPEG/PNG; retained for Y4M | YUV range, full or limited. Y4M input keeps its own range. |
--target-size | positive bytes | disabled | Aim for this file size in bytes by searching over quality. Up to 7× slower; conflicts with fixed —qcolor/—qalpha. |
—progressive to —irot
| Parameter / aliases | Type or accepted values | Default | Purpose and constraints |
|---|---|---|---|
--progressive | flag | false | Write a two-layer image that can render progressively from one input. Needs —qcolor of at least 10; support is limited. |
--layered | flag | false | Encode two to four inputs as layers of one image. Not an animation. |
--grid, -g | columns x rows | disabled | Write a grid of COLSxROWS cells, from identical inputs or one image split evenly. |
--codec, -c | build-specific encoder ID | auto | Pick the AV1 encoder, for example aom, rav1e or svt. Decoder-only IDs can’t encode. |
--exif | payload path | preserve input metadata if present | Use this Exif payload instead of any embedded Exif. |
--xmp | payload path | preserve input metadata if present | Use this XMP payload instead of any embedded XMP. |
--icc | profile path | preserve input profile if present | Use this ICC profile instead of any embedded one. Tags the image; samples are not converted. |
--timescale, --fps | positive integer | 30; may inherit Y4M timing | Sequence ticks per second. With one-tick frames this is the frame rate. Y4M frame rate is used if unset. |
--creation-time | nonnegative Unix seconds | 0: use modification time | Sequence creation time in Unix seconds. 0 uses the modification time. |
--modification-time | nonnegative Unix seconds | 0: use current time | Sequence modification time in Unix seconds. 0 uses the current time. |
--keyframe, -k | integer | 0: disabled | Maximum keyframe interval for sequences, in frames. 0 disables the limit. |
--ignore-exif | flag | false | Drop embedded Exif. |
--ignore-xmp | flag | false | Drop embedded XMP. |
--ignore-icc, --ignore-profile | flag | false | Drop the embedded ICC profile. |
--ignore-gain-map | build-gated flag | false | Drop an embedded JPEG gain map. Needs a libavif built with gain-map conversion. |
--qgain-map | build-gated integer 0–100 | 60 | Gain map quality, 0–100. Needs a gain-map build; takes no :u form. |
--pasp | H,V positive spacing | absent | Pixel aspect ratio as H,V. Metadata only. |
--crop | x,y,width,height | absent | Clean-aperture crop as x,y,width,height. Applied at display time; pixels are not removed. |
--clap | eight rational components | absent | Clean aperture as eight numerator/denominator values: width, height, horizontal offset, vertical offset. |
--irot | integer 0–3 | absent | Rotation in 90° steps anticlockwise (0–3). Stored as a transform. |
—imir to —
| Parameter / aliases | Type or accepted values | Default | Purpose and constraints |
|---|---|---|---|
--imir | 0 or 1 | absent | Mirror axis: 0 top-to-bottom, 1 left-to-right. Stored as a transform. |
--clli | MaxCLL,MaxPALL | absent | MaxCLL,MaxPALL content light level metadata. Doesn’t make the image HDR. |
--repetition-count | nonnegative integer or infinite | infinite | How many times a sequence plays, or infinite. |
--tilerowslog2, --tilerowslog2:u, --tilerowslog2:update | integer 0–6 | 0 before automatic tiling | log2 of the number of tile rows (0–6). Setting it switches to manual tiling. |
--tilecolslog2, --tilecolslog2:u, --tilecolslog2:update | integer 0–6 | 0 before automatic tiling | log2 of the number of tile columns (0–6). Setting it switches to manual tiling. |
--autotiling, --autotiling:u, --autotiling:update | flag | true | Choose AV1 tiling automatically. This is the starting mode; it is separate from a HEIF grid. |
--min, --min:u, --min:update | deprecated quantizer 0–63 | 0 | Deprecated minimum quantizer (0–63). Use —qcolor. |
--max, --max:u, --max:update | deprecated quantizer 0–63 | 63 | Deprecated maximum quantizer (0–63). Use —qcolor. |
--minalpha, --minalpha:u, --minalpha:update | deprecated quantizer 0–63 | 0 | Deprecated minimum alpha quantizer (0–63). Use —qalpha. |
--maxalpha, --maxalpha:u, --maxalpha:update | deprecated quantizer 0–63 | 63 | Deprecated maximum alpha quantizer (0–63). Use —qalpha. |
--scaling-mode, --scaling-mode:u, --scaling-mode:update | positive N[/D] | 1/1 | Frame or layer scaling as N[/D], for example 1/2. |
--duration, --duration:u, --duration:update | positive clock ticks | 1; may inherit Y4M timing | Frame duration in timescale ticks for the following inputs. Applies with or without :u. |
--advanced, -a, --advanced:u, --advanced:update, -a:u, -a:update | KEY[=VALUE], repeatable | none | Pass KEY[=VALUE] straight to the codec, for example -a tune=ssim. Repeatable. Keys are the codec’s own. |
--mini | build-gated flag | false | Compact-header writer. Needs a build with AVIF_ENABLE_EXPERIMENTAL_MINI; not in current binaries. |
-- | separator | not used | End of options; later arguments are filenames. |
libheif AVIF plugin references
Section titled “libheif AVIF plugin references”Plugin parameters for heif-enc --avif -e aom|rav1e|svt, set with -p NAME=VALUE. The full heif-enc frontend reference is on the HEIC page.
libheif AOM plugin parameters
Section titled “libheif AOM plugin parameters”| Parameter / aliases | Type or accepted values | Default | Purpose and constraints |
|---|---|---|---|
realtime | boolean | false | Use libaom’s realtime mode instead of good-quality mode. Faster, larger. |
speed | integer 0–9 | 6 | libaom cpu-used, 0 is slowest. Realtime mode changes what the values mean. |
threads | integer 1–64 | CPU count, max 64 (4 if undetectable) | Worker threads. |
quality | integer 0–100 | 50 | Colour quality. |
lossless | boolean | false | Lossless colour coding. |
chroma | 420, 422 or 444 | 420 | Chroma subsampling. Lossless RGB needs 444. |
tune | auto, psnr, ssim or iq | auto | auto picks by image type (still, sequence, alpha). iq can’t be combined with lossless. |
min-q | integer 0–63 | 0 | Lowest quantizer index the encoder may use. |
max-q | integer 0–63 | 63 | Highest quantizer index the encoder may use. |
alpha-quality | integer 0–100 | same as quality | Alpha quality. Follows the colour quality if unset. |
alpha-min-q | integer 0–63 | same as min-q | Lowest alpha quantizer. Follows min-q if unset. |
alpha-max-q | integer 0–63 | same as max-q | Highest alpha quantizer. Follows max-q if unset. |
lossless-alpha | boolean | false | Code alpha losslessly while colour stays lossy. |
auto-tiles | boolean | false | Let libaom choose the tile layout. |
enable-intrabc | boolean | true | Allow intra block copy, which helps screen content. |
libheif rav1e plugin parameters
Section titled “libheif rav1e plugin parameters”| Parameter / aliases | Type or accepted values | Default | Purpose and constraints |
|---|---|---|---|
speed | integer 0–10 | 8 | rav1e speed, 0 is slowest. |
threads | integer 1–16 | 4 | Worker threads. |
tile-rows | 1, 2, 4, 8, 16, 32, 64 | 4 | Number of tile rows (a count, not the log2 value avifenc uses). |
tile-cols | 1, 2, 4, 8, 16, 32, 64 | 4 | Number of tile columns (a count, not log2). |
chroma | 420, 422 or 444 | 420 | Chroma subsampling. |
min-q | integer 0–255 | 0 | Lowest quantizer rav1e may use. |
quality | integer 0–100, -q only | 50 (set by heif-enc) | Set with heif-enc -q and mapped to a 0–255 quantizer. Not in the parameter list, so -p quality= is rejected. |
lossless | not settable | unsupported | No lossless mode: -L falls back to lossy with a warning, and -p lossless= is rejected. |
libheif SVT-AV1 plugin parameters
Section titled “libheif SVT-AV1 plugin parameters”| Parameter / aliases | Type or accepted values | Default | Purpose and constraints |
|---|---|---|---|
speed | integer 0–13 | 12 | SVT-AV1 preset. Lower is slower and smaller. |
threads | integer 1–16 | 4 | Thread hint, not a guaranteed worker count. |
tile-rows | 1, 2, 4, 8, 16, 32, 64 | 4 | Number of tile rows. |
tile-cols | 1, 2, 4, 8, 16, 32, 64 | 4 | Number of tile columns. |
quality | integer 0–100 | 50 | Quality, converted to a QP unless qp is set. |
lossless | boolean, SVT ≥3 | false | Lossless coding, SVT-AV1 3 or newer. heif-enc -L on RGB input (PNG, JPEG) exits with ‘Unsupported encoder parameter’ because it also sets chroma=444, which this plugin lacks. |
qp | integer 0–63 | unset: derived from quality | Quantizer. Overrides quality when set. |
min-q | integer 0–63 | 0 | Lowest quantizer SVT-AV1 may use. |
max-q | integer 0–63 | 63 | Highest quantizer SVT-AV1 may use. |
tune | vq, psnr, ssim, iq, ms-ssim | psnr | SVT-AV1 tune: vq, psnr, ssim, iq, ms-ssim. iq and ms-ssim need SVT-AV1 4 or newer. |
chroma | fixed 420 | 420 | Not a parameter: the plugin always encodes YCbCr 4:2:0, and -p chroma= is rejected. |