ハイパーマッスルエンジニア

Vim、ShellScriptについてよく書く

はてなブログでgifの代わりにmp4で投稿するために、Github Actionsでgif→mp4変換を自動化した

f:id:rasukarusan:20210125191908p:plain:w500

gifの欠点

  • ファイルサイズがでかい → ページ読み込みが遅くなる
  • シークバーが表示されない → 一時停止、早送りができない

MP4にしてvideoタグで埋め込むといい

<video controls muted autoplay playsinline width="95%">
  <source src="mp4動画のURL">
</video>

gifの圧縮アルゴリズムはそこまで最適化されていないため、MP4などの動画フォーマットのほうがファイルサイズを小さくできるらしい。
またvideoタグで埋め込むのでシークバーが表示されるようになる。

こんな感じで再生できるようになる

gif→mp4の変換

コマンド。ffmpegがない場合brew install ffmpegでインストールできる。

ffmpeg -i org.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" video.mp4

いちいち変換するのが面倒くさいのでGithub Actionsする

gif撮ってpushしたらmp4動画の作成が終わっている、という感じにしたい。

github.com

workflow

下記を満たすようなstepを書いた。

  • gifが追加されたとき: mp4の作成
  • gifがリネームされたとき: 以前の名前で作られたmp4を削除し、新たな名前でmp4を作成
  • gifが削除されたとき: mp4の削除
  • gif以外のファイル: 対象外にする
# .github/workflows/convert.yml
name: Convert GIF To MP4

on:
  push:
    branches:
      - master
jobs:
  build:
    name: Convert GIF
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Setup ffmpeg
        uses: FedericoCarboni/setup-ffmpeg@v1-beta
        id: setup-ffmpeg

      - name: Convert
        run: |
          git show --pretty="format:" --name-status HEAD | grep '.gif$' | while read target; do
            read status gif <<< "$(echo $target | awk '{print $1,$NF}')"
            printf "\e[31m===========${gif}============\e[m\n"
            filename=$(basename $gif | sed 's/\.[^\.]*$//')
            dir=$(dirname $gif)
            mp4=${dir}/${filename}.mp4
            case "$status" in
              'A') # add
                echo 'add'
                [ ! -e $mp4 ] && ffmpeg -i $gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" $mp4 </dev/null
                ;;
              [R]*) # rename
                echo 'rename'
                read pre_mp4 <<< "$(echo $target | awk '{print $2}' | sed 's/\.[^\.]*$/.mp4/' )"
                [ -e $pre_mp4 ] && git rm $pre_mp4
                [ ! -e $mp4 ] && ffmpeg -i $gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" $mp4 </dev/null
                ;;
              'D') # delete
                echo 'delete'
                [ -e $mp4 ] && git rm $mp4
                ;;
            esac
          done

      - name: Commit and push
        run: |
          git status
          if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
            git config --local user.email "action@github.com"
            git config --local user.name "GitHub Action"
            git add -A
            git commit -m "convert gif to mp4"
            git push origin master
          fi

f:id:rasukarusan:20210125190201p:plain

pushしたらgifがmp4に変換される

f:id:rasukarusan:20210125190144p:plain

pushしたのはgifだけなのにmp4が出来上がっている状態

f:id:rasukarusan:20210125190125p:plain

mp4動画のURLをコピーできる

終わり

Github Actionsこんな使い方もあるんだ。楽しい。

参考