On this page:

I’m not overly concerned with SEO or my blog’s performance but there is no need to make someone download a 350k image when a 17k one will do. To make that happen I have converted all my images from their previous png and jpg formats, and using Google’s WebP format. I’ve been doing this using the cwebp command line tool.

My goals were to:

  1. Convert all jpg and png files to webp
  2. Resize all those files to a maximum width of 800 (maintaining aspect ratios)
  3. Batch up #1 and #2 for entire directory structures

Converting a Single File

Converting a single file to webp using cwebp is simple:

cwebp infile.png -o outfile.webp

This converts the png file to webp using the defaults.

cwebp -resize 800 0 infile.webp

This resizes the webp file to a maximum width of 800 with 0 indicating “maintain the aspect ratio for the height”.

And you can put these both together like:

cwebp -resize 800 0 infile.png -o outfile.webp

Batch Converting a Directory

Now that we can convert a single file, I used a combination of either find and bash, or just zsh, to do what I needed for the directory. This example converts all the png files in a directory structure to webp, and resizes them to 800px wide while maintaining the original aspect ratio:

Using bash shell:

for x in $(find . -iname '*.png');do cwebp -resize 800 0 "${x}" -o "${x%%png}"webp;done

Using Z shell:

unsetopt CASE_GLOB && for x in ./**/*png;do cwebp -resize 800 0 "${x}" -o "${x/(png|PNG)/webp}";done; setopt CASE_GLOB 

Basically the pipeline is this:

  1. Find all the files in the current directory and it’s children using find (bash) or builtin (zsh)
  2. Loop through the files, running cwebp on each
  3. Use shell parameter expansion to format the output filename for each file

This seems super hacky but it works and that’s all I really cared about. If you can improve on this then please feel free to submit a PR to this blog post to help (really, please do!)

When this runs each png file in the directory tree will have a cooresponding webp at the same location and that webp file will have been resized to a max width of 800px.

Now my steps were:

  1. Delete the original files (I used the same command as above but replaced the bash command with an rm command)
  2. Mass-update the blog posts (I used Find/Replace in Sublime)
  3. Run jekyll and test

And I think the outputs speak for themselves. Here is an example input image:

A black c-clamp on a black background
Photo by Matt Artz on Unsplash

And here is the WebP compressed and resized version

A black c-clamp on a black background
Photo by Matt Artz on Unsplash

The original file was 338712 bytes and the webp version is 16544 bytes - roughly 95% savings with very little change in the overall visual experience (as needed for a personal blog).


Thanks to noksookhao for improving the shell commands!