実現したいこと
Pythonの音声分析ライブラリLibrosaを用いて分析した音響信号データをJSON形式でまとめて返すWebアプリケーションを作りたいです
発生している問題・分からないこと
データをjson形式に変換する過程でエラーが発生してしまいます
エラーメッセージ
error
1Traceback (most recent call last): 2 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/app.py", line 2190, in wsgi_app 3 response = self.full_dispatch_request() 4 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/app.py", line 1486, in full_dispatch_request 5 rv = self.handle_user_exception(e) 6 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/app.py", line 1484, in full_dispatch_request 7 rv = self.dispatch_request() 8 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/app.py", line 1469, in dispatch_request 9 return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) 10 File "/**/test.py", line 76, in top 11 return render_template("view_test.html", sign=sign) 12 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/templating.py", line 151, in render_template 13 return _render(app, template, context) 14 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/templating.py", line 132, in _render 15 rv = template.render(context) 16 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render 17 self.environment.handle_exception() 18 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception 19 raise rewrite_traceback_stack(source=source) 20 File "/**/flask_workspace/卒研/templates/view_test.html", line 1, in top-level template code 21 {% extends "base.html" %} 22 File "/**/flask_workspace/卒研/templates/base.html", line 10, in top-level template code 23 {% block content %} 内容 {% endblock %} 24 File "/**/flask_workspace/卒研/templates/view_test.html", line 9, in block 'content' 25 {{content|tojson|safe}} 26 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/jinja2/filters.py", line 1688, in do_tojson 27 return htmlsafe_json_dumps(value, dumps=dumps, **kwargs) 28 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/jinja2/utils.py", line 658, in htmlsafe_json_dumps 29 dumps(obj, **kwargs) 30 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/json/provider.py", line 180, in dumps 31 return json.dumps(obj, **kwargs) 32 File "/**/anaconda3/envs/flask_env/lib/python3.10/json/__init__.py", line 238, in dumps 33 **kw).encode(obj) 34 File "/**/anaconda3/envs/flask_env/lib/python3.10/json/encoder.py", line 199, in encode 35 chunks = self.iterencode(o, _one_shot=True) 36 File "/**/anaconda3/envs/flask_env/lib/python3.10/json/encoder.py", line 257, in iterencode 37 return _iterencode(o, 0) 38 File "/**/anaconda3/envs/flask_env/lib/python3.10/site-packages/flask/json/provider.py", line 120, in _default 39 raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable") 40TypeError: Object of type Undefined is not JSON serializable
該当のソースコード
test.py
1from flask import Flask 2from flask_wtf import FlaskForm 3from wtforms.fields import FileField, SubmitField 4from flask_wtf.file import FileRequired, FileAllowed 5from flask import Flask, render_template, request 6#from flask_migrate import Migrate 7from audio import convert_to_wav, load_audio 8from werkzeug.utils import secure_filename 9import librosa 10import numpy as np 11import json 12 13ALLOWED_EXTENSIONS = {"mp3", "wav", "flac", "ogg", "aac", "m4a"} 14 15class InputForm(FlaskForm): 16 file = FileField("音楽ファイル(wav,mp3など)", validators=[ 17 FileRequired(), 18 FileAllowed(ALLOWED_EXTENSIONS, "対応していないファイル形式です.対応形式: "+",".join(ALLOWED_EXTENSIONS)) 19 ]) 20 submit = SubmitField("生成") 21 22app=Flask(__name__) 23 24import os 25upload_folder = "./uploads" 26if not os.path.exists(upload_folder): 27 os.makedirs(upload_folder) 28app.config["UPLOAD_FOLDER"] = "./uploads" 29app.config["SECRET_KEY"]=os.urandom(24) 30 31@app.route("/",methods=["GET","POST"]) 32def top(): 33 form=InputForm() 34 35 if request.method == "POST": 36 #音楽ファイル入力 37 file = form.file.data 38 filename = secure_filename(file.filename) 39 input_file_path = os.path.join(app.config["UPLOAD_FOLDER"], filename) 40 file.save(input_file_path) 41 42 # output_wav_path = os.path.join(app.config["UPLOAD_FOLDER"], "converted.wav") 43 # wav_file = convert_to_wav(input_file_path, output_wav_path) 44 45 # audio_data, sample_rate = load_audio(wav_file) 46 audio_data, sample_rate = load_audio(input_file_path) 47 48 if os.path.exists(input_file_path): 49 os.remove(input_file_path) 50 # if os.path.exists(output_wav_path): 51 # os.remove(output_wav_path) 52 53 #BPMの計算 54 tempo, beat_frames = librosa.beat.beat_track(y=audio_data, sr=sample_rate) 55 beat_times = librosa.frames_to_time(beat_frames, sr=sample_rate) 56 57 #周波数スペクトルの計算 58 stft = librosa.stft(audio_data) 59 spectrogram = np.abs(stft) 60 61 #メロディやピッチ(クロマ特長量)を取得 62 chroma = librosa.feature.chroma_stft(y=audio_data, sr=sample_rate) 63 64 #音圧 65 rms = librosa.feature.rms(y=audio_data) 66 67 68 acoustic_sign = { 69 "tempo":tempo, 70 "beat_frames":beat_frames.tolist(), 71 "spectrogram":spectrogram.tolist(), 72 "rms":rms.tolist() 73 } 74 75 sign = json.dumps(acoustic_sign, indent=2) 76 return render_template("view_test.html", sign=sign) 77 78 return render_template("input_test.html",form=form) 79 80 81if __name__=="__main__": 82 app.run() 83 84 85
audio.py
1import subprocess 2import librosa 3 4def convert_to_wav(input_file_path, output_file="output.wav"): 5 """ 6 任意の音声ファイルをWAV形式に変換する関数 7 Args: 8 input_file_path (str): 入力音声ファイルのパス 9 output_file (str): 出力WAVファイルのパス (デフォルト: "output.wav") 10 Returns: 11 str: 変換後のWAVファイルのパス 12 """ 13 try: 14 # FFmpegコマンドを実行 15 subprocess.run( 16 ["ffmpeg", "-i", input_file_path, "-ar", "44100", "-ac", "2", output_file], 17 check=True 18 ) 19 print(f"WAV形式に変換されました: {output_file}") 20 return output_file 21 except subprocess.CalledProcessError as e: 22 print("エラー: FFmpegによる変換に失敗しました。") 23 raise e 24 25def load_audio(file_path): 26 """ 27 librosaで音声ファイルを読み込む関数 28 Args: 29 file_path (str): 音声ファイルのパス 30 Returns: 31 tuple: (音声データ, サンプルレート) 32 """ 33 y, sr = librosa.load(file_path) # オリジナルのサンプルレートを維持 34 print(f"音声データが読み込まれました: {file_path}") 35 return y, sr 36
base.html
1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="utf-8" /> 5 <title>WTForm</title> 6</head> 7<body> 8 {% block title %} タイトル {% endblock %} 9 <hr /> 10 {% block content %} 内容 {% endblock %} 11</body> 12</html>
input_test.html
1{% extends "base.html" %} 2 3{% block title %} 4 <h1>テスト</h1> 5{% endblock %} 6 7{% block content %} 8 {% from "_formhelpers.html" import render_field %} 9 <form method="POST", enctype ="multipart/form-data"> 10 {{ render_field(form.file) }} 11 {{ form.submit() }} 12 </form> 13{% endblock %}
view_test.html
1{% extends "base.html" %} 2 3{% block title %} 4 <h1>分析結果</h1> 5{% endblock %} 6 7{% block content %} 8 <pre><code> 9 {{content|tojson|safe}} 10 </code></pre> 11 12{% endblock %}
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
json.dumpsに渡す値の型numpyだと良くないのかと思いtolist()でリスト型に変えてみたりしましたが同じエラーが出てしまいました
補足
実行したパソコン: Macbook Air
OS: macOS Sequoia 15.2
> json.dumpsに渡す値の型numpyだと良くないのかと思いtolist()でリスト型に変えてみたりしましたが同じエラーが出てしまいました
エラー発生個所は「sign = json.dumps(acoustic_sign, indent=2)」なのですか?
TypeError: Object of type Undefined is not JSON serializable
このエラーはjson.dumpsが対応していない型をjson形式に変換しようとした際に起こるエラーのようなのでおそらくエラー発生箇所は合っていると思うのですが,エラーログを見てみると
return render_template("view_test.html", sign=sign)
の部分でエラーが出ているとなっているのでもしかしたら違うかもしれません...
質問を詳細まで読めてなかった。
エラーコードは {{content|tojson|safe}} の方かな?
tempo が ndarray なのも別問題として残りますが。
回答1件
あなたの回答
tips
プレビュー