# AVIF

Canonical URL: https://encode.wiki/codecs/images/avif/
Content version: ca42e61ede0a24f789d7287a0001244ad22f4abf
Status: current
License: CC BY-SA 4.0
Checksum (SHA-256): 6649f626c8ccebb5f8e813163a9928a12fcd593643fd26f72a73841ac515f97f

AVIF 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](/codecs/images/heic/); the payload is the [AV1](/codecs/video/av1/) video codec, so any AV1 encoder can in principle produce AVIF images.

## Strengths and weaknesses

**Strengths**

- Very good lossy compression on photos and on flat graphics. At low and medium bitrates it beats [JPEG](/codecs/images/jpeg/) and [WebP](/codecs/images/webp/) by a wide margin; against [JPEG XL](/codecs/images/jxl/) 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 --progressive` can 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

| 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](https://github.com/mdn/browser-compat-data/blob/main/mediatypes/image/avif.json) and Android's [supported media formats](https://developer.android.com/media/platform/supported-formats). Desktop OS thumbnailers, editors and messaging apps are patchier than browsers; see [image and audio support](/reference/image-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

`avifenc` from [libavif](https://github.com/AOMediaCodec/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).

```sh
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

`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

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](/reference/metrics/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

| 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

- **Alpha** is stored as a separate monochrome AV1 image, so it has its own quality (`--qalpha`). Use `-p` only if you intend premultiplied (associated) alpha.
- **HDR**: keep the source's real transfer function and primaries (`--cicp 9/16/9` for PQ BT.2020, `9/18/9` for HLG) and encode at 10 bit or more. Tagging SDR pixels as PQ does not make them HDR. In builds with gain-map support, `avifenc` converts 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

- A lossless AV1 stream does not make the file lossless: RGB→YUV conversion and 4:2:0 are lossy unless you use `-l`.
- `avifenc` copies Exif, XMP and ICC from PNG and JPEG input and turns the Exif orientation into AVIF `irot`/`imir` transforms. Use `--ignore-exif`, `--ignore-xmp` or `--ignore-icc` to 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

Any AV1 encoder can produce AVIF; see [aomenc](/tools/software-encoders/aomenc/), [SVT-AV1](/tools/software-encoders/svt-av1/) and [rav1e](/tools/software-encoders/rav1e/). Rachel Barker's [tinyavif](https://github.com/rachelplusplus/tinyavif) is a minimal AVIF encoder written to show how AVIF and AV1 work, not for production.

## Related pages

- [AV1](/codecs/video/av1/) is the video codec underneath.
- [JPEG XL](/codecs/images/jxl/) has lossless JPEG recompression and a stronger lossless and high-quality story.
- [WebP](/codecs/images/webp/) is the older, faster, 8-bit-only alternative.
- [HEIC](/codecs/images/heic/) uses the same container with HEVC.

## Full option reference

The tables below are the full `avifenc` and libheif AVIF plugin parameter references. [Reading option tables](/reference/encoder-parameters/) explains the Default column.

## avifenc 1.4.2 complete parameter reference

<details>
<summary>INPUT to --target-size</summary>

| 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. |

</details>

<details>
<summary>--progressive to --irot</summary>

| 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. |

</details>

<details>
<summary>--imir to --</summary>

| 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. |

</details>

## 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](/codecs/images/heic/#heif-enc-1236-complete-frontend-reference).

### 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

| 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

| 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. |
