JPEG to AVIF 一括コンバーターを作ってみた – Pyinstaller

Pyinstaller で JPEG から AVIF 一括コンバートの実行ファイルを作る HowTo
Pyinstaller で JPEG から AVIF 一括コンバートの実行ファイルを作る

なぜ、そんなものが欲しいのか?

 先日、NASにある大量の画像をAVIFにコンバートして容量節約する記事を書きました。ここで使用した Python のコードは実際に機能するにはするけど、週に1回、スマホから画像をNASで移す作業にいちいちコマンドラインを叩くのがだんだん億劫になってきました。

 そこで、単純でいいので簡単に一括コンバートできるプログラムを用意したくなったのが動機です。

似たような機能を持つソフトやサービスがあるにはあるが

 本当に簡単でよいのです。市井にはこの手のWebサービスがたくさん存在するのですが、大量のデータをアップデートする時間のロスと、1回で処理できるファイル数が20から30程度といった制約がつきまとうことで、どうにも使い勝手が悪いのです。

 フリーソフトに目を向けると、できるにはできるけど、バッチを組んだりしないといけなかったり、AVIF->JPEG 方向のコンバートしかサポートしていなかったりと、どれもニーズに合いません。

 私が求めているのは、本当に細やか機能なのです。

  • プログラムをポンと置いて即実行
  • 特定フォルダ内のJPEGファイルを一括でAVIFにコンバートしてくれる
  • 解像度はオリジナルを維持
  • 品質パラメータは固定でOK
  • EXIF 情報は維持
  • Windowsでのみ動作すれば可

 なんと志の低いことでしょう!でも、これだけで十分なのです。

仕方がないので自分で作ろう

Python を使います

 機能的には、この前用意した Python コードがそのまま EXE になってくれればOKです。

 Python の流行につれて、実行プログラムを生成してくれるソリューションがたくさん登場してきているので、これを活用させてもらうことにします。

Pyinstaller を使います

 コードはもうそこにあるので、これを実行ファイルにパッケージングしてくれるものであれば何でもOKです。今回はいちばんお手軽そうな pyinstaller を使用してみます。

PyInstaller Manual — PyInstaller 6.15.0 documentation

 日本語訳のドキュメントはありません。有志の方々による解説記事がたくさんありますので、安心してください。ハマりどころがいくつかありましたが、これらのサイトに助けられました。

PyInstallerによるPythonスクリプトのexe化とエラー対処方法まとめ - Qiita
はじめに この記事では、PythonモジュールのひとつであるPyInstallerを用いたPythonスクリプトのexe化方法および各種エラー対処方法について説明します。PyInstallerでexe化することで、Pythonをインストール...

実行ファイルを生成してみる

Pyinstaller を使用する上での注意事項

 簡単に注意事項をまとめておくと‥

  • Windows 環境で作成した実行ファイルは Windows 上でしか動作しない
    Pyinstaller は Windowsをはじめ、Mac OS、Linux の実行バイナリも生成できます。今回はWindows環境のみがターゲットです。
  • Microsoft Store 版の Python 環境には対応していない
    公式サイトからファイルを持ってきて、インストールし直してください。
  • 実行ファイル生成には専用の venv 仮想環境が必須
    普段からプロジェクトごとに環境を分けている人には今更ですが。
    これをサボすると、pip list で表示されるすべてのモジュールが自動的にインクルードの対象となってしまいます。下手をすると、”Hello World!” するだけのプログラムが数百MBになっちゃいます。ファイルの肥大化を避けるために必ず行うべきです(サボっても動くことは動きます)。
  • 実行ファイルは巨大化しがち
    今回のような他愛のないプログラムであっても、実行バイナリは16MBを超えました。そのほとんどは画像処理系のライブラリが占めているでしょう。ダイエットする技もあるようですが、今回は面倒なのでやりません。しかし、必要なものを須くパッケージングしていることにより、余計な環境依存のトラブルを回避することができると思えば、安い対価と言えるでしょう。
  • 最低動作環境はWindows 8
    いまどき、ここは問題ないでしょう。

 ざっと、こんなところです。特に今回の目的を達成するにあたり、不都合のないレベルのものです。

使用するコード

 私の環境で、私が望む動作を実現しただけのコードですので、試される方はご自分の志向に合わせて改造してください。品質パラメータの調整は赤字の部分です。

#
# Convert JPEG to AVIF with Pillow
# Ver1.0
# 2023-08-18	aries67.com
#

from PIL import Image
from io import BytesIO
import os
import time
import pillow_avif

start = time.time()
QUALITY = 30

import glob

dir = './convert/'
if not os.path.exists(dir):
	os.makedirs(dir) 


print('\n/// Convert JPEG to AVIF with Pillow Ver1.0 ///' )
print('\nCompress rate' )
print('-------------')

files = glob.glob("./*.JPG")
for file in files:

	original_file_size = os.path.getsize(file)

	file_name = os.path.splitext(os.path.basename("./" + file))[0]
	with open(file, 'rb') as inputfile:
		im = Image.open(inputfile)
		im_io = BytesIO()
		im.save(im_io, 'avif', quality = QUALITY, exif=im.info['exif'])
	with open('./convert/' + file_name + '.avif', mode='wb') as outputfile:
		outputfile.write(im_io.getvalue())

	output_file_size = os.path.getsize('./convert/' + file_name + '.avif')

	compress_rate = output_file_size / original_file_size
	compress_rate_percent = round(compress_rate * 100, 2)
	print( str(compress_rate_percent) + ' %' )

end = time.time()
print('\nTotal exec time ')
print('----------------')
print( str(round( end - start, 2)) + ' sec')
print('\nJob done. Converted files in |convert| directory.\n')

筆者の環境

  • Windows11 Home
  • Python 3.9.13

実行ファイルの生成手順

 Python のインストールが終わっている前提です。

venv 仮想環境の作成

 Powershell は最新版を使用しましょう。

 適当なフォルダでコマンド実行。

python -m venv testvenv

 インストールが完了したら、Scripts フォルダに移動します。admin はあなたのユーザー名です。

PS C:\Users\admin\Documents\py\testvenv\Scripts> ls

    Directory: C:\Users\admin\Documents\py\testvenv\Scripts

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2023/08/18    20:09           1985 activate
-a---          2023/08/18    20:09            977 activate.bat
-a---          2023/08/18    20:09          21976 Activate.ps1
-a---          2023/08/18    20:09            368 deactivate.bat
-a---          2023/08/18    20:09         106366 pip.exe
-a---          2023/08/18    20:09         106366 pip3.9.exe
-a---          2023/08/18    20:09         106366 pip3.exe
-a---          2023/08/18    20:08         599032 python.exe
-a---          2023/08/18    20:08         598520 pythonw.exe

venv 仮想環境のブート

 仮想環境をブートします。

./Activate.ps1

モジュールのインストールと動作テスト

 出来立ての仮想環境は空っぽです。
 プロジェクト実行に必要なモジュールをすべて pip install していきます。

(testvenv) PS C:\Users\admin\Documents\py\testvenv\Scripts> pip list
Package                   Version
------------------------- --------
altgraph                  0.17.3
asgiref                   3.7.2
Django                    4.2.4
image                     1.5.33
pefile                    2023.2.7
Pillow                    10.0.0
pillow-avif-plugin        1.3.1
pip                       23.2.1
pyinstaller               5.13.0
pyinstaller-hooks-contrib 2023.6
pywin32-ctypes            0.2.2
setuptools                58.1.0
six                       1.16.0
sqlparse                  0.4.4
typing_extensions         4.7.1
tzdata                    2023.3

 ここでモジュールの不足がないかの確認のため、仮想環境上でコードの実行テストをしておいたほうがよいでしょう。

パッケージング

 問題なければ、ようやくパッケージングです。

pyinstaller C:\Users\admin\py\pyinstaller\conv_avif_pillow.py  --onefile

 エラーがでなければ、実行ファイルが生成されたはずです。

C:\Users\admin\Documents\py\testvenv\Scripts\dist\conv_avif_pillow.exe

生成された実行ファイル

 生成された実行ファイルをzipで固めて置いておきます。配布を主たる目的としたものではないため、ドキュメントはありません。試される方は自己責任でお願いします。

実際に使ってみる

 この実行ファイルは、ローカルマシンでもNASでもどこにでもコピーして実行が可能です。この気楽さがよいのです。

 試しに、TrueNAS SCALE の SAMBA フォルダに生成ファイルとJPEGファイルをいくつか放り込みます。これは、デジカメやスマホからファイルをコピーする作業と同じイメージです。

\\TRUENAS\storage-a\test>

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2023/08/18    20:14       16848071 conv_avif_pillow.exe
-a---          2023/08/10    16:32        6950553 DSC_0328.JPG
-a---          2023/08/10    16:32        8178258 DSC_0330.JPG
-a---          2023/08/10    16:32        7699757 DSC_0331.JPG
-a---          2023/08/10    16:32        5376154 DSC_0332.JPG
-a---          2023/08/10    16:32        8130650 DSC_0334.JPG
-a---          2023/08/10    16:32        7805118 DSC_0335.JPG
-a---          2023/08/10    16:32        7816365 DSC_0337.JPG
-a---          2023/08/10    16:32        6667472 DSC_0338.JPG

 この生成ファイルを実行するだけです。

\\TRUENAS\storage-a\test> python conv_avif_pillow.py

/// Convert JPEG to AVIF with Pillow Ver1.0 ///

Compress rate
-------------
1.29 %
1.79 %
2.22 %
1.12 %
2.02 %
1.83 %
1.56 %
3.64 %

Total exec time
----------------
10.59 sec

Job done. Converted files in |convert| directory.

 同じ階層に convert フォルダが生成されて、その中にコンバートされた AVIF ファイルができあがっているのが確認できました。

\\TRUENAS\storage-a\test\convert>

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2023/08/19     7:48          89517 DSC_0328.avif
-a---          2023/08/19     7:48         146390 DSC_0330.avif
-a---          2023/08/19     7:48         170744 DSC_0331.avif
-a---          2023/08/19     7:48          60392 DSC_0332.avif
-a---          2023/08/19     7:48         164247 DSC_0334.avif
-a---          2023/08/19     7:48         142675 DSC_0335.avif
-a---          2023/08/19     7:48         122013 DSC_0337.avif
-a---          2023/08/19     7:48         242575 DSC_0338.avif

Pyinstaller は業務でもプライベートでも活躍しそう

 業務効率化のために、Python などを活用している人は多いと思います。クライアントへのプログラム配布が便利なケースでは、Pyinstaller を使用しても問題なさそうです。

 サンデープログラマーのお父さんにもおすすめします。Pythonのお手軽さが実行ファイルになると世界が広がりますからね。次の週末にでも、ぜひ遊んでみてください。