Qiita記事でAPNGの投稿と再生はできるのか、実際に上げてみた

当然だが、内容は執筆時点のものとなる。


# 本題：拡張子を `.png` にすれば上げられる

まず、拡張子 `.apng` の APNG ファイルを上げようとすると…

![Something went wrong]()

```
![Something went wrong]()
```

失敗する。

で、拡張子を `.png` に変えて上げてみると…

![q.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/becc2b9f-d118-7bac-584d-b9784e827e7f.png)

```
![q.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/becc2b9f-d118-7bac-584d-b9784e827e7f.png)
```

**上げられる**。
ここでは、緑背景に白文字の「Q」が回転し続ける APNG を上げている。

ただし、**上げられる**ことと**再生できる**ことはまた別のお話。
この APNG が記事内で再生できるのかどうか、仮に記事内ではできないとしてもクリックで別窓表示すれば再生できるのか、といった点については、今あなたが見ている光景があなたの環境での答えとなる。

## GitHub でも同じ手口で APNG が上げられる

GitHub の Issue や Gist 等のエディターでも、`.apng` の APNG ファイルは直接上げることができず、`.png` に変更してやれば上げられるようになる。

https://gist.github.com/Phroneris/12e4d54c5eb6163433ceeee6ec67bbde

といっても、特に Issue の方は Qiita よりもかなり手広いファイル形式に対応しているので、MP4 等の動画の方が良い場合も普通にありそう。

> We don’t support that file type. Try again with a GIF, JPEG, JPG, MOV, MP4, PNG, SVG, WEBM, CSV, DOCX, FODG, FODP, FODS, FODT, GZ, LOG, MD, ODF, ODG, ODP, ODS, ODT, PATCH, PDF, PPTX, TGZ, TXT, XLS, XLSX or ZIP.


# 背景：Qiita でのアニメーションの選択肢について

Qiita でアニメーション画像を使いたい状況は多々ある。
ソフトウェアの動作のキャプチャ映像を示すのが主な用途となるだろう。

GIF アニメなら元から上げられる。
しかし、今の時代に **256 色縛りなんてやってらんねえ**。
キャプチャ系の動画は実写系より断然色数が少なく済むのでまだマシだろうが、それでも UI にちょっとシャドーやグラデーションが入るだけで 256 色なんて早々に突破してしまうので、大抵はなんか変なディザリングが入って汚くなる。
下記の記事（およびそこの[私のコメント](https://qiita.com/yusuga/items/ba7b5c2cac3f2928f040#comment-1247c6999edbe7d26878)）のように、ffmpeg のオプションでディザリングを切るとかの色々な工夫は確かにできるが、そもそも今の時代においてそれは費やすに値する労力なのか、疑問に思わざるを得ない。

https://qiita.com/yusuga/items/ba7b5c2cac3f2928f040

WebP アニメは上げられない。

AVIF アニメは Firefox が対応しておらず、何なら Qiita ではそのせいで GIF アニメの再生にすら支障が出ている。

https://help.qiita.com/ja/articles/qiita-image-upload#firefox-gif

> 画像はCDNによりブラウザの種類に応じて適切な形式に変換されます。FirefoxではAVIFに変換されますが、現在AVIFのアニメーションには対応していないため、アニメーションが動作しない場合があります。（2023年2月時点）
> 画像をクリックして表示した場合は、元の画像が表示されるので、アニメーションが動作します。

そして APNG は…、拡張子を変えれば**上げられる**。
色数制限も不可逆圧縮も無く、もちろんアルファチャンネルも使えるので、**動くなら**現状最高の形式となる。
まぁ上記ヘルプページで思いっ切りサポート外呼ばわりされてるけど。

> `apng`等、その他はサポート外のため正しく表示されない場合があります。

他の選択肢としては、YouTube 等に投稿した動画の埋め込みがある。
音声を伴う映像なら当然埋め込み一択になる。
また、見る側がシークしたくなるような長い映像の場合にも、無理にアニメーション画像にこだわるよりは潔く動画にしておく方が読み手に優しいだろう。


# 本題の APNG を作成したコード

本題の APNG はこれ。（再掲）

![q.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/becc2b9f-d118-7bac-584d-b9784e827e7f.png)

これは、ffmpeg を使って下記の Bash スクリプトで作成した。
…シェルスクリプトは無限に難読になりがちなので意図的にスペースや改行を入れまくってみたけど、これはこれでやりすぎ。

```bash
#!/usr/bin/env bash

boxSize=100
fontSize=90
boxColor=0x55C500
fontColor=white

ffmpeg -loglevel warning \
  -f lavfi -i "
    color = color=${boxColor}: size=${boxSize}x${boxSize}
    , format = rgba
  " \
  -filter:v "
    split [back] [front];
    [front]
      lut = a=0: r=0: g=0: b=0
      , drawtext =
        text='Q'
        : fontfile='C\:/Windows/fonts/arialbd.ttf'
        : fontcolor=${fontColor}
        : fontsize=${fontSize}
        : x=(main_w-text_w)/2
        : y=(main_h-text_h)/2
      , rotate =
        angle=(t*60+30)*PI/180
        : fillcolor=black@0
      , unpremultiply = inplace=1
      [text];
    [back] [text] overlay = format=rgb
  " \
  -plays 0 -loop 0 -t 6 -f apng -y q.png
```

動画フィルター `-filter:v`（`-vf` とも）の処理のイメージはこんな感じ。

![process.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/e242ba61-3b9f-c8eb-39d8-b09cb01003ad.png)

なお、このイメージも拡張子 `.png` の APNG ファイルとして上げている。
さすがにこれは AviUtl で作った。
ただし AviUtl はデフォルトでは APNG 出力に対応していないので、[ffmpegOut プラグイン](https://github.com/rigaya/ffmpegOut)を導入し、[APNG プリセット](https://scrapbox.io/Mr-Ojii/ffmpegOut_stg%E7%BD%AE%E3%81%8D%E5%A0%B4)から下記のように変更して出力した。

- 出力拡張子：`.apng` → `.png`
- 転送色空間：`rgba` → `rgb`
  - アルファチャンネルは特に要らないため
- コマンド：`-c:v apng -plays 0` → `-c:v apng -plays 0 -f apng`
  - 静止画 PNG として出力しようとするのを防ぐため

ついでに、本題の APNG を GIF アニメに変換するならこうする。

```bash
ffmpeg -loglevel warning -f apng -i q.png \
  -vf "
    split [a] [b];
    [a]
      palettegen =
        reserve_transparent=0
        : stats_mode=diff
    [p];
    [b] [p] paletteuse = diff_mode=rectangle:dither=none
  " \
  -y q.gif
```

既に述べた通り、GIF アニメは普通に Qiita へ**上げられる**が、やはり再生できるとは限らない。

![q.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/30dbc083-4a6e-759e-2e24-96fb98adf7e1.gif)

```
![q.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/30dbc083-4a6e-759e-2e24-96fb98adf7e1.gif)
```

# 筆者環境

- Windows 10 Home 64-bit 22H2
- Google Chrome 111.0.5563.149
- GNU bash 5.2.15(1)-release（Git for Windows 2.24.0 により導入）
- ffmpeg 6.0-essentials_build-www.gyan.dev（Chocolatey 1.3.1 により導入）
- AviUtl 1.10
  - 拡張編集 0.92
  - ffmpegOut 1.07

…Qiita での APNG の使用について検証したかっただけなのに、気付けば 1 週間かけて ffmpeg への理解が無駄に深まっていた。

&ZeroWidthSpace;

おわり