=== WebP & AVIF Offload ===
Contributors: smallapis
Tags: webp, avif, convert webp, image optimization, optimize images
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.5.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Convert images to WebP and AVIF. Unlimited WebP on your own server, free, no account. AVIF even when your host cannot make it.

== Description ==

Your images are the heaviest thing on your pages. This plugin makes a WebP and
an AVIF copy of each one and serves whichever the visitor's browser prefers,
without touching your originals.

**Install it, answer two questions, press one button.** The setup opens by
itself, tells you what your server can do, and converts your library while you
watch. It takes about a minute.

= What you actually get =

* **WebP, unlimited, free, on your own server.** No account, no key, no monthly
  credits, no "first 100 images". Your server already knows how to do this; the
  plugin just uses it. About a third off every photograph.
* **AVIF even when your host cannot produce it.** AVIF needs libavif compiled
  into GD, or ImageMagick 7.0.10-58 and up. On shared hosting that is almost
  never the case and only the hosting company can change it. So the plugin can
  hand that one job to a conversion service and bring the file straight back —
  roughly half the weight of WebP again on photographs.
* **A dry run before anything happens.** The scan reads your whole library
  without writing a byte and tells you how many files would be converted, what
  that should save, and exactly which images your rules are leaving out and why.
* **Proof that it worked.** One button downloads a converted file from your own
  site, the way a browser would, and checks the status, the bytes and the
  content type. Most plugins tell you they converted something. This one shows
  you the delivery arrives.
* **Your originals, untouched.** Nothing is replaced, resized or deleted. The
  copies sit next to the originals as `photo.jpg.webp`. Remove the plugin and
  your site is exactly as it was.

= Fast, and measured =

Numbers from the plugin's own benchmark on a 4-core VPS, PHP 8.5:

* **0.34 ms** to rewrite a page carrying 21 images — 0.016 ms per image.
* **0.0001 ms** on a page with no images: the filter leaves immediately.
* **+287 bytes gzipped** of extra markup for those 21 images.
* **0.5 ms per image** to scan the library, so ten thousand images take about
  five seconds.

The companion lookup is memoised per request and stored in your object cache
when you have one, so a gallery that repeats the same thumbnail forty times
costs one disk check, not forty.

= Exclusions, because "convert everything" is wrong =

* **By image size.** Every registered size, with its dimensions and where it
  comes from. Tick the ones to leave alone, or all the ones under 300 px at once.
* **By name or folder.** One rule per line: `logo-*.png`, `*-nowebp.*`,
  `2019/*`, `brand/`.
* **By threshold.** Below a file size, below or above a number of pixels.
* **By file type.** JPEG, PNG, GIF — and animated GIFs are always left alone,
  because converting one silently loses the animation.
* **One image at a time.** A checkbox on any image, a column in the media
  library showing what happened to it, bulk actions and a filter.

= Try AVIF before deciding anything =

AVIF works out of the box for a few images a day, with no key, no account and
no card. Convert your own photographs, compare the sizes in the media library
column, then decide.

= Where it appears in WordPress =

In the media library as a column, per-image actions, bulk actions and a filter.
In **Tools → Site Health**, as a status check and a full section under Info, so
whoever maintains the site sees the state of the images with everything else.
And in its own four screens: dashboard, settings, exclusions, tools.

= WP-CLI =

For agencies and large libraries, everything the dashboard does is also a
command:

* `wp webp-avif status` — what is converted, pending and excluded, and what the
  server can do.
* `wp webp-avif scan` — the dry run, nothing written.
* `wp webp-avif convert [<id>...] [--format=webp|avif|both] [--limit=<n>]` —
  convert the library or chosen images.
* `wp webp-avif check` — the delivery check, from the command line.
* `wp webp-avif remove --yes` — delete every copy; originals untouched.

= How the file reaches the browser =

* **Picture tag** (default): each image becomes a `<picture>` with the modern
  sources first and your original `<img>` last. A browser that understands
  neither takes the original, so nothing can break.
* **Web server rules**: same URL, different file, chosen from the browser's
  Accept header. Faster still, and it covers images the plugin never sees, such
  as CSS backgrounds. Written into .htaccess for you on Apache and LiteSpeed,
  with an nginx snippet to paste. The plugin then checks whether your host
  actually applies them, and says so if it does not.
* **Nothing for now**: keep converting, keep serving the originals.

= External service =

AVIF conversion — and WebP conversion on the rare server that cannot do it —
uses the Smallapis image API at https://smallapis.com. The image is
sent over https, converted, returned, and deleted immediately; it is not
stored, indexed or reused. This happens only for a format your own server
cannot produce, and only while that format is switched on. Leave AVIF off and
nothing is ever sent anywhere. A small number of conversions a day works with
no key at all; a free key raises the limit and can be requested from the
settings screen without leaving WordPress. Terms and privacy policy:
https://smallapis.com/legal.html — in short: nothing about the file is
kept, uploads are deleted as soon as the answer is written, and no content is
ever used to train anything.

== Installation ==

1. Install and activate.
2. The setup opens on its own: what your server can do, how hard to squeeze,
   then the button that converts the images you already have.
3. Done. New uploads are converted from then on — WebP immediately, AVIF in the
   background so an upload never waits on a network call.

The setup can be skipped, and everything it sets can be changed afterwards.

== Frequently Asked Questions ==

= Will this break my images? =

The original file is never touched. With the picture tag method your original
`<img>` stays in the page as the final fallback, so a browser that understands
neither format gets exactly what it got before.

= How do I know it is actually working? =

Press **Check my site** on the dashboard. It downloads one of the converted
files from your own site, the way a browser would, and reports what came back:
whether the file arrives, whether your server labels it `image/webp` rather than
something generic, and whether your pages really offer the modern format. It
catches the failures that look like success — a host that refuses unknown
extensions, .htaccess rules silently ignored, a cache dropping the Vary header.

= Why is the AVIF quality number so much lower than the WebP one? =

Because the scales are not the same. AVIF at 45 looks like WebP at 72, and that
is where AVIF is worth having: roughly half the weight. Setting both to the same
number is a common mistake and makes AVIF look pointless — above quality 60 it
often produces a *bigger* file than WebP, which this plugin then throws away
rather than serve.

= Does it need an account? =

Not for WebP, which is the bulk of the gain: that runs on your server and
nothing leaves the site. The AVIF service works for a few images a day with no
key at all, so you can see the result on your own photographs before deciding
anything.

= Nothing seems to change on my pages. How do I check? =

Open the dashboard and press **Check my site**. It names the step that fails:
no converted file yet, a file the server does not deliver, a wrong content
type, or server rules that are ignored. With the picture tag method, look at
the page source: each image should sit inside a `<picture>` element. A page
cache keeps serving the old HTML until it is cleared, so clear it once after
the first conversion.

= Can I undo the conversion of one image? =

Yes. In the media library, the **WebP & AVIF** column has an **Undo** link on
every converted image: it deletes the copies of that image and nothing else.
**Exclude** makes sure it is never converted again.

= I use nginx. What do I do? =

Keep the picture tag method, which needs nothing from the server. If you want
server rules instead, the Settings screen gives you the exact nginx snippet to
paste, and **Check my site** tells you whether it is active.

= Is there a command line? =

Yes, see WP-CLI above: `wp webp-avif convert` converts a whole library without
a browser open, which is the comfortable way past ten thousand images.

= Does it work with a CDN? =

With the picture tag method, yes: the URLs are ordinary files. With server
rules, your CDN must vary on the Accept header, which the rules declare.

= What happens to animated GIFs? =

They are left alone. Converting one to a single-frame WebP loses the animation
without telling anyone.

= Can I keep the converted files if I remove the plugin? =

Yes, there is a switch for it in Tools. By default they are deleted on
uninstall, because leaving thousands of orphaned files on someone's hosting is
not a polite way to be removed.

== Screenshots ==

1. The dashboard: what has been saved, what this server can do, and the scan.
2. Setup, step one: what your server can and cannot do, in plain words.
3. The dry run: what would be converted, and everything left out with its reason.
4. The check that downloads a converted file from your own site to prove it arrives.
5. Exclusions: every image size with its dimensions, name rules and thresholds.
6. The media library column, with per-image actions and bulk actions.
7. Tools to Site Health, where the plugin reports its own state.

== Changelog ==

= 1.5.0 =
* New: WP-CLI commands: `wp webp-avif status`, `scan`, `convert`, `check` and `remove`.
* New: an Undo link on every converted image in the media library column, which deletes that image's copies only.
* Changed: clearer directory description and answers on nginx, undoing and checking the delivery.

= 1.4.0 =
* New: a Get a key button in the plugin header. After paying, one click activates the key on the site it was bought from, no copy and paste.
* New: once the plugin has done its job, a short request for a review, on its own screens only, which can be put off or turned off.

= 1.3.2 =
* Changed: the Smallapis service moved to its own domain, smallapis.com.

= 1.3.1 =
* New: a key entered in another Smallapis plugin on the same site is used here too.

= 1.3.0 =
* New: appears in Tools → Site Health, as a status check and a full Info section.
* New: companion lookups are memoised per request and cached in the object cache
  when one is available. A page of 21 images now costs 0.34 ms.
* New: benchmark script, so the performance claims above can be re-measured.
* Changed: the conversion service explains its own refusals instead of a generic
  message.

= 1.2.0 =
* New: three-step setup that opens on first activation — server check, one
  quality choice, and the first conversion, with sensible defaults throughout.
* New: end-to-end check that downloads a converted file from your own site and
  reports whether the delivery really works, including the content type.
* New: first-run state on the dashboard instead of a screen full of zeros.
* Fixed: ImageMagick reports formats it can only read. Each format is now proven
  by encoding a test image, per engine, so the plugin cannot claim local AVIF
  support it does not have and then silently produce nothing.
* Fixed: excluding one image size no longer costs the whole image its modern
  delivery. The smallest width is the one that must stay.
* Fixed: deleting every converted copy now also sweeps files whose record was
  lost, and resets the savings figures with them.
* Changed: without a key the conversion service still converts a few images a
  day, and a refusal pauses further calls instead of repeating them.

= 1.1.0 =
* New: dry-run scanner that reports what would be converted and why anything is skipped.
* New: exclusions by image size, name pattern, folder, file size, dimensions and file type.
* New: per-image exclusion, media library column, bulk actions and filter.
* New: server-level delivery through .htaccess rules, with an nginx snippet.
* New: dashboard with real savings figures, failure log and system report.
* New: animated GIFs are detected and left alone.
* Changed: a file that does not compress is remembered and not retried on every run.
* Changed: admin rebuilt as four screens instead of one long settings page.

= 1.0.0 =
* First release.
