mastodonでavifとwebpに対応する方法

# はじめに

画像は軽い方がよいですね。

というわけで本家が対応していなくても、無理やり外部スクリプトから対応させます。

make を使用していますので、既に変換済の画像を変換しません。

## ビルドスクリプト

```imagebuild.pl
#!/usr/bin/env perl

my $path="/home/mastodon/live/public/system";
# FreeBSDなら /usr/local/www/mastodon/public/system
my $makefile="./Makefile";
# 巨大になるのでramdiskに置いた方がよいのかもしれないし、そうではないかもしれないし
my $makepath=".";

my $jobs="8";
my $q=80;

my $pwd=`/usr/bin/pwd`;
$pwd=~s/[\r|\n]//g;
chdir $path;

my $finds=`find $path`;
my @finds=split(/\n/, $finds);

foreach my $find (@finds) {
        if($find=~/\.jpeg$/) {
                push(@array, "$find");
        }
        if($find=~/\.png$/) {
                push(@array, "$find");
        }
}

chdir $pwd;

my $makedata="all: \\\n";
foreach(@array) {
        $makedata.="\t$_.webp \\\n";
        $makedata.="\t$_.avif \\\n";
}



$makedata.="\n\n";

foreach(@array) {
        $makedata.=<<EOM;
$_.webp : $_
        echo cwebp -q $q $_ -o $_.webp
        cwebp -q $q $_ -o $_.webp

$_.avif : $_
        echo avifenc -j $jobs -s 0  --min 15 --max 63 --minalpha 63 --maxalpha 63 $_ $_.avif
        avifenc -j $jobs -s 0  --min 15 --max 63 --minalpha 63 --maxalpha 63 $_ $_.avif

EOM
}

if(open($W, ">$makefile")) {
        print $W $makedata;
        close($W);

        chdir "$makepath";
        print "make -j$jobs -f $makefile\n";
        `make -j $jobs  -f $makefile2>&1`;
} else {
        print "Error\n";
}

```

これをmastodon ユーザーでcrontabで毎分動作させます

:::note info
既に運用中のインスタンスであれば、すぐにcrontabに登録せず、一度スクリプトを実行します。その後crontabに登録してください。
:::

crontabの1行目に
```
PATH=/bin:/usr/bin:/usr/local/bin
```
を設置して

```
* * * * * /usr/bin/perl /home/pathto/imagebuild.pl 2>&1 >/dev/null
```

とします


## .htacccess っぽいものを設置する

以下の nginx版です
https://qiita.com/nanakochi123456/items/adedfe54e50bbb3653d5

```/etc/nginx/nginx.conf
# FreeBSDなら /usr/local/etc/nginx/nginx.conf
http {
.... 
# http { の中に以下を入れる
  map $http_accept $webp_suffix {
    default        "";
    "~image/webp"  ".webp";
  }
  map $http_accept $avif_suffix {
    default        "";
    "~image/avif"  ".avif";
  }
```

```/etc/nginx/mime.types
# FreeBSDなら /usr/local/etc/nginx/mime.types

# 以下を適切な所に追加
    image/avif                            avif;
```

```/etc/nginx/sites-available/mastdon.conf
#FreeBSDなら /usr/local/www/mastodon/dist/nginx.conf

# location ~ ^/system/ { の下に入れる
location /system {
   location ~ \.(png|jpe?g)$ {
       add_header Vary "Accept-Encoding";
       access_log off;
       log_not_found off;
       expires max;
       try_files $uri$avif_suffix $uri$webp_suffix $uri =404;
   }
}
```
# 現実的には
運用してみてわかったのですが、
- avifはやはり処理が重い
- これではLTLで圧縮がかかりにくい

ということで、このようなソースコードで運用しています。

```nanosleep.cpp
#include <unistd.h>

constexpr int TIME_TO_SLEEP = 500;

int main() {
    usleep(TIME_TO_SLEEP * 1000);;
    return 0;
}
```

```webp.sh
#!/bin/sh
PATH=/bin:/usr/bin:/usr/local/bin
SCRIPT=/home/mastodon/webp.pl
SLEEP=/home/mastodon/nanosleep
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1

perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
$SLEEP 1
perl $SCRIPT
```