Optimal WebP Conversion Settings
A practical reference for choosing quality, frame rate, and dimensions based on where your animated WebP will actually be used.
The settings that actually matter (and the ones that don't)
When converting video to animated WebP, four knobs produce meaningful results: quality (the perceptual fidelity of each frame), lossless mode (whether to compress losslessly or not), frame rate (how many frames per second survive into the output), and output dimensions (pixel width and height after scaling).
Everything else is secondary. The encoder method flag (-compression_level) only adjusts how long the encoder spends searching for better compression — it does not change the visual output at all, just the CPU time. Preset name strings in some wrappers are usually just quality shortcuts with a label; reading the underlying number is more useful than the label itself.
Start with quality and frame rate. Get those right for your target size budget, then adjust dimensions only if the file is still too large. You rarely need to touch anything else.
Quality vs. file size: the trade curve
The -qualityflag in ffmpeg's libwebp encoder runs from 0 to 100. The relationship between quality and file size is not linear — it follows a curve with a sharp inflection point around 75.
Below 50, banding artifacts become visible on gradients and mosquito noise appears around high-contrast edges. These artifacts are particularly obvious in motion because your eye catches flickering compression noise between frames. For any output a real person will scrutinize, I don't go below 60.
In the 60–75 range, quality improves quickly relative to the file-size cost. This is where most useful settings live. At 75, output looks clean on most content and files remain manageable.
Above 75, you're paying disproportionately for marginal gains. Going from quality 75 to 90 often increases file size by 50–80% while producing a difference that's invisible unless you pixel-peep. Above 90, you're approaching lossless territory in file size without the correctness guarantees of actual lossless mode — the worst of both worlds for photographic content.
One important clarification: -quality and -compression_level are completely orthogonal. Compression level (0–6) controls encoder speed — a higher value means the encoder tries harder to find a compact encoding of the same quality target, at the cost of more CPU time. It does not affect what the output looks like. See the libwebp cwebp documentation for the full parameter breakdown.
My default starting point is quality 75. I move down toward 65 when hitting a file-size target and up toward 82 only for static thumbnails where a single frame gets heavy scrutiny.
Frame rate: when to drop frames
Source clips are typically shot at 24, 30, or 60 fps. For most animated WebP use cases, you don't need to preserve that. Frame count is one of the largest drivers of file size — halving the frame rate roughly halves the file size, before any quality adjustment.
For UI loops, product carousels, and email body animations, 12 fps almost always looks fine. The human eye reads looping UI motion as smooth down to about 10 fps when the motion is simple and predictable (a slide, a fade, a product spin). At 12 fps, a 5-second clip has 60 frames; at 30 fps, it has 150 frames — 2.5x more data for no perceptible improvement in most cases.
Motion-heavy content is different. Fast pans, sports footage, or anything with unpredictable rapid movement will show visible judder at 12 fps because the viewer's eye is tracking motion and catching dropped frames. For that content, 24 fps is the practical floor.
A useful test: if you can predict where every element will be one second later, 12 fps is probably fine. If not, test at 24 first.
Lossless vs. lossy: when each pays off
Lossless WebP uses a different prediction-based coding scheme than lossy. It preserves pixel values exactly, which matters for some content and wastes space for others.
Lossless wins for: small icons and UI elements with flat color regions, transparent animated overlays (alpha channel content), screen recordings of code or terminal output where text crispness matters, and animations generated from vector graphics or design tools. For these, lossy encoding often produces visible artifacts on sharp edges and solid fills — colors that should be identical across a region end up slightly different, which looks like noise on a clean background.
Lossy wins for everything photographic. Google's WebP benchmark data (the "gallery2" dataset) shows that lossy WebP at quality 80 produces files roughly 26% smaller than equivalent-quality JPEG, and significantly smaller than lossless WebP for the same content. For a typical photograph, forcing lossless mode can produce a file 3–5x larger than a quality-80 lossy encode with no meaningful visual improvement.
The practical rule: if your source has transparency or large uniform color regions, test lossless. Otherwise, use lossy.
Per-use-case presets
These are the settings I use repeatedly. Target sizes assume a 5-second clip at the given dimensions.
| Use case | FPS | Quality | Max width | Target (5s) |
|---|---|---|---|---|
| Email body | 10 | 65 | 480px | <80 KB |
| Hero loop | 20 | 78 | 1280px | 300–500 KB |
| Thumbnail | 12 | 72 | 320px | <40 KB |
| Markdown / GitHub README | 15 | 75 | 800px | <250 KB |
| Lottie replacement | 24 | lossless | 400px | <150 KB |
| Marketing campaign asset | 24 | 80 | 960px | <500 KB |
The email row is aggressive by design. Gmail clips message display at roughly 102 KB — any image that pushes the total message over that threshold gets a "Show entire message" prompt that most readers ignore. Staying under 80 KB for the WebP itself leaves room for the HTML wrapper and any other assets in the email.
The Lottie replacement row uses lossless because those animations typically come from vector sources with flat fills — the kind of content where lossy encoding introduces color-banding artifacts on what should be solid shapes. At 400px and 24fps, lossless is still compact because the source data is spatially simple.
The hero loop row uses 1280px rather than 1920px deliberately. Most hero sections display at full viewport width but CSS scales the image — serving 1280px and letting the browser upscale slightly costs nothing perceptible and saves meaningful bandwidth compared to encoding at 1920px.
Example ffmpeg invocations
Email preset — aggressive size target, 480px wide, 10 fps:
ffmpeg -i input.mp4 \ -vf "fps=10,scale=480:-1" \ -c:v libwebp -loop 0 -quality 65 \ output-email.webp
Hero loop preset — 1280px wide, 20 fps, quality 78:
ffmpeg -i input.mp4 \ -vf "fps=20,scale=1280:-1" \ -c:v libwebp -loop 0 -quality 78 \ output-hero.webp
File-size targets I aim for
I use these as hard constraints before I start adjusting quality and fps:
- <100 KB for any inline email image — Gmail clips entire messages at ~102 KB and Outlook has its own thresholds for large media.
- <250 KB for a GitHub README hero — GitHub renders WebP natively in Markdown but large files slow down repository page loads noticeably on mobile.
- <500 KB for marketing hero images on landing pages with above-average traffic.
- <1 MB as a hard ceiling for anything else — if a WebP won't fit under 1 MB with reasonable quality, the source clip is probably too long or the use case is better served by a video element with autoplay.
These aren't aesthetic preferences — they're driven by real-world clipping behavior in email clients and browser rendering. A 1.5 MB WebP that technically displays correctly will still cost you conversions on 4G connections.
Decoder cost: what 'too many keyframes' costs the user
Animated WebP frames decode on the CPU, not the GPU. Each frame in the animation loop requires the browser to decompose and composite pixel data. On desktop this is invisible. On a low-end Android phone — the kind that still accounts for a significant share of traffic in Southeast Asia, South Asia, and parts of Latin America — looping a 60-frame WebP at full resolution can sustain 4–6% CPU load continuously. That drains battery and competes with everything else on the page.
Fewer frames means less decode work per loop. A 12-fps, 5-second animation has 60 frames; the same clip at 24 fps has 120. Halving frame rate halves the decode burden per loop cycle, not just the file size.
For any looping animation on a page where low-end device performance matters, I also add a prefers-reduced-motion media query in CSS that replaces the animated WebP with its first frame as a static image. This is good accessibility practice and eliminates the CPU cost entirely for users who prefer reduced motion.
Common mistakes
- Quality above 90. You get near-lossless file sizes without the correctness guarantees of lossless mode. For photographic content, quality 75–82 is visually indistinguishable from 95 at screen sizes.
- Matching source frame rate (60 fps) without thinking. A 60 fps source converted 1:1 to WebP produces 3–5x the frames needed for smooth-looking UI motion. Drop to 24 fps first and see if it passes a squint test.
- Forcing the alpha channel when the source is opaque. Adding
-pix_fmt yuva420pto an opaque source increases per-frame data without doing anything useful. If there's no transparency in the source, don't encode alpha. - Using lossless mode for photographic content. A photograph with lossless encoding can be 4–6x larger than lossy at quality 80, with no visible improvement on any display under normal viewing conditions.
- Skipping dimension scaling entirely. A 1920px source converted at 100% resolution for use in a 400px thumbnail slot wastes bandwidth on every request. Always scale to the display size.
For a full breakdown of every ffmpeg flag that affects WebP output — including keyframe intervals, filter ordering, and color space handling — see the ffmpeg flags for WebP guide. If your primary use case is email, the animated WebP for email guide covers client compatibility in detail.
Apply these settings directly in the converter.
Convert a video now