Vinicius Morais
Vinicius Morais

Reputation: 595

Is there a fast way to convert a image into WEBP?

In my website i'm now converting my upload images into webp, because is smaller than the other formats, the users will load my pages more faster(Also mobile user). But it's take some time to converter a medium image.

import StringIO
import time

from PIL import Image as PilImage

img = PilImage.open('222.jpg')

originalThumbStr = StringIO.StringIO()

now = time.time()
img.convert('RGBA').save(originalThumbStr, 'webp', quality=75)
print(time.time() - now)

It's take 2,8 seconds to convert this follow image:

860kbytes, 1920 x 1080

My memory is 8gb ram, with a processor with 4 cores(Intel I5), without GPU.

I'm using Pillow==5.4.1.

Is there a faster way to convert a image into WEBB more faster. 2,8s it's seems to long to wait.

enter image description here

Upvotes: 4

Views: 1689

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207670

If you want them done fast, use vips. So, taking your 1920x1080 image and using vips in the Terminal:

vips webpsave autumn.jpg autumn.webp --Q 70

That takes 0.3s on my MacBook Pro, i.e. it is 10x faster than the 3s your PIL implementation achieves.

If you want lots done really fast, use GNU Parallel and vips. So, I made 100 copies of your image and converted the whole lot to WEBP in parallel like this:

parallel vips webpsave {} {#}.webp --Q 70 ::: *jpg

That took 4.9s for 100 copies of your image, i.e. it is 50x faster than the 3s your PIL implementation achieves.


You could also use the pyvips binding - I am no expert on this but this works and takes 0.3s too:

#!/usr/bin/env python3

import pyvips

# VIPS
img = pyvips.Image.new_from_file("autumn.jpg", access='sequential')
img.write_to_file("autumn.webp")

So, my best suggestion would be to take the 2 lines of code above and use a multiprocessing pool or multithreading approach to get a whole directory of images processed. That could look like this:

#!/usr/bin/env python3

import pyvips
from glob import glob
from pathlib import Path
from multiprocessing import Pool

def doOne(f):
   img = pyvips.Image.new_from_file(f, access='sequential')
   webpname = Path(f).stem + ".webp"
   img.write_to_file(webpname)

if __name__ == '__main__':
    files = glob("*.jpg")
    with Pool(12) as pool:
        pool.map(doOne, files)

That takes 3.3s to convert 100 copies of your image into WEBP equivalents on my 12-core MacBook Pro with NVME disk.

Upvotes: 5

Related Questions