なぜGIFアニメか
スマホアプリ開発やフロントエンド開発をやっている方はGithubのIssuesやPull requestsに動画を載せたい時があると思います。しかしそられはmp4等の動画ファイルのアップロードに対応していません。mp4ファイルをアップロードしようとするとこのようなエラーが出ます。
しかしGIFファイルのアップロードには対応しており、GIFにはアニメーション機能があります。256色までといった画質面の妥協点はありますが、それを使うと動画を載せることができます。
なぜフォルダ監視か
私は普段、Androidアプリ開発をしていますが、現状のGIFアニメ作成の工程に非効率を感じていました。
(工程はMacを前提にしています)
工程1 Android端末の画面録画を行う
- Android StudioのLogcat下タブをクリック
- 録画する端末のLogcatを表示しているか確認する
- Logcat左下の
Screen Record
ボタンをクリック -
Start Recording
ボタンをクリック
コマンドライン派の方は補足参照。
工程2 mp4形式のファイルを保存する
- 保存フォルダを選択
- 必要に応じてファイル名を設定
-
Save
ボタンクリック
工程3 GIFアニメ形式にエンコードする。
ffmepgコマンドでmp4ファイルをgifファイルに変換します。
Githubにはアップロード画像の10MB制限があるので、横幅320px、10fpsにして容量を小さくしています。
ffmpeg -i input.mp4 -vf scale=320:-1 -r 10 output.gif
工程4 Githubにアップロードする
Githubのコメント入力欄にドラッグアンドドロップすると、GIFアニメをアップロード出来ます。
効率化
フォルダ監視を行えば工程 - ファイル保存をトリガーにして工程3- GIFアニメ形式にエンコードを自動で行うことが出来て、作業を効率化できます。
フォルダ監視を行う
このようなPythonプログラムを作成しました。
import os
import time
from watchdog.events import FileSystemEventHandler
from watchdog.events import FileCreatedEvent
from watchdog.observers import Observer
from pathlib import PurePath
import subprocess
import signal
class MovieFileSystemEventHandler(FileSystemEventHandler):
def on_any_event(self, event):
if(type(event) == FileCreatedEvent):
src_path = event.src_path
pp = PurePath(src_path)
if pp.suffix != '.gif':
output_path = "%s/%s.gif" % (os.path.dirname(src_path), pp.stem)
subprocess.run(['ffmpeg', '-i', event.src_path, '-vf',
'scale=320:-1', '-r', '10', output_path])
exit_flag = False
def handle_exit(sig, frame):
global exit_flag
exit_flag = True
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
path = "%s/movie" % os.environ['HOME']
event_handler = MovieFileSystemEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
while exit_flag == False:
time.sleep(1)
observer.stop()
observer.join()
このプログラムではWatchdogというライブラリを使うのでpipコマンドでインストールします。
pip install watchdog
また、このプログラムでは ~/movie を監視して、エンコード結果のgifアニメも同じ場所に保存しますが、別のフォルダが良い場合はお好みに応じてこちらの箇所を書き換えてください。
path = "%s/movie" % os.environ['HOME']
監視フォルダを作製します。
mkdir ~/movie
Pythonプログラムを実行します。常駐プログラムになります。
python watchdog.py
これでフォルダが監視されます。動画ファイルが監視フォルダに保存されてると、同じ名前のgifアニメファイルが自動で生成されます。
常駐を終了するときはコンソールでCtrl + Cキーを入力します。
補足
ffmpegをインストールする
brewを使えばインストール出来ます。
brew install ffmpeg
Androidの画面録画をコマンドラインで行う
adb shell
adb /mnt/sdcard
# 録画開始
screenrecord output.mp4
# Ctrl + C で録画終了
exit
adb pull /mnt/sdcard/output.mp4
Docker化する場合の注意点
Docker化も可能です。しかし正常に動作しないケースがあります。Android Studioから監視ディレクトリへの直接保存は問題無いですが、他のフォルダからの移動の場合は正常に動作しませんでした。
FROM python:3.7-alpine
WORKDIR /root/
RUN apk add --update --no-cache ffmpeg
RUN pip install watchdog
COPY watch.py .
CMD python watch.py
version: '3'
services:
main:
build: .
volumes:
- ~/movie:/root/movie
ビルドして実行する。
docker-compose build
docker-compose up
正常に動作しないケースの詳細
class MovieFileSystemEventHandler(FileSystemEventHandler):
def on_any_event(self, event):
# type(event) を確認する
他のフォルダから監視フォルダへファイルを移動すると、FileCreatedEventではなくFileModifiedEventが発生しました。FileModifiedEventでも動画のGIFアニメ変換を行おうと思いましたが、他のフォルダからのコピーの場合はFileCreatedEventの後にFileModifiedEventが発生してしまい、適切なトリガーを作るのが難しと思いました。