Fmtify: Auto WebP and AVIF Converter

Описание

Fmtify automatically converts images uploaded to your WordPress media library into modern WebP and AVIF formats. Serve smaller, faster images with zero manual work.

Features:

  • Automatic conversion on upload
  • WebP and/or AVIF output
  • Multiple conversion backends: GD, Imagick, cwebp, cavif
  • Bulk convert your existing media library
  • Apache .htaccess rewrite rules for seamless serving
  • Nginx configuration snippet for manual setup
  • Compatibility wizard to detect server capabilities

Установка

  1. Upload the fmtify folder to /wp-content/plugins/
  2. Activate the plugin through the Plugins menu in WordPress
  3. Go to Settings Fmtify to configure conversion options
  4. Visit Media Bulk Convert to convert existing images

Часто задаваемые вопросы

Which image formats are supported as input?

JPEG, PNG, GIF, and BMP source images are supported.

Do I need a special server setup?

No. Fmtify detects your available conversion libraries automatically and picks the best one. For Apache, it writes .htaccess rewrite rules. For Nginx, it provides a copy-paste configuration snippet.

Will my original images be deleted?

Never. Converted files are stored alongside the originals. You can delete them at any time from the settings page.

Are animated GIFs converted?

No. Animated GIFs are skipped on purpose: WebP and AVIF sidecars would only contain the first frame, so the animation would be lost. Static GIFs are converted normally.

Отзывы

Нет отзывов об этом плагине.

Участники и разработчики

«Fmtify: Auto WebP and AVIF Converter» — проект с открытым исходным кодом. В развитие плагина внесли свой вклад следующие участники:

Участники

«Fmtify: Auto WebP and AVIF Converter» переведён на 1 язык. Благодарим переводчиков за их работу.

Перевести «Fmtify: Auto WebP and AVIF Converter» на ваш язык.

Заинтересованы в разработке?

Посмотрите код, проверьте SVN репозиторий, или подпишитесь на журнал разработки по RSS.

Журнал изменений

1.3.0

  • Added: Image Engine setting on the main settings page (Auto / GD faster / Imagick better quality, slower). It replaces the per-run Backend selector on the Bulk Convert page and now applies to ALL conversions: uploads, Bulk Convert, and WP-CLI. Auto keeps the previous behavior (GD first, Imagick fallback). When the selected engine is unavailable or cannot produce a format, Fmtify falls back automatically.
  • Fixed: Every GIF (and PNG-8 / indexed BMP) failed on the GD engine with «Palette image not supported by webp» and «avif doesn’t support palette images» warnings. GD loads these as palette images; they are now converted to truecolor before encoding, preserving transparency.
  • Fixed: BMP images always failed on the GD engine because the BMP loader was missing.
  • Fixed: Static thumbnails of an animated GIF are now converted; the animated files themselves are excluded up front instead of being counted as conversion issues and retried on every bulk run.
  • Improved: More precise animated GIF detection (anchored frame headers, fewer false positives from pixel data).
  • Improved: Engine availability probes now run once per request instead of once per converted file.

1.2.15

  • Fixed: Bulk Convert could report 100% complete while leaving most of the library unconverted. The fresh-pass query window did not advance past images that stay in the result set (failed, missing on disk, excluded type, or any image when conversion tracking is off), so each batch re-read the same items. The query now paginates with a persistent offset in all modes and orders by ID for deterministic batches.
  • Fixed: An image was marked as fully converted when only some of its sizes succeeded. The _fmtify_converted meta now records a format only when every file (original plus all thumbnails) converted, so a later fresh pass retries partially failed images. Applies to upload conversion, Bulk Convert, and WP-CLI.
  • Fixed: The PHP-fallback rewrite rule was registered only during activation, so saving permalinks (or any plugin flushing rewrite rules) silently removed it. The rule is now registered on every request and self-heals after plugin updates.
  • Fixed: Requests for missing images could render the homepage with HTTP 200 instead of returning a 404 when serving via .htaccess. The image handler is now active for every serving method and sends a real 404 for missing files.
  • Fixed: The rewrite rule assumed uploads live at wp-content/uploads under the site root. The pattern is now derived from the actual uploads URL, supporting subdirectory installs, the UPLOADS constant, and multisite upload paths.
  • Fixed: The Imagick backend reported success when it wrote a 0-byte file (for example on an unwritable directory). It now removes the empty file and reports the failure, matching the GD backend.
  • Fixed: Serving an original PNG, GIF, or BMP through the PHP fallback could send Content-Type: image/jpeg when MIME detection failed. The type is now derived from the file extension.
  • Fixed: Animated GIFs were silently flattened to a static first frame. They are now detected and skipped so the animation is preserved.
  • Fixed: wp fmtify bulk loaded every attachment ID into memory at once and could exhaust memory on large libraries. It now pages through the library 100 attachments at a time.
  • Fixed: The «Conversion issues» counter could exceed the total because it counted every failed file and format. It now counts each image once.
  • Fixed: Conversion stats counted files that had failed. The total now reflects actual successful conversions.
  • Fixed: Bulk job progress and lock transients are now removed on uninstall.
  • Changed: The PHP image handler refuses to serve anything but the supported image extensions, even if the query variables are set directly.
  • Changed: Removed unused internal converter methods and an unused setting key left over from an earlier architecture.

1.2.14

  • Fixed: register_setting() sanitize_callback was an instance method reference ([$obj, ‘sanitize’]) that WP Plugin Check cannot resolve statically, causing a false «missing sanitize_callback» warning. Fmtify_Settings::sanitize() is now a static method registered as [Fmtify_Settings::class, ‘sanitize’], which is fully statically-analysable.
  • Hardened: sanitize() now accepts mixed input — previously the array type hint would throw a PHP TypeError if WordPress called the callback with a non-array value (e.g. null on a fresh install).

1.2.13

  • Performance: .htaccess active state is now cached in a WordPress option (fmtify_htaccess_active). Previously Fmtify read .htaccess from disk on every front-end request (in auto serving mode) to decide whether the PHP image handler should register. The option is kept in sync whenever rules are written or removed.
  • Performance: Fmtify_Compatibility::get_status() result is now cached in a transient for one hour. Previously the full server-probe (including two Imagick::queryFormats() calls) ran on every admin page render.
  • Fixed: is_path_in_uploads() path-prefix check now appends a trailing slash to both sides of the comparison, preventing false positives for sibling directories such as uploads_backup/ or uploads-old/.
  • Fixed: Canonical list of convertible source MIME types is now defined once in Fmtify_File_Helper::CONVERTIBLE_MIME (jpeg/png/gif/bmp) and referenced by all conversion paths — upload hooks, bulk processor, and CLI. Previously the upload hook silently accepted image/tiff (never served by the rewrite rules) and image/webp (already a modern format; no sidecar needed).

1.2.12

  • Fixed: readme.txt had duplicate == Upgrade Notice == headers causing the WP Plugin Check 300-character limit warning. Merged all version entries under one header.
  • Fixed: set_time_limit() in the AJAX batch handler now suppresses the Plugin Check discouraged-function warning via phpcs:ignore. The call is intentional.

1.2.11

  • Updated translations for all 8 bundled locales (de_DE, fr_FR, ja, pt_PT, ru_RU, fa_IR, vi, si_LK) to cover new strings added in 1.2.8 and 1.2.9: Strip metadata, Conversion tracking, Backend selector, and related UI descriptions.

1.2.10

  • Fixed: Stale in-flight AJAX poll responses could overwrite the final «Done.» / count display after a bulk run completed. Added a jobDone flag that discards any poll response arriving after polling stops.
  • Fixed: PHPCS code-style violations introduced in 1.2.9 — array double-arrow alignment, assignment alignment, empty catch clause, and PHP tag placement in view files. No functional change.

1.2.9

  • Changed: GD is now the default conversion backend when available (was Imagick). GD encodes AVIF faster; Imagick is now the fallback for servers without GD.
  • Added: Backend selector on the Bulk Convert page. When both GD and Imagick are available, choose which backend to use for a bulk run — GD (faster, default) or Imagick (better quality, slower).

1.2.8

  • Added: Strip metadata setting (Settings Fmtify, off by default). When enabled, EXIF, ICC profile, and XMP are removed from every converted sidecar file. All four backends support it natively: Imagick (stripImage()), GD (skips the Imagick metadata-copy step), cwebp (-metadata none), cavif (—no-metadata).
  • Added: wp fmtify bulk —mode=rebuild re-converts every eligible image from scratch, matching the Full rebuild scope in the admin UI.
  • Added: Conversion tracking setting. When disabled, Fresh pass checks sidecar files on disk instead of _fmtify_converted post meta — always reflects actual files, useful after manually deleting sidecars.
  • Fixed: wp fmtify bulk now converts all registered thumbnail sizes per attachment, matching the WP admin Bulk Convert.
  • Fixed: cwebp backend was stripping all EXIF metadata. Added -metadata all so EXIF, ICC profile, and XMP are preserved by default.
  • Fixed: GD backend now copies EXIF and ICC profile from the source via Imagick after conversion. On GD-only servers without Imagick, metadata is still stripped (a fundamental GD limitation).

1.2.5

  • Improved: AVIF encoding speed raised to 8 (libaom cpu-used) across all three backends — Imagick, GD, and cavif CLI — cutting AVIF encode time by ~30–50% with imperceptible quality difference at web resolutions.

1.2.4

  • Improved: Imagick backend now sets WebP encoding method to 4 (was default 6), cutting WebP conversion time roughly in half with negligible quality difference.
  • Improved: GD backend now passes speed 6 to imageavif(), halving AVIF encode time vs the library default.

1.2.3

  • Fixed: Bulk Convert progress always showed «0 / N» when WP-Cron held the batch lock. The progress transient is now saved after every image so AJAX polls see live progress even while WP-Cron is processing a long-running batch.
  • Fixed: Batch lock TTL was 60 seconds, shorter than a typical batch on slow hardware (10 images × 5 thumbnail sizes × 2 formats). Raised to 300 seconds to prevent the lock from expiring mid-batch and triggering concurrent batch runs.

1.2.2

  • Fixed: AJAX batch loop ran for up to 20 seconds per poll, causing 504 Gateway Timeout errors on sites behind an Nginx reverse proxy (e.g. wordpress.test on Laragon/Herd). The per-poll processing budget is now capped at 8 seconds.

1.2.1

  • Fixed: Bulk Convert progress bar never advanced on local dev environments (Laragon, XAMPP, Herd) where WP-Cron cannot spawn HTTP requests. The AJAX progress poll now drives batch processing directly.
  • Fixed: Batch lock could be left set indefinitely after an unexpected exception in process_batch(), causing all subsequent polls to return stale zeros. The lock is now always released via try-finally.
  • Fixed: Conversion errors from non-RuntimeException sources were silently dropped instead of incrementing the «Conversion issues» counter. Changed inner catch to \Throwable.
  • Fixed: get_batch() was processing attachment ID 0 instead of real IDs. WP_Query with fields=’ids’ returns plain integers; wp_list_pluck() returned null for each, intval(null) = 0. Replaced with array_map(‘intval’, $query->posts).
  • Fixed: Images whose source file is in the database but missing from disk were silently skipped. They are now counted as «Conversion issues».
  • Added: «Already up to date» counter — images whose WebP/AVIF sidecars already exist on disk are now reported separately, replacing the confusing «0 written, 0 issues» result.

1.2.0

  • Added: Fresh pass / Full rebuild scope selector on the Bulk Convert page. Fresh pass skips already-converted images; Full rebuild regenerates all output files — use after changing quality settings or adding a format.
  • Added: Live stats box on Bulk Convert showing Images written and Conversion issues, updated with each polling interval.
  • Fixed: Stats counters always showed 0 — the progress transient stored errors but the UI read converted and failed. Replaced with separate converted/failed counters throughout.
  • Fixed: Bulk Convert now converts all registered thumbnail sizes for each attachment, not just the original.
  • Fixed: .htaccess rules are now re-written whenever settings are saved and on plugin activation, so Apache/LiteSpeed sites serve WebP/AVIF correctly after a settings change.
  • Fixed: GD backend now detects 0-byte output files (silent failure on unwritable directories), logs an error, and cleans up the empty file.
  • Changed: Stats labels updated — «Images written» and «Conversion issues» replace the previous wording.
  • Changed: Bulk Convert start button shortened to «Start».

1.1.7

  • Fixed: LiteSpeed was not accepted as a valid server_type value in the settings sanitizer. LiteSpeed servers had their server_type silently reset to «apache» on every settings save.

1.1.6

  • Renamed plugin internals from «Pictur» to «Fmtify»: plugin entry point, PHP classes, JS/CSS assets, language files, option keys, and hook tags. No functional changes.

1.1.5

  • Fixed AVIF images not being served on Apache when both WebP and AVIF are enabled. Apache re-reads .htaccess after the internal rewrite and served the sidecar file using the wrong MIME type (image/png instead of image/avif). Added AddType directives so the correct Content-Type is always used.

1.1.4

  • Fixed Apache serving: .htaccess rules are now written automatically on plugin activation and whenever settings are saved.
  • Fixed PHP fallback in auto mode — now activates on any server when .htaccess rules are absent, instead of silently failing on Apache.
  • Removed marketing language («Free, no upsells») from plugin description.
  • Updated translations for all 8 bundled locales.

1.1.3

  • Renamed plugin to «Fmtify — Auto WebP and AVIF» for clarity in the WordPress plugin directory.

1.1.2

  • Fixed bulk conversion showing «No unconverted images found» when the Themes folder was selected but all Media Library images were already converted.

1.1.1

  • Sidecar files (.webp/.avif) and all converted thumbnail sizes are now always deleted when an image is removed from the Media Library. The opt-in setting has been removed — cleanup is always on.
  • Added a note to the Nginx Setup tab for local dev environments (Herd, Valet, Laragon) that require an explicit root directive inside the location block.
  • Updated translations for all 8 bundled locales.

1.1.0

  • Browsers now receive WebP/AVIF bytes under the original image URL — no filename changes. Works on Apache (.htaccess), Nginx (config snippet), and via PHP fallback.
  • Added Serving Method setting (auto-detect, .htaccess, Nginx, PHP).
  • Bulk conversion now supports the Themes directory in addition to Uploads.
  • Fixed bulk image count (was unreliable on large libraries).
  • Fixed progress bar not resetting when there is nothing to convert.
  • Added translations for German, French, Japanese, Portuguese, Russian, Persian, Vietnamese, and Sinhala.
  • Changed delete-on-remove default to off to prevent accidental file deletion.

1.0.0

  • Initial release.