Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

Flask:Webアプリでサーバ上のオーディオファイルを再生・ダウンロード(Blueprint版、デモ付き)

概要

前回ご紹介した、ブラウザ上でサーバ上の音源を再生するFlask実装を、Blueprintを使って実用化した例です。

※前回の記事も合わせて読んでいただければ幸いです。

ディレクトリ構成

devディレクトリの中に、flask_play_audioのようなアプリをいくつも制作することを想定しています。

project_root
 ├ dev/
 │ ├ another_yourapp/
 │ │
 │ └ flask_play_audio/
 │  ├ music/
 │  │ └ audio.mp3
 │  ├ templates/
 │  │ └ dev
 │  │  └  flask_play_audio
 │  │   └ index.html
 │  └ views.py
 └ run.py

ソースコード

views.py

from flask import Blueprint
from flask import render_template, send_from_directory

app_name = 'flask_playback_audio'
app_path = f"dev/{app_name}"
flask_playback_audio = Blueprint(app_name, __name__, template_folder='templates')

@flask_playback_audio.route('/')
def index():
    return render_template(f'{app_path}/index.html') #ポイント1

@flask_playback_audio.route("music/<path:filepath>")
def flask_playback_audio_send_music(filepath):
    return send_from_directory(f"{app_path}/music", filepath) #ポイント2

Blueprintを使うにあたっての注意すべき点がポイント1、2です。

ポイント1:index.htmlの配置とディレクトリ構成

Blueprintでは、どうやら全てのtemplates/のファイルを参照するような実装になっているようです

例えば、上記ディレクトリ構成において、another_yourappflask_play_audiotemplatesディレクトリにそれぞれ同名のindex.htmlを置くと正しく動作しないようです。
そのため、templates以下にプロジェクトのディレクトリ構成を反映させてindex.htmlを配置するという 手法がよく採用されているようです。

今回の場合ですと、上記ディレクトリ構成のように、templates/apps/flask_play_audio/index.htmlという配置になります。
Python + Flask + Blueprint で複数のアプリケーションを登録する際に気をつけること - Qiita Flask Blueprint における template_folderパス解決の罠 - 真面目に、強く、上品に

ポイント2:サーバから送るファイルの配置

ローカルサーバ、本番サーバ両方で試したところ、以下の実装で動きました。 send_from_directoryに、project_rootから見たファイルパスを与えてやることで実現できました。

run.py(一部掲載)

公式のBlueprintの使い方通り、Blueprintインスタンスをappに登録します。 Modular Applications with Blueprints — Flask Documentation (1.0.x)

Pythonの仕様やパッケージ構成における混乱を避けるため、ディレクトリ名やURLはスネイクケースもしくはキャメルケースで命名するのがよいと思います。

from dev.flask_playback_audio.views import flask_playback_audio

app = Flask(__name__)

# Regiter apps
app.register_blueprint(flask_playback_audio, url_prefix="/dev/flask_playback_audio")

index.html

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Download audio</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <audio src="music/audio.mp3" controls></audio>
</body>
</html>

デモ

http://www.wizardcraft.works/dev/flask_playback_audio/www.wizardcraft.works