◆ 変換処理は Rust のライブラリで WASM 化してる
◆ ローカルのフォルダを選択して一括変換に対応
◆ 速度や画質のオプションを調整可能
◆ WASM にしてるのに全体的に遅め

AVIF 変換ツール

以前から AVIF を積極的に使おうとしてますが 扱いづらいところの一つが変換のしづらさだと思います
変換するのに標準ではない外部ツールが必要になりますし ブラウザでも Canvas から出力できないです

環境を整えていない PC でも簡単に JPG を AVIF 化できるといいなと思って AVIF 化するツールを作りました
https://to-avif-nexpr-6b45a3091281085c13d727f9f49565361e07301e611d8d8fa.gitlab.io/

ウェブページ上で変換できます
デスクトップアプリ風にしたかったので フォルダ内を一括変換できるようにしています
変換処理は Rust の image クレートを使っています
WASM 化しているのでブラウザで動いていてサーバーに画像の送信はしません

Speed と Quality で速度と画質を選べます
ファイルを選択 を選ぶと単体ファイルの変換です

フォルダを選択 を選ぶとフォルダ内をまとめて変換できます
選んだフォルダからチェックした拡張子のファイルをリストに表示します
リストでは個別にファイルにチェックを付けれて変換するしないを選べます
変換ボタンを押したときにチェックしたもののみが変換されます
変換後のファイル名は拡張子を .avif に置き換えたものになります
同一の名前がすでにあれば確認なく上書きされます

変換は並列実行するようにしています
同時実行数は CPU 数 (navigator.hardwareConcurrency) の半分です

遅い

小さいファイルで試してたときは 1 つに 1 秒もかかってなくて 速度に問題は感じてなかったのですが 大きめのファイルを変換するととても遅いです
大きめと言っても HD やフル HD のスクショ程度のサイズでもかなり遅く数秒~数十秒かかってます
オプションの Speed や Quality を変えるとマシにはなりますが それでも遅めです
コマンドラインの変換ツールだとこんなにはかからないのですけど

release ビルドになってないのかなと思いましたが wasm-pack はデフォルトがリリースビルドですし これ以上の最適化オプションもなさそうです
ググっていると image クレートの image::load_from_memory が遅いという情報がでてきて これを使ってるのでこれが原因そうです
ただ他に良さそうな方法もないですし 問題視されてるものならいつか解消されると思うのでとりあえずはこのままにします

遅いと言っても何時間もかかるわけではないですし 一括変換なので開始を押して あとは放置しておくだけです
多くのファイルを一括変換したいならウェブページの機能でやらずに専用ツールをインストールするでしょうし気にしないことにします

フロントライブラリ

変換処理は Rust で WASM 化することにしたのですが 画面側は何で作ろうか迷いました

簡単な画面ですし ビルド処理は挟みたくないので React などは避けたいです
となるととりあえず Lit でしょうか
ただ最近は LitElement が前提になっていて WebComponents 都合でコードが長くなったり面倒ごともあります
lit-html 単体は少し使いづらいところですし uhtml でいいかと考えましたが 面白さがあまりないです

せっかくですしあまり使っていない Solid か VanJS でも使ってみようかなとおもいます
ただ Solid は基本の使い方だと JSX なのでビルドが必要です
Lit 風なビルド不要の記法もありますが 変換処理がされないことで JSX のときとシグナルの扱いが違って面倒があります
VanJS を htm で使えばいいかなと思いましたが HTML 風なものばかりではなくたまには VanJS の本来の記法で書いてみるのもありかなと思って VanJS で htm なしで作ってみることにしました

実際作ってみると 結構不便なところがありました
state 化すると毎回 .val にアクセスするのが面倒です
値そのままでよければ state オブジェクトをプロパティや children としてそのまま渡せばいいのですが なんらかの変換を通したいことが多く そこを可変であることを伝えるために関数化しないといけないところが多いです

また配列やオブジェクトとしてまとめて管理したいけど 内部の要素ひとつひとつも変更を検知したいです
React 系だと再レンダリングして仮想 DOM の比較という形なので DOM の更新は差分だけですが VanJS だと関数化したところ全体が新しい DOM に置換されます
大きな単位を state で持って 全体を変更してしまうと 配列やオブジェクトを使うところ全体が作り直されてしまって影響が大きいんですよね
例えばリストの中のひとつのチェックを切り替えただけでリストの参照を新しいものにするとリスト全体が作り直されることになってムダです
React 系以上に更新範囲について考える必要があります

これを避けるなら 配列の要素やプロパティそれぞれで変更を検知して依存関係を更新してほしいです
それをするなら配列の要素やプロパティすべてを個別に state 化しないといけないです
そうなるとその部分も全部 .val でアクセスしないといけなくなり面倒です
あと VanJS に依存したくないロジック側でも .val を知らないといけなくなったりです

そんな感じで 再レンダリングの無駄はなくても更新範囲を考えたりしないといけないので完全に上位とも言えないのですよね
これらは VanJS というより Preact や Solid なども signal 系は同じなのかもです