LoginSignup
3
4

Python + Flask でアニメGIF ダウンロードサーバーを作る

Last updated at Posted at 2020-02-02

アニメGIF ダウンロードサーバーとは

  • フリーソフト9VAeをベースに開発された、PEASmotch! は、キッズプラザ大阪に5台設置され、毎日150から200本のアニメが作られている。
  • 作成したベクトルアニメーションは、共有サーバーに保存され、専用プレーヤー 9view を使って、連続したアニメーションとして大型ディスプレイで上映されているが、かねてから、作ったアニメーションをスマホに入れて持ち帰りたいという要望があった。
  • それを実現する方法として、共有サーバーのアニメーションをアニメGIFに変換する python プログラムを公開した。
  • 今回、Flask を用いて、スマホからアクセスできるサーバープログラムを作成したので公開する。
    • スマホにアニメをダウンロードできる
    • サイトのURLアドレスをQRコードで表示する
    • スマホアプリ(9VAe, PEASmotch)からアニメをアップロードできる

以下の記事も関連している

項目 パソコン スマホ
WiFiアクセスポイントの設置
共有フォルダにアニメを保存、連続上映
作成したアニメをスマホにダウンロード(本記事)
スマホアプリからアニメをアップロード(本記事)

以下はプログラムの実行例。表示されているURLをスマホでアクセスすれば同じ画面が表示され、アニメーションをダウンロードできる。

サーバーを実行した図

Python のインストール

プログラムは python を使う。Windows と ラズベリーパイで作成してみた。

Windowsの場合

Windowsの場合(仮想環境)

  • こちらの記事の anaconda は、仮想環境で実行できる。アプリごとにライブラリを使い分けるときに便利。
  • 日本語を使いたいので、Python Ver3をダウンロード。(anacondaインストール後の「anaconda-navigator」の実行はWindowsロゴから行う必要があったが、ほかは記事どおりに実行できた)

ラズベリーパイの場合

  • python(Ver2), python3(Ver3) が最初からはいっている

Flask とQRコードライブラリのインストール

次のコマンドで、Flask とQRコード用ライブラリをインストールする。(ラズベリーパイの場合 pip3 、 python3 をつかう)pip が見つからない場合、pythonをインストールしたなかに、pip がはいっていると思われるので、そのフォルダに移動してから実行するとよい。

pip install Flask
pip install qrcode
pip install pillow

Linuxで上の命令で失敗した場合は、次の命令をためしてみてください

sudo apt-get install python-Flask
sudo apt-get install python-qrcode
sudo apt-get install python-pillow

アニメGIF ダウンロードサーバー

環境が整ったのであとはプログラム

フォルダ構成

Flask サンプルを参考に、以下のフォルダ構成とした。app.py がプログラム本体。ここに Flask を起動するコードがかかれている。templatesの中の設定データを利用して Web サイトの応答が行われる。

py    
  ├──app.py (プログラム本体)   
  ├──static    
  │    ├──qrcode.png(プログラムで作成される)    
  │    └──setpath.ini(プログラムで作成される)    
  └──templates    
       ├──index.html    
       └──layout.html    

python Flask ソースコード

  • ソースコードは、すべて UTF-8 で作成すること

templates    

Webサイトの内容が index.html に書かれている。

index.html
{% extends "layout.html" %}
{% block content %}
<img src="{{ url_for('static', filename='qrcode.png') }}" width="200">
<br>
画像を長押しすればダウンロードできます。<br>
Long press on the image to download.<br>
<div  align="right">
{{ message }} <br>
<a href="{{ url_for('static', filename='setpath.ini') }}">setpath.ini</A>
</div>
{% if images %}
  {% for path in images %}
    {% if '.eva.gif##' in path %} 
    {% elif '.eva.gif' in path %} 
      <div>
        <img src="images/{{ path }}" style="margin-top: 10px; vertical-align: bottom; width: 200px;">
        {{ path }}
      </div>
    {% endif %}
  {% endfor %}
{% endif %}

{% endblock %}
記述 意味 補足
{% extends "layout.html" %} ページレイアウトの設定ファイル
{% block content %}...{% endblock %} この部分が中身
<img src="{{ url_for('static', filename='qrcode.png') }}" staticフォルダの中のQR画像を表示
{{ message }} 引数messageの文字列表示
{% if images %} 引数images(ファイル名リスト)があれば
{% for path in images %} imagesリストの要素path(ファイル名)を順番に
{% if '.eva.gif' in path %} .eva.gifが含まれるファイルだけ処理
<img src="images/{{ path }}" images/フォルダのファイル
{{ path }} ファイル名も表示
{% endif %} ifの終わり
{% endfor %} forの終わり
layout.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>9VAe Anime Post</title>
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>
記述 意味 補足
{% block content %}{% endblock %} この部分に中身がはいる

app.py

以下の値は環境に応じて設定

定数 意味 補足
EVA_FOLDER アニメを保存するフォルダ 例では「/home/pi/2018」
QVIEW_EXE 9view.exe のフルパス Windowsでもパスの区切りは'/'
HTTP_URL 公開するURLアドレス 最初は'127.0.0.1'でテストする
HTTP_PORT 公開するポート 最初は5000でテストする
  • アニメの保存フォルダについて、共有フォルダ直下でうまくいかない場合、共有フォルダの中のフォルダを指定してみてください。
app.py
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, make_response

import os         # ファイル操作
import subprocess # プログラム実行
import time       # 時間処理
import re         # 文字置換,正規表現
import webbrowser # ブラウザ
import threading  # multi thread
import qrcode     # QRコード生成

EVA_FOLDER = '/home/pi/xxxxxx'    #アニメを保存するフォルダ
QVIEW_EXE = '/home/pi/9va/9view'  #9view.exe のフルパス
HTTP_URL = '192.168.99.1'         #公開するURLアドレス
HTTP_PORT = 8080                  #公開するポート

app = Flask(__name__)

inpFolder = EVA_FOLDER

class MyThread(threading.Thread):
    def __init__(self):
        super(MyThread, self).__init__()

    def run(self):
        loop(self,False)

@app.route('/')
def index():
  global inpFolder
  return render_template('index.html', images=sorted(os.listdir(inpFolder)[::-1], reverse=True), message = inpFolder)

@app.route('/images/<path:path>')
def send_js(path):
  global inpFolder
  return send_from_directory(inpFolder, path)

@app.route('/',methods=["POST"]) #アニメのアップロード
def save_eva():
  global inpFolder
  mno = -1
  #print("Posted file: {}".format(request.files['file']))
  file = request.files['file']
  if(file.filename.endswith('.eva')):
      files = [f for f in os.listdir(inpFolder)]   #入力
      for fn in files:
        eva = os.path.join(inpFolder,fn)
        if(not eva.endswith('.eva')):
            continue
        if( '_編集中' in eva):     #自動保存ファイルは無視
            continue
        if( '_とちゅう' in eva):
            continue
        if( '_autosave' in eva):
            continue
        no = int(os.path.splitext(os.path.basename(fn))[0])
        if(no > mno):               #最終番号を探す
            mno = no

      savepath = os.path.join(inpFolder, '%04d.eva' % (mno+1))
      file.save(savepath)
  return str(mno+1)   #保存した番号を返す


# GIF変換ループ
def loop(self,askFolder):
  global inpFolder
  drmax = '0000-0000'
  while True:
    dirs = [f for f in os.listdir(EVA_FOLDER)] #一番新しい日付を取得
    drs = [s for s in dirs if re.match('[0-9]{4}-[0-9]{4}', s)]
    for dr in drs:
      if dr > drmax:
        drmax = dr
    inpFolder = EVA_FOLDER + '/' + drmax
    if(askFolder):
        return inpFolder

    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') #-gif オプションでGIFに変換
        print(cmd)                  #変換したことを表示
        subprocess.run(cmd)         #gif作成
    time.sleep(1.0) #sleep(秒指定)
  return inpFolder


t = MyThread()
inpFolder = loop(t,True)            #evaが修正されたらgif作成、新フォルダへの移動
t.start()

html = 'http://' + HTTP_URL + ':' + str(HTTP_PORT)
img = qrcode.make(html)          #QR code作成
img.save('static/qrcode.png')
with open('static/setpath.ini', mode='w') as f:
    f.write(html)


if __name__ == '__main__':
    webbrowser.open(html)            #ブラウザ起動
    app.run(debug=True, host=HTTP_URL, port=HTTP_PORT)

記述 意味 補足
from flask import Flask, ... Flask用拡張
import 関数を使えるようにする
app = Flask(name) 処理の名前
class MyThread(threading.Thread): マルチスレッド定義 Flask内で同時実行する
def run(self): MyThreadで実行する処理
@app.route('/') ルートアクセスで表示される内容
def: 関数定義
global inpFolder 変数inpFolderは全体で共通
render_template('index.html' Flaskのtemplates/index.html を表示
os.listdir(inpFolder)[::-1] inpFolderのファイル全部 -1は最後の意味
sorted(xxx, reverse=True) リストを逆順でソート
@app.route('/images/path:path') /images/のアクセスで表示される内容 index.htmlから呼ばれる
send_from_directory(inpFolder, path) inpFolderフォルダのpathファイル
@app.route('/',methods=["POST"]) POSTを受け取ったときの処理 アップロード用
request.files['file'] POSTされたファイル
if(file.filename.endswith('.eva')): 拡張子が.evaの場合
files = [f for f in os.listdir(inpFolder)] inpFolderのファイルをリスト化
os.path.splitext(os.path.basename(fn))[0] 拡張子のないファイル名
int(文字列) 文字列を数値に変換
'%04d.eva' % (mno+1) 数値(mno+1)を文字列に変換
savepath = os.path.join(inpFolder,ファイル名) フォルダとファイル名の結合
file.save(savepath) ファイルをsavepathに保存 POSTされたファイルを別名で保存
if re.match('[0-9]{4}-[0-9]{4}', s) s が「数字4桁-数字4桁」の場合 正規表現
if(os.path.exists(gif)): ファイルが存在した場合
os.path.getmtime(gif) ファイルの更新時間
cmd = (QVIEW_EXE , eva , '-gif') コマンド作成 EVAアニメをGIFに変換
subprocess.run(cmd) コマンド実行
time.sleep(1.0) 1秒停止
t = MyThread()
t.start()
マルチスレッドの実行
img = qrcode.make(html) QRコード画像imgを作成
img.save('static/qrcode.png') 画像imgをstaticフォルダに保存
with open('static/setpath.ini', mode='w') as f: 書き込みファイルをオープン
f.write(html) 文字列の書き込み
webbrowser.open(html) ブラウザ起動
app.run(debug=True, host=HTTP_URL, port=HTTP_PORT) URL、Portを指定して実行

使い方

ラズベリーパイで実行した例を示す

  • ラズベリーパイで WiFi アクセスポイントを作成し、URL「192.168.99.1」で公開した。やり方はこちら
  • ターミナルでpyフォルダに移動。python3 app.py でプログラムを実行
  • ブラウザが開き、以下のように表示されるezgif.com-video-to-gif.gif

スマホにアニメをダウンロードする方法

  1. スマホのWiFi設定で、ラズベリーパイアクセスポイントにWiFiをつなぐ
  2. スマホでQRコードをみてURLをひらく > 上と同じ画面が開く
  3. アニメーションを長押しし、メニューから「ダウンロード」を選べばGIFアニメをダウンロードできます。

スマホアプリ(PEASmotch!one)からアニメをアップロードする方法

  1. ラズベリーパイアクセスポイントにWiFiをつなぐ
  2. スマホでQRコードをみてURLをひらく > 上と同じ画面が開く

setpath.iniの設定

  1. setpath.ini を長押しし、「リンクをダウンロード」>setpath.ini ファイルをダウンロードする
  2. ファイルマネージャなどのアプリをつかって、setpath.ini ファイルを「PEASmotch」フォルダに入れる
  3. PEASmotchを起動し、PEASロゴをタッチ、メニューの一番下に「アップロード」が追加されていればOK。
  • メニューの最後の「アップロード」項目は、スマホが、9VAeアニメGIF POSTと接続しており、保存用フォルダにアクセスできるときだけ表示される。
  • アニメを作成し「アップロード」をタッチすればアニメが保存され、自動的に gif ファイルに変換される。(上の app.py プログラムの MyThread が新しいファイルを検出し、EVAからGIFに変換を行う)
  • スマホ版のアップロード機能は、Ver.0.6.12(200110) 以降の PEASmotch!one に搭載された。なお、パソコン版の場合は、9va_dataフォルダの中の setpath.ini に共有フォルダのフルパスを記載しておき、直接保存する機能が従来から搭載されている。

問題点と改良版

上のシステムを実際にキッズプラザ大阪に設置したところ、以下のような問題があった。

問題点 修正
Windows7の共有フォルダにfopenではアクセスできたが、statがアクセスできなかった ファイルの存在チェックを、statを使わずにfopenを使う関数に変更
ラズパイで共有フォルダ上でEVA-GIF変換を行うと、ほかの端末から共有フォルダへの接続ができなくなった。Windowsの記憶域不足エラーが発生 共有フォルダからラズパイに1日分のフォルダを転送し、ラズパイ上でEVA-GIF変換、Flaskサーバー応答を行うように変更
上のプログラムだと、EVA-GIF変換が2つ起動してしまう Flaskの応答とEVA-GIF変換を別プログラムにして起動する
EVA-GIF変換の変換途中のファイルをFlaskサーバーが表示しようとしてエラー表示が出る 変換途中の拡張子を、.gif##とし、変換終了後に.gifにリネームする
EVAファイルを転送するときに、0バイトのファイルができることがある。 0バイトのファイルは削除する
Macから共有フォルダをアクセスしたときに、隠しファイルがいくつも作成される。そのファイルを処理しようとしてエラー終了する Macが作成する隠しファイルは読み飛ばす処理が必要
POSTしても応答がない 2文字のPOSTに改行をつけないと、Linuxでは返事がこなかった。Windowsでは返事があった。

改良版プログラム

上の問題を修正したプログラム app-2.py, gif-2.py が以下

ダウンロードサーバープログラム

サーバーは内部フォルダをみる。内部フォルダで、GIF変換を行う。内部フォルダを最新にするのは、GIF変換プログラム。

app-2.py
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, make_response

import os         # ファイル操作
import shutil     # ファイル操作
import subprocess # プログラム実行
import time       # 時間処理
import re         # 文字置換,正規表現
import webbrowser # ブラウザ
import threading  # multi thread
import qrcode     # QRコード生成

EVA_FOLDER = '/home/share/xxxxxx' #アニメを保存する内部フォルダ(1日分)
HTTP_URL = '192.168.99.1'         #公開するURLアドレス(例)
HTTP_PORT = 8080                  #公開するポート

app = Flask(__name__)

inpFolder = EVA_FOLDER

class MyThread(threading.Thread):
    def __init__(self):
        super(MyThread, self).__init__()

    def run(self):
        loop(self,False)

@app.route('/')
def index():
  global inpFolder
  return render_template('index.html', images=sorted(os.listdir(inpFolder)[::-1], reverse=True), message = inpFolder)

@app.route('/images/<path:path>')
def send_js(path):
  global inpFolder
  return send_from_directory(inpFolder, path)

@app.route('/',methods=["POST"]) #アニメのアップロード
def save_eva():
  global inpFolder
  mno = -1
  #print("Posted file: {}".format(request.files['file']))
  file = request.files['file']
  if(file.filename.endswith('.eva')):
      files = [f for f in os.listdir(inpFolder)]   #入力
      for fn in files:
        eva = os.path.join(inpFolder,fn)
        if(not eva.endswith('.eva')):
            continue
        if( '_編集中' in eva):     #自動保存ファイルは無視
            continue
        if( '_とちゅう' in eva):
            continue
        if( '_autosave' in eva):
            continue
        no = int(os.path.splitext(os.path.basename(fn))[0])
        if(no > mno):               #最終番号を探す
            mno = no

      savepath = os.path.join(inpFolder, '%04d.eva' % (mno+1))
      file.save(savepath)
  return str(mno+1)   #保存した番号を返す


# 新しいフォルダができていないか確認するループ
def loop(self,askFolder):
  global inpFolder
  drmax = '0000-0000'
  while True:
    dirs = [f for f in os.listdir(EVA_FOLDER)] #一番新しい日付を取得
    drs = [s for s in dirs if re.match('[0-9]{4}-[0-9]{4}', s)]
    for dr in drs:
      if dr > drmax:
        drmax = dr
    inpFolder = EVA_FOLDER + '/' + drmax

    if(not os.path.exists(inpFolder)):    #フォルダがなかったら作成
        os.mkdir(inpFolder)

    if(askFolder):
        return inpFolder

    time.sleep(5.0) #sleep(秒指定)
  return inpFolder


t = MyThread()
inpFolder = loop(t,True)            #新フォルダへの移動
t.start()

html = 'http://' + HTTP_URL + ':' + str(HTTP_PORT)
img = qrcode.make(html)          #QR code作成
img.save('static/qrcode.png')
with open('static/setpath.ini', mode='w') as f:
    f.write(html)


if __name__ == '__main__':
    webbrowser.open(html)            #ブラウザ起動
    app.run(debug=True, host=HTTP_URL, port=HTTP_PORT)

EVA→GIF変換プログラム

gif-2.py
import os         # ファイル操作
import shutil     # ファイル操作
import subprocess # プログラム実行
import time       # 時間処理
import re         # 文字置換,正規表現

#ラズベリーパイ 例
ORG_FOLDER = '/home/pi/xxxxxx'    #アニメを保存するフォルダ(オリジナルをmount)
EVA_FOLDER = '/home/share/xxxxxx' #アニメを保存する内部フォルダ(1日分)
QVIEW_EXE = '/home/pi/9va/9view'  #9view.exe のフルパス
EVAorSVG = '.eva' #'.svg'

# Windows 例
#ORG_FOLDER = 'Q:/share/xxxxxx'    #ネットワークドライブで指定
#EVA_FOLDER = 'C:/share/xxxxxx'    #内部フォルダ

# Macintosh 例
#QVIEW_EXE = '/Volumes/9VAe1033a/9VAe.app/Contents/MacOS/9VAe'  #ダウンロードした 9VAeの場合


orgFolder = ORG_FOLDER
inpFolder = EVA_FOLDER

# GIF変換ループ
drmax = '0000-0000'
while True:
    dirs = [f for f in os.listdir(ORG_FOLDER)] #一番新しい日付を取得
    drs = [s for s in dirs if re.match('[0-9]{4}-[0-9]{4}', s)]
    for dr in drs:
      if dr > drmax:
        drmax = dr
    orgFolder = ORG_FOLDER + '/' + drmax
    inpFolder = EVA_FOLDER + '/' + drmax

    #ORGとINPを比較してデータ取得
    if(not os.path.exists(inpFolder)):    #フォルダがなかったら作成
        os.mkdir(inpFolder)

    files = [f for f in os.listdir(orgFolder)]   #入力
    for fn in files:
        eva = os.path.join(inpFolder,fn)
        if(not os.path.exists(eva)):    #ファイルがなかったら転送
          org = os.path.join(orgFolder,fn)
          shutil.copy(org, inpFolder)

    #不要フォルダ削除
    files = [f for f in os.listdir(EVA_FOLDER)]   
    for fn in files:
        if( '.DS_Store' in fn): # Mac用システムフォルダは無視
            continue
        if(fn != drmax):
            dr = os.path.join(EVA_FOLDER,fn)
            shutil.rmtree(dr)

    #サイズ0のEVAファイルは削除
    files = [f for f in os.listdir(inpFolder)]   #入力
    for fn in files:
        if(os.path.splitext(fn)[1] == EVAorSVG):
            dr = os.path.join(inpFolder,fn)
            if(os.path.getsize(dr)==0): #サイズが0のファイルは削除
                os.remove(dr)

    #GIF作成
    files = [f for f in os.listdir(inpFolder)]   #入力
    for fn in files:
        if(os.path.splitext(fn)[1] != EVAorSVG):
            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') #-gif オプションでGIFに変換
        #cmd = (QVIEW_EXE , eva , '-gif-trans') #-trans 背景透明にする場合
        print(cmd)                  #変換したことを表示
        subprocess.run(cmd)         #gif作成
        break;
    time.sleep(1.0) #sleep(秒指定)

起動方法(ラズベリーパイ)

起動時に、以下のシェルスクリプトで、EVAアニメを保存する共有フォルダをマウントし、その後、GIF変換、ダウンロードサーバーを起動しています。

#!/bin/sh 
sudo mount -t cifs //xx.xx.xx.xx/xx/xxxxxx /home/pi/xxxxxx -o user=xxxx,password=xxxx,sec=ntlmssp,nounix,noperm,rw 
sleep 10
cd /home/share/py
python3 /home/share/py/gif-2.py &
python3 /home/share/py/app-2.py

起動方法(Windows)

  • Windowsの場合、EVAアニメの共有フォルダをネットワークドライブに割り当てれば、Pythonからアクセスできます。(以下の例では gif.bat の中のnet use 命令で、Qドライブに割り当て)
  • GIF変換とサーバーの2つを別々のバッチファイルで起動します。

GIF変換の起動

gif.bat
timeout /t 30
net use Q: \\xx.xx.xx.xx\xxxx パスワード /user:ユーザー名
cd C:\Users\xx\xx\xx\py
python gif.py
pause

ダウンロードサーバーの起動

app.bat
timeout /t 50
cd C:\Users\xx\xx\xx\py
python app.py
pause

timeout は指定した時間(秒)待つ命令で、この2つをスタートアップフォルダに入れれば、先にGIF変換が起動し、そのあと、サーバーが起動します。

固定IPアドレスの割り当て

  • ダウンロードサーバー用 WiFiアクセスポイントは、WiFiルーターを使用しました。
  • Windows 機は、Wifi と、EVAアニメを保存する共有サーバーと2つのネットワークに接続します。それぞれ、固定IPアドレスを割り当てました。(コントロールパネル>ネットワークとインターネット>アダプターオプション>WiFiやLANアダプタアイコンの右ボタンメニュー>プロパティ>インターネットプロトコル(TCP/IPV4)>プロパティ>「IPアドレスを自動的に取得する」から「次のIPアドレスを使う」に変更)
  • 設定した固定IPアドレスを、Pythonプログラムの記載と一致させます。

Macintoshの場合

ダウンロードしたドライブイメージをダブルクリックし、9VAe1033a というフォルダの中に、9VAe アプリがある場合

QVIEW_EXE = '/Volumes/9VAe1033a/9VAe.app/Contents/MacOS/9VAe' 

のように書けばGIF変換できます。上のプログラムは、EVAファイルを変換しますが、EVAorSVG を'.svg'にすれば、SVGファイルを変換できます。(.evaのほうがサイズが小さいので、転送エラーがおこる場合は、EVAで運用したほうがよいでしょう)

設定例

  1. ここから 9VAeをダウンロード(右上のダウンロードボタン)
  2. ダブルクリックして展開。
  3. 9VAeを右ボタンクリックから「開く」(2回目に実行できる)
  4. ターミナルに9VAeをドラッグすると、9VAeのフルパスがわかります。
  5. デスクトップなどに、9VAeアニメを集めるフォルダを作成します。
  6. その中に、(1) 上の Python プログラム(gif-2.py)を作ります。
  7. (2) 年号-月日というフォルダ名を作ります。例「2023-0505」
  8. GIFを出力するフォルダをつくります。年号ー月日と同じ場所につくってもかまいません。
  9. gif-2.py プログラムの下の4行を修正します。
  10. ORG_FOLDER 年号-月日の親フォルダを指定します。
  11. EVA_FOLDER GIF出力するフォルダを指定します
  12. QVIEW_EXE  9VAeのパスを指定します(最後は9VAe.app/Contents/MacOS/9VAe)
  13. EVAorSVG  SVGファイルを変換する場合は'.svg'にします
  14. ターミナルで、gif-2.py をいれたフォルダに移動(cd フォルダ)
  15. python3 gif-2.py
  16. 年号-月日フォルダが、ORG_FOLDER の中にある場合、その一番最後の月日が、EVA_FOLDERの中に作成され、データ入力待ちになります。最後の月日フォルダの中に、アニメが保存されると、自動的に変換フォルダにコピーされ、同じ名前のGIFファイルが作られます。
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4