Python で アニメGIF ダウンロード HTML を自動作成

[アニメーション作成フリーソフト「 PEAS motch! 」](http://peasmotch.jpn.org/) を使えば、４歳児から [１コマアニメーション](https://9vae.blogspot.com/p/blog-page_15.html) を簡単に作成できます。

複数のパソコンをLAN接続すれば、作成した全員のアニメーションをその場で上映することが簡単にできます。([9VAeワークショップ](https://qiita.com/danjiro/items/b9cde6e9d6e2a9fd6306))

ただ、作成したアニメを持ち帰りたいという要望には、上映画面をスマホで撮影する方法しかありませんでした。

今回、Pythonを使って、スマホにアニメGIFをダウンロードできるサイトを自動作成するプログラムを作りましたので、公開します。

Python プログラムが理解できるよう、順番に作成していきます。


![001.gif](https://qiita-image-store.s3.amazonaws.com/0/67734/50f1d09d-3090-4108-c697-00508568a9c7.gif)

# アニメーションをダウンロードする手順

1. [PEAS motch!](https://9vae.blogspot.com/p/9vae.html) もしくは、 [9VAeきゅうべえ](https://9vae.blogspot.com/p/9vae-download.html) でアニメを作成すると、EVAファイルができます。これを上映用のフォルダに保存します。
2. Pythonを使って、上映フォルダの EVAアニメをアニメGIFに変換します。
3. さらに、アニメGIFを表示するHTMLを自動作成します。
4. スマホのブラウザで、作成した HTMLを表示すれば、アニメGIFをスマホに保存することができます。

# 必要なソフト(Python) の入手

ここでは、Windows の Python を使って説明します。Macintosh, Raspberry Pi でも同じプログラムが動作します。

## Windows の場合

- [Python.jpの古インストーラ版](https://www.python.jp/install/windows/index.html)からダウンロードするのが簡単。[ここ（pythonlinks.python.jp）](https://pythonlinks.python.jp/)から32bit/64bitなどを選んでダウンロードできます。 Python2 と、Python3 がありますが、日本語を使う場合は、Python3が使いやすいようです。
    1. 上からダウンロードした、インストーラを実行します。
    2. インストール画面の一番下の「**Add Python to PATH**」にはチェックを入れ、「**Install Now**」ボタンでインストールするとよいでしょう。コマンドプロンプトで、Pythonが使えるようになります。


## Mac の場合

- python(Ver2), python3(Ver3) が最初からはいっています。ターミナルから使えます。
- ターミナルは「アプリケーション＞ユーティリティ」の中にはいっています。ドックの上にターミナルアイコンをドラッグして登録しておくとよいでしょう。
- ターミナルから「idle」を実行すれば、IDLEが起動します。
- ※Mac版 9View は、まだ、Pythonから起動できません。

# 必要なソフト(9view) の入手


- EVAファイル からGIFアニメの変換には、Windows版 または Mac版、PEAS motch! もしくは、 9VAeきゅうべえに付属する再生ソフト 9view を使います。
    1. [PEAS motch!をダウンロード](https://9vae.blogspot.com/p/9vae.html) したら、解凍してください。ダウンロードした場所で、右ボタンから「すべて展開」を実行してもかまいません。9vakid フォルダの中に 9view-full（.exe） があることを確認してください。

# 1. EVAファイルを順番に読み出す

まず、以下のように、EVAファイルをアニメGIFに変換する Python プログラムを作ってみましょう。

- 指定したフォルダの中の、EVAアニメを全部取得する
- EVAアニメから、GIFアニメの名前を作成する
- EVAアニメをGIFアニメに変換する



|項目|Pythonプログラムのポイント|
|:--|:--|
|文字コード|「UTF8」<br>メモ帳で保存する場合、「ファイル」＞「名前を付けて保存」＞下の「文字コード」を「UTF-8」にして保存。|
|拡張子|.py|
|実行１|IDLEを使う場合（Windows）<br>(1) 作成した .py ファイルを右ボタンでクリックし、メニューから「Edit with IDLE」を実行。<br>(2) Run ＞ Run Module (F5キー)|
|実行２|コマンドプロンプト（Windows）<br>(1) .py ファイルのフォルダで、シフトキーを押しながら右ボタンでクリックし、メニューから「コマンドウィンドウをここで開く」を実行。<br>(2) コマンドプロンプトから、python xxx.py を実行（xxx.pyはファイル名）|

- 以下のテキストを、「test1.py」という名前で「UTF-8」で保存してください。※ Python2 の場合パスに日本語がはいると動作しないことがあるようです。`c:\pytest` といったフォルダを作って保存するとよいでしょう。

- EVA_FOLDER, QVIEW_EXE は、自分の環境にあわせて修正してください。Windowsの場合は、QVIEW_EXE の最後に拡張子「.exe」が必要です。EVA_FOLDER は、PEAS motch! もしくは 9VAe の example フォルダを指定するとよいでしょう。※ただし、example フォルダの中に「\_bgm20sec.eva」というファイルがあると、アニメGIFに変換できません。右ボタンでクリックし、メニューから「名前の変更」を実行し「bgm20sec.eva」にリネーム（先頭の「\_」を削除）してください。
- PEAS motch!の場合「9view」は「9view-full」という名前になっています。右ボタンでクリックし、メニューから「名前の変更」を実行し「9view」に変更してください。（名前に -full がある場合、画面全体で再生します。9view にすれば、普通サイズで再生します。）
- 上の実行１、実行２の方法をつかって、実行してみてください。「指定されたパスが見つかりません。」というエラーが出た場合、EVA_FOLDER を正しく修正してください。パスの区切りは「/」です。

```py:test1.py
import os  	# ファイル操作
import subprocess # プログラム実行
EVA_FOLDER = 'C:/XXX/XXX/9vakid/example'  #アニメを保存するフォルダ
QVIEW_EXE = 'C:/XXX/XXX/9vakid/9view.exe' #9view.exe のフルパス

# メインループ
inpFolder = EVA_FOLDER                    #入力フォルダ
files = [f for f in os.listdir(inpFolder)] #入力
for fn in files:
	if(os.path.splitext(fn)[1] != '.eva'):
		continue
	gif = fn + '.gif'  #GIFファイル名
	gif = os.path.join(inpFolder,gif)
	eva = os.path.join(inpFolder,fn)
	cmd = (QVIEW_EXE , eva , '-gif')
	print(cmd)
	subprocess.run(cmd)  #gif作成

```

それぞれ、以下の意味です。

|項目|使用例|説明|
|:--|:--|:--|
|ファイル操作|import os |ファイル操作を使う|
|プログラム実行|import subprocess|プログラム実行を使う|
|EVAフォルダ|`EVA_FOLDER ='xxx'`|ファイル、パス名に日本語は使えない、パスの区切は「/」|
|9viewの場所|`QVIEW_EXE ='xxx'`|ファイル、パス名に日本語は使えない、パスの区切は「/」|
|フォルダのファイル取得|`files = [f for f in os.listdir(inpFolder)]`|inpFolderの中のファイルをfilesに取り出す|
|Forループ|`for cnt in files:`|filesの中身を全部処理。Forの中は、一段下げる。|
|拡張子取得|`os.path.splitext(fn)`|ファイル名fnを拡張子とそれ以外に分ける。拡張子はos.path.splitext(fn)[1]、名前はos.path.splitext(fn)[0]|
|次のループ処理に移る|`if(xxx):continue`|xxxの場合、次のループ処理に移る|
|文字の結合|`gif = fn + '.gif'`|文字の結合は「+」|
|ファイルパスの結合|`os.path.join(inpFolder,gif)`|フォルダとファイル名をつなげる|
|文字配列|`cmd = (QVIEW_EXE , eva , '-gif')`|文字配列作成|
|出力|`print()`|なんでも表示できる。Python2では()が不要|
|プログラム実行|`subprocess.run(cmd) `|プログラムと引数を文字配列で渡す|

- 正しく動作すれば、EVA_FOLDERで指定したフォルダに、アニメGIFファイルが作成されます。

# 2. フォルダをチェックし、新しい EVAを見つけたら、アニメGIFを作成する

上のプログラムに、以下の機能を追加しましょう。

- 1秒ごとに、EVAフォルダを調べる。
- GIFアニメが存在しない場合は変換する。
- GIFアニメより、EVAアニメが新しい場合は変換する。
- 自動保存のEVAファイルは変換しない。

- 以下のテキストを、「test2.py」という名前で「UTF-8」で保存してください。
- EVA_FOLDER, QVIEW_EXE は自分の環境にあわせて修正してください。9view-full は、9view にリネームしてください。
- 上にあげた方法で実行してみましょう。

```py:test2.py
import os  	# ファイル操作
import subprocess # プログラム実行
import time	# 時間処理

EVA_FOLDER = 'C:/XXX/XXX/9vakid/example'  #アニメを保存するフォルダ
QVIEW_EXE = 'C:/XXX/XXX/9vakid/9view.exe' #9view.exe のフルパス


# メインループ
inpFolder = EVA_FOLDER                    #入力フォルダ
print ('Type Ctrl+C to exit.')
while True:
	files = [f for f in os.listdir(inpFolder)] #入力
	for fn in files:
		if(os.path.splitext(fn)[1] != '.eva'):
			continue
		gif = fn + '.gif'  #GIFファイル名
		gif = os.path.join(inpFolder,gif)
		eva = os.path.join(inpFolder,fn)
		if( '_編集中' in eva):     #自動保存ファイルは無視
			continue
		if( '_とちゅう' in eva):
			continue
		if( '_autosave' in eva):
			continue
		if(os.path.exists(gif)):    #gifが存在,作成すみチェック
			if(os.path.getmtime(gif) > os.path.getmtime(eva)):
				continue
		cmd = (QVIEW_EXE , eva , '-gif')
		print(cmd)
		subprocess.run(cmd)  #gif作成
	time.sleep(1.0) #sleep(秒指定)

```

それぞれ、以下の意味です。

|項目|使用例|説明|
|:--|:--|:--|
|時間処理|import time |時間処理を使う|
|時間待ち|`time.sleep(1.0)`|１秒待つ|
|Whileループ|`while True:`|処理を繰り返す。ループの中身は、一段下げる。|
|プログラムの中断|Ctrl+C|Ctrl と C キーを同時に押せばプログラムを中断する|
|文字が含まれるか|`if( '_編集中' in eva):`|文字列 eva に、'_編集中'が含まれているか調べる|
|ファイルの存在|`if(os.path.exists(gif)):`|gifというファイルが存在するか調べる|
|ファイルの更新時間|`os.path.getmtime(gif)`|gifというファイルの更新時間を取得|

- 自動バックアップファイルには「\_編集中」「\_とちゅう」「\_autosave」が含まれるので、その場合、GIFアニメを作成しないようにします。

# 3. GIFアニメを表示するHTMLを自動作成する。

上のプログラムに、HTML作成機能を追加して、完成させましょう。

- 以下のテキストを、「qva2gif.py」という名前で「UTF-8」で保存してください。
- EVA_FOLDER, QVIEW_EXE は自分の環境にあわせて修正してください。9view-full は、9view にリネームしてください。
- HTMLファイルのヘッダは、「header.txt」 という別ファイルにまとめています。下にサンプルを掲載していますので、「qva2gif.py」と同じフォルダに作成してください。

```py:qva2gif.py
import os  	# ファイル操作
import subprocess # プログラム実行
import time	# 時間処理
import re 	# 文字置換
import webbrowser # ブラウザ

EVA_FOLDER = 'C:/XXX/XXX/9vakid/example'  #アニメを保存するフォルダ
QVIEW_EXE = 'C:/XXX/XXX/9vakid/9view.exe' #9view.exe のフルパス

HTML_OUTPUT = 'index.html'	#アニメGIFダウンロードサイト
FILE_HEADER = 'header.txt'	#HTML ヘッダーファイル

#HTML作成
def makeHTMLdoc(html):
	fw = open(html,"w")
	outstr = open(FILE_HEADER).read() 
	#GIF 画像を挿入
	files = [f for f in os.listdir(inpFolder)] #入力フォルダ
	files.sort(key=os.path.basename)       #ファイル名でソート
	for fn in files:
		if(os.path.splitext(fn)[1] != '.gif'):
			continue;
		outstr += '<br>' + fn + '<br>'
		outstr += '<img src="' + fn + '"><br>\n'
	outstr += '</body></html>' 
	outstr = re.sub("%title%", '「１コマアニメーション」ダウンロード', outstr)
	fw.write(outstr)
	fw.close()

# メインループ
openWeb = True				#HTMLを開く
inpFolder = EVA_FOLDER      #入力フォルダ
print ('Type Ctrl+C to exit.')
while True:
	files = [f for f in os.listdir(inpFolder)] #入力
	makeHTML = False #HTML作成するフラグ
	for fn in files:
		if(os.path.splitext(fn)[1] != '.eva'):
			continue
		gif = fn + '.gif'  #GIFファイル名
		gif = os.path.join(inpFolder,gif)
		eva = os.path.join(inpFolder,fn)
		if( '_編集中' in eva):     #自動保存ファイルは無視
			continue
		if( '_とちゅう' in eva):
			continue
		if( '_autosave' in eva):
			continue
		if(os.path.exists(gif)):    #gifが存在,作成すみチェック
			if(os.path.getmtime(gif) > os.path.getmtime(eva)):
				continue
		cmd = (QVIEW_EXE , eva , '-gif')
		print(cmd)
		subprocess.run(cmd)  #gif作成
		makeHTML = True	#HTMLを更新する
	html = os.path.join(inpFolder,HTML_OUTPUT)
	if(makeHTML): 
		makeHTMLdoc(html)
	if(openWeb):
		webbrowser.open(html)
		openWeb = False
	time.sleep(1.0) #sleep(秒指定)

```

それぞれ、以下の意味です。

|項目|使用例|説明|
|:--|:--|:--|
|文字置換|import re |文字置換を使う|
|ブラウザ|import webbrowser |ブラウザ起動|
|関数定義|`def makeHTMLdoc(html):` |HTML作成する関数の定義。htmlは引数（ファイル名）関数の中身は、一段下げる。|
|ファイル出力|`fw = open(html,"w")` |書き込みファイルを開く。htmlはファイル名|
|テキスト読み出し|`open(XXX).read() `|ファイル名XXXから文字列を取得|
|ソート|`files.sort(key=os.path.basename)` |ファイル名でソート|
|改行|`'<br>' `|HTMLの改行|
|画像表示|`'<img src="' + fn + '"><br>\n'` |HTMLの画像表示|
|HTML終了|`'</body></html>'`|HTMLの最後のタグ|
|文字の置換|`re.sub("%title%", 'XXXX', outstr)`|文字列の中の"%title%"を、XXXXで置き換える|
|ファイル書き込み|`fw.write(outstr)`|文字列のファイル書き込み|
|ファイル書き込み|`fw.close()`|ファイル書き込み終了|
|関数の実行|`makeHTMLdoc(html)`|HTML作成関数を呼ぶ|
|ブラウザ起動|`webbrowser.open(html)`|作成したHTMLを開く|

HTMLファイルのヘッダのサンプルです。
- qva2gif.py と同じ場所に入れてください。

```HTML:header.txt
<?xml version="1.0" encoding="Shift_Jis"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
	<title>%title%</title>
</head>
<body>
```
- 実行してから、EVAファイルを修正してみてください。アニメGIFが自動的に作成され、HTMLファイルを作り直します。

---
# 関連記事

1. [無料ソフトでアニメを作ってみよう（9VAe きゅうべえ）](http://qiita.com/danjiro/items/253e5a33a38599098274)
- [スクラッチ、ビスケットの次は 9VAe＝第３のプログラミング学習環境](http://qiita.com/danjiro/items/d856d393b3e138af123a)
6. [書き順アニメーションの作り方](http://qiita.com/danjiro/items/8dd0d7c7263f62189437)
7. [9VAeきゅうべえ：長いアニメを作る方法](http://qiita.com/danjiro/items/020cd885edb5eb3d9fb0)
- [動くLINEスタンプのAPNG作成：無料ソフト9VAeきゅうべえ](http://qiita.com/danjiro/items/e4d9eb2b22f90ebd1e91)
- [9VAeきゅうべえ」で絵を描かずに作れるGIFアニメ](http://qiita.com/danjiro/items/7fa584a4336cda9c0a05)
- [9VAeきゅうべえで作成したSVGアニメーション](http://qiita.com/danjiro/items/1b4f6b5a520ade762116)
-  [アニメソフト 9VAe をカスタマイズする方法](http://qiita.com/danjiro/items/c5dc07671ffdbbb8a9a9)
- [9VAeをキッズプラザ大阪向けに改造する](http://qiita.com/danjiro/items/bbb10e07a9775a938200)
- [9VAe / 9svg データフォーマット解説](http://qiita.com/danjiro/items/0d4ac334a7a97ddb4fe2)
- [OpenCV と Python を使ったアニメーション動画用紙のスキャン画像位置合わせ](http://qiita.com/danjiro/items/985afccd07722d4c21e9)
- [Python で アニメGIF ダウンロード HTML を自動作成](https://qiita.com/danjiro/items/7d03223c85b3df317ab8)