見出し画像

Gif秒数カウンターをWebアプリに変換!

前回は、Pythonで作った簡単なハローワールドやジャンケンなどをブラウザで動かす練習をしました。
今回は、前に作ったGIF秒数カウンターをWebアプリにして公開してみようと思います。

今日のハイライト
GIF秒数カウンターのWEBアプリ版です。


ファイルアップロード機能を作る

新しいフォルダ

WEBアプリ化のための新しいフォルダ構成を作ります。

gif_web_app/
├── app.py              # Flaskアプリケーション本体
├── templates/
│   └── index.html      # ユーザーが見るHTMLページ
└── uploads/            # アップロードされたGIFが保存されるフォルダ

Flaskアプリケーション(app.py)

まず、メインのPythonファイルを作成します。このコードは、ファイルのアップロードを受付け、指定したuploadフォルダに保存する機能を持っています。gif_web_app/app.pyという名前で以下のファイルを作成します。

app.py

import os
from flask import Flask, request, render_template, flash, redirect, url_for
from werkzeug.utils import secure_filename

# --- 設定 ---
# アップロードされたファイルを保存するフォルダ
UPLOAD_FOLDER = 'uploads'
# アップロードを許可するファイルの拡張子
ALLOWED_EXTENSIONS = {'gif'}

# --- Flaskアプリケーションの初期化 ---
app = Flask(__name__)
# UPLOAD_FOLDERをFlaskの設定に追加
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# flashメッセージ(ユーザーへの通知)機能に必要な秘密鍵
app.config['SECRET_KEY'] = 'a_very_secret_key_for_flash_messages' 
# アップロードされるファイルの最大サイズ(例: 16MB)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

# --- ヘルパー関数 ---
def allowed_file(filename):
    """アップロードされたファイルが許可された拡張子かチェックする"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# --- ルーティング ---
@app.route('/', methods=['GET', 'POST'])
def upload_file():
    # POSTリクエスト(ファイルがアップロードされた)の場合
    if request.method == 'POST':
        # リクエストにファイルが含まれているかチェック
        if 'file' not in request.files:
            flash('ファイルがリクエストに含まれていません')
            return redirect(request.url)
        
        file = request.files['file']
        
        # ユーザーがファイルを選択しなかった場合(ファイル名が空)
        if file.filename == '':
            flash('ファイルが選択されていません')
            return redirect(request.url)
        
        # ファイルが選択され、かつ許可された拡張子の場合
        if file and allowed_file(file.filename):
            # 安全なファイル名に変換(危険な文字を削除)
            filename = secure_filename(file.filename)
            # ファイルを UPLOAD_FOLDER に保存
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            
            # 成功メッセージを表示
            flash(f'ファイル "{filename}" のアップロードに成功しました!')
            
            # 次のフェーズでは、ここでGIFの解析処理を呼び出すことになります。
            
            return redirect(url_for('upload_file'))

    # GETリクエスト(単にページを訪れた)の場合
    return render_template('index.html')

if __name__ == '__main__':
    # 'uploads' フォルダがなければ作成する
    if not os.path.exists(UPLOAD_FOLDER):
        os.makedirs(UPLOAD_FOLDER)
    app.run(debug=True) # debug=True は開発中のみ使用します

HTML(index.html)

次に、ブラウザで見る画面を templates フォルダ内に作成します。

index.html

<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>GIFアップローダー</title>
    <style>
        body { font-family: sans-serif; margin: 2em; background-color: #f4f4f9; }
        .container { max-width: 500px; margin: auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1 { color: #333; }
        .flash { padding: 1em; margin-bottom: 1em; border-radius: 4px; }
        .flash.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
        .flash.error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
        input[type=file] { margin-bottom: 1em; }
        input[type=submit] { background-color: #007bff; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; }
        input[type=submit]:hover { background-color: #0056b3; }
    </style>
</head>
<body>
    <div class="container">
        <h1>GIF情報カウンター (フェーズ1)</h1>
        <p>解析したいGIFファイルをアップロードしてください。</p>
        
        <!-- Flaskからのメッセージ(flash)を表示するエリア -->
        {% with messages = get_flashed_messages(with_categories=true) %}
          {% if messages %}
            {% for category, message in messages %}
              <!-- 成功メッセージとエラーメッセージでスタイルを分ける(今は成功のみ) -->
              <div class="flash success">{{ message }}</div>
            {% endfor %}
          {% endif %}
        {% endwith %}

        <!-- ファイルアップロード用のフォーム -->
        <form method="post" enctype="multipart/form-data">
            <input type="file" name="file" accept=".gif">
            <input type="submit" value="アップロードして解析">
        </form>
    </div>
</body>
</html>

実行

仮想環境を設定

ターミナルで、仮想環境を設定します。
仮想環境を作ると、独自のPythonやツールのバージョンで実行でき、他のアプリの影響を受けないため、安定して変換できる環境になります。

.\.venv\Scripts\Activate.ps1

ターミナルの先頭に (.venv) がつけば仮想環境になっています。

ライブラリのインストール

ターミナルでgif_web_appフォルダに移動し、Flaskをインストールします。

pip install Flask

アプリケーションの実行

ターミナルでapp.pyを実行します。

python app.py

ブラウザでアクセス

Running on http://○○○○とでたら、そのIPアドレスをブラウザに入力します。この時、赤字でWarningが出ますが、それは「これはローカルだけで実行可能でサーバーではダメよ」という内容なので、むしろ、成功です。

ブラウザにIPを入れると、こんな感じの表示が出てきます。

「ファイルを選択」して、「アップロードして解析」をクリックして、uploadにファイルが入っていれば成功です。


GIF解析機能の実装と結果表示

GIFtimecount.pyを組み込む

GIFtimecount.pyの機能を、app.pyに組み込んで、解析結果をindex.htmlで見られるように修正します。
※ここからは、ファイルが大きくなりすぎるのでコードは割愛。公開版を見てください。

ターミナルの仮想環境で実行します。

python app.py

IPアドレスをブラウザで実行します。
「ファイルを選択」してGIFアニメーションを選択し、「アップロードを解析」を押すと、再生時間、フレーム数、FPSが出ました。

デザインを修正しました。


デプロイの準備

本番用サーバー gunicorn のインストール

Flaskに付属の開発用サーバーから、本番環境に対応したサーバーをターミナルの仮想環境にインストールします。

pip install gunicorn

requirements.txt の作成

requirements.txt は、このプロジェクトが必要とするPythonライブラリの一覧が書かれたファイルです。Renderは、このファイルを見て必要なライブラリを自動でインストールしてくれます。

pip freeze > requirements.txt

これを実行すると、以下のような requirements.txt ができます。

blinker==...
click==...
colorama==...
Flask==...
gunicorn==...
...

.gitignoreファイルの作成

Gitに不要なファイルが含まれないように、.gitignoreファイルを新規に作成します。

# Python
__pycache__/
*.pyc

# Virtual Environment
.venv/
venv/

GitHubに公開用の新しいリポジトリを作る

GitHubに公開用のリポジトリを作って、作ったプログラムを入れました。

Render.comで公開

Render.comのアカウントを作る

Render.comは、フリープランのあるホスティングサービスです。
ここで公開するために、ホームページから新規アカウントを作ります。

Get Started for Freeをクリック

今回はGitHubでアカウントを作ります。
ここから、ブラウザの機能で日本語化して説明します。

GitHubと接続して、そのままログインします。

Render.comで新しいWebサービスを作成する

上の「+新しい」(英語はNew+)からウェブサービスを選びます。

一番下のGitHubを選択します。

GitHubで追加するリポジトリを指定して一番したの Install をクリック。

内容を確認

Languageは「Python3」、Build Command は「pip install -r requirements.txt」、Start Command は「gunicorn app:app 」になっていることを確認します。
確認ができたら、ページの一番最後にある「Deploy Web Service」をクリックします。

修正は、Githubにプッシュした瞬間から自動的に更新されて便利です。

公開ファイル

公開できました!

なんか知らんが嬉しい!

簡単なプログラムですが、苦労した分、メッチャ嬉しいです。

誰かの参考になれば幸いです。


使用ツール

いいなと思ったら応援しよう!