fastapiで音声を測定するAPIを作ってみた
音のテンポを測定するAPIを作ってみた
昔、Flutterの案件でしたが、音声の音のテンポBPMというらしい?
を測定する案件に携わったことがありました。しかし、Flutter, Dartには音声を測定するパッケージはありませんでした😵
音声の再生時間は、14〜20秒ぐらいが良いと思われます。短いサンプロを用意して、試してみてください。
無料の音声サンプルサイト
当時は、ChatGPTに質問すると、C++, Pythonで作れると教えてくれました?
本当か😅
Pythonは、経験があったので試しに作ってみた。当時は、librosaというライブラリを使っていました。作った後は、Cloud Runにデプロイして、Flutterから、file_picker, http packageを使って、HTTP POSTして、MP3ファイルの音のテンポを測定していました。123BPMとか測定した数値が返ってきていました。
当時は、Flaskの経験があったので、使ってましたが、最近は、fastapiが流行ってるので、同じの作れないかなと試しにやってみたら、作れました!
できてるか怪しいが....
Flutterのコードは、仕事で作ったものなので、公開できませんが、fastapiのコードは、趣味で作ったものなので、公開できます。仕事のは、Flaskなので笑
ファイルは、3つあればOKです
- app.py
- requirements.txt
- Dockerfile
Google Cloudに、デプロイしてみたい人は試してみてください。結構躓きます笑
fastapi
のファイルを作成。これだけあればOK。今回は、ローカル環境でしか動かしません。
import os
import tempfile
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import librosa
from pydantic import BaseModel
app = FastAPI()
# CORSミドルウェアの設定
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class BPMResponse(BaseModel):
bpm: float
@app.get("/")
async def home():
return "FastAPI BPM API"
async def estimate_tempo(audio_file: UploadFile):
with tempfile.NamedTemporaryFile(suffix=".mp3", delete=True) as temp_file:
content = await audio_file.read()
temp_file.write(content)
temp_file.flush()
y, sr = librosa.load(temp_file.name, sr=None)
onset_env = librosa.onset.onset_strength(y=y, sr=sr)
tempo, _ = librosa.beat.beat_track(onset_envelope=onset_env, sr=sr)
if tempo == 0:
tempo = librosa.feature.tempo(onset_envelope=onset_env, sr=sr)[0]
return tempo
@app.post("/estimate_bpm", response_model=BPMResponse)
async def upload_file(audio: UploadFile = File(...)):
try:
bpm = await estimate_tempo(audio)
return {"bpm": bpm}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
port = int(os.environ.get('PORT', 8080))
uvicorn.run(app, host="0.0.0.0", port=port)
パッケージをインストールするファイルを作成。私、Pythonエンジニアを4ヶ月やってた頃に、この書き方覚えました。コマンド打ったら、インストールしたパッケージをファイルに追加してくれるコマンドもあったりします。
fastapi
uvicorn
python-multipart
librosa
Dockerfile
を作成。これは正直いうと参考にしながら、作ったので、いいものではないかも?
Flaskの時も急いで作ったから、あれも良いものか?
FROM python:3.9-slim
# システムの依存関係をインストール
RUN apt-get update && apt-get install -y \
libsndfile1 \
libasound2-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
BPM測定APIの使い方
Flaskと違って、Swaggerが使えるのが、良かった笑
fastapi
最高です。Flutter, Reactから、音声ファイルを送信するのですが、Swagger使えば、file uploadが使えるので、バックエンドだけでも動作検証はできるようになりました。
- Dockerイメージをビルド
docker build -t fastapi-bpm-api .
- Dockerコンテナを実行
docker run -p 8080:8080 fastapi-bpm-api
Hello URL
Swagger URL
こんな感じで動きます。お試しあれ。Dockerは、起動しておいてくださいね。
最後に
解析系のツールとかを作るなら、ライブラリが豊富なPythonを使うと良いそうで、Web APIを自作できるのではと、試しにやってました。意外とできた。他にも趣味で解析系のAPI作りたいですね。
Flaskで、デプロイした時は、こんな感じでやりました。コマンドは一緒ですが、プロジェクトIDとかが入力の時に必要でしたね。IAMの設定とかするので、クラウドを操作するときは、難易度上がるかも?
Cloud Runは無料だそうですが、私には、毎月10〜15円の請求が来てました笑
コンテナのイメージで、料金がかかるとか?
Discussion