動画をサムネ表示して再生させるWebアプリ

#概要
動画を一覧表示してサムネをクリックすることで再生できるようしたwebアプリ

#依存環境
Flask 1.0+ 
Bootstarp 4
python 3.4+
pymongo,joblib
MongoDB 3.6+(on Docker)
ffmpeg
(Imagemagic-6)
Linux Mint 19.1にて動作確認

#使い方
GitHubにてプログラムを公開している。(https://github.com/mimaburao/moviebrowser.git)
- 動画の再生
- データベースの新規作成
- 並び順の変更
- データベースの更新

#動作
Flaskは@app.routeにより受け取ったurlに応じて関数を返すような仕組みになっている。そしてreturn render_templateにて指定したhtmlを呼び出す。
私の場合は大まかに図1のような構成とした。
![path5397-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168780/828d4c2c-4788-042f-f9cb-14ebad6df9ca.png)
-/movie

```python:moviebrowser.py

@app.route('/movie', methods=['GET','POST'])
def show_all(data_all=[]):
    global my_database
    my_database.index_howto = request.args.get('index_sort',default='views', type=str)
    my_database.search_id = ''
    my_database.search = ''

    if(request.method == 'GET'): #検索窓の取得（何故かGETメソッド）
        my_database.search = request.args.get('search', default='', type=str)
        skip = request.args.get('page', default='', type=str)  #データベースのスキップ
    data_all.clear()
    if( my_database.thumnail_images == {} ):
        data_all = my_database.read_db_thumnail(data_all,skip)
    else:
        data_all = my_database.read_db_thumnail(data_all,skip)

    return render_template('show.html', data_all=data_all)

```

Mongoのデータベースにて登録されたデータをdata_allのリストに読み取ってshow.htmlに流し込む感じである。

```html:show.html
{% extends "layout.html" %}
{% block title %}Movie Database{% endblock %}

{% block content %}
<nav class="navbar navbar-fixed-top sticky-top navbar-dark bg-dark">
    <a href="/movie" class="navbar-brand">MovieBrowser</a>
    <form class="form-inline my-2 my-lg-0">
      <input type="search"  name = "search" class="form-control mr-sm-2" placeholder="検索..." aria-label="検索...">
      <button type="submit" class="btn btn-outline-success my-2 my-sm-0">検索</button>
    </form>
    <button class="navbar-toggler" type="button"
        data-toggle="collapse"
        data-target="#navmenu1"
        aria-controls="navmenu1"
        aria-expanded="false"
        aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navmenu1">
      <div class="navbar-nav">
        <a class="nav-item nav-link" href="/select_database">データーベース変更</a>
        <a class="nav-item nav-link" href="#">#</a>
        <a class="nav-item nav-link" href="#">#</a>
        <a class="nav-item nav-link" href="/manager">管理</a>
        <a class="nav-item nav-link" href="/update">更新</a>
      </div>
    </div>
  </nav>

<div class="table-responsive">
    <table class="table table-dark table-striped">
      <thread>
        <tr>
          <th></th>
          <th><a type="button" class="btn btn-dark" href="/movie?index_sort=views" role="button">views</a></th>
          <th><a type="button" class="btn btn-dark" href="/movie?index_sort=star" role="button">☆</a></th>          
          <th><a type="button" class="btn btn-dark" href="/movie?index_sort=date" role="button">日付</a></th>
          <th><a type="button" class="btn btn-dark" href="/movie?index_sort=duration" role="button">時間</a></th>
          <th><a type="button" class="btn btn-dark" href="/movie?index_sort=access_time" role="button">アクセス日付</a></th>
          <th><a type="button" class="btn btn-dark" href="/movie?index_sort=filename" role="button">ファイル名</a></th>
          <th><a type="button" class="btn btn-dark" href="/movie?index_sort=size" role="button">ファイルサイズ(MByte)</a></th>          
        </tr>
      </thread>
      <tbody>
        {% for samp in data_all %}
        <tr>
            <td><a href="/play?id_number={{ samp["_id"] }}""> <img src={{ samp["thumnail_file"] }} alt="test"> </a></td>
            <td>{{ samp["views"] }}回</td>
          <td>
            <a href="/star?stars=0&id_number={{ samp["_id"] }}" class="badge badge-dark" data-toggle="tooltip" data-placement="top" title="星を無くしますか">★{{ samp["star"] }}</a>
            <a href="/star?stars=1&id_number={{ samp["_id"] }}" class="badge badge-dark">★</a>
            <a href="/star?stars=2&id_number={{ samp["_id"] }}" class="badge badge-dark">★★</a>
            <a href="/star?stars=3&id_number={{ samp["_id"] }}" class="badge badge-dark">★★★</a></td>
          
          <td>{{ samp["date"] }}</td>
          <td>{{ samp["duration"] }}</td>
          <td>{{ samp["access_time"] }}</td>
          <td>{{ samp["name"] }}</td>
          <td>{{ samp["size"] }}</td>
        </tr>
        {% else %}
          <td>no entry exist!</td>
        {% endfor %}
      </tbody>
    </table>
    <a type="button" class="btn btn-dark btn-block" href="/movie?page=pre" role="button">前</a>
  <a type="button" class="btn btn-dark btn-block" href="/movie?page=next" role="button">次</a>
  </div>
</div>

{% endblock %}
```

{{}}となっている部分はrender_templateにて指定した変数を入れることができる。ここでは、動画の各情報（ファイル名とかサムネイル画像等）をテーブルとして表示できるようにしている。この変数を受け取れる仕組みはjinja2というものらしい。また制御構文をhtml内にて利用できるようにもしている。
htmlの各部品はBootstrapにて提供されていて、主にボタン、テーブル、バッジといったものを利用している。

#感想
初めてのwebアプリの作成であった。実用的なもの作りたいと溜まっていた動画を中身が３コマくらいで見ることできるアプリが欲しかった。
githubに登録してMicrosoft Visual CODEを利用してみたが便利であった。そして、作った自作のクラスや関数もポップアップ形式で引数などを教えてくれて至れりつくせりである。
Flaskも当然初めてなのだが、webアプリとしてメジャーなDjangoは使ったことがなかった。せっかくなのでシンプルなフレームワークにした。
データベースを用いたプログラムにも挑戦したくてNoSQL系のmongoが面白そうと飛びついた。なれると面白かった。
中でもgithubでreadme.mdには力を入れた。プログラムに機能を追加しては追記していくスタイルとなった。プログラムとはこんなプロセスで出来上がった行くものだろう。
利用面では当初考えていた機能はできたので今回公開してみた。
それにしても動画再生アプリのmpvはショートカット動作の上、シンプルでとっても便利である。

#参照
Bootstrap公式(https://getbootstrap.com/)
Mongo公式(https://www.mongodb.com/jp)
Flask公式(http://flask.pocoo.org/)