質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

140閲覧

Librosaで分析した音声ファイルの音響信号をJSON形式で表示したい

Kurimeshi

総合スコア14

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2024/12/18 15:24

実現したいこと

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2024/12/18 17:53

> json.dumpsに渡す値の型numpyだと良くないのかと思いtolist()でリスト型に変えてみたりしましたが同じエラーが出てしまいました エラー発生個所は「sign = json.dumps(acoustic_sign, indent=2)」なのですか?
Kurimeshi

2024/12/19 04:37

TypeError: Object of type Undefined is not JSON serializable このエラーはjson.dumpsが対応していない型をjson形式に変換しようとした際に起こるエラーのようなのでおそらくエラー発生箇所は合っていると思うのですが,エラーログを見てみると return render_template("view_test.html", sign=sign) の部分でエラーが出ているとなっているのでもしかしたら違うかもしれません...
teamikl

2024/12/19 07:15

質問を詳細まで読めてなかった。 エラーコードは {{content|tojson|safe}} の方かな? tempo が ndarray なのも別問題として残りますが。
guest

回答1

0

ベストアンサー

見た感じですけど、tempoが ndarry のままになってます。
他のデータと合わせて

diff

1- "tempo":tempo, 2+ "tempo":tempo.tolist(),

※ librosa 0.10.2post1 で上記の変更で json化を確認

但し、ndarray の場合は Undefined とはならないかもしれないので、
tempoに期待する値が入ってない場合は別のエラーになるかもしれません。
その場合は問題を再現する wavデータの詳細が必要になります。
⇒ 他のデータ(別経路で入手もしくは作成)でも同様のエラーが起こるかどうかをテスト

デバッグの方法としては、flask とは一旦問題切り分けて、
ローカル環境で librosa 部分のみのテストを行いましょう。

python

1print(repr(tempo))

で確認してみてください。
print(tempo)だとリストとの区別がつかない場合があります。


あと、オフトピだけど、WTForm の使い方。設定したvalidator が使われてません。

diff

1- if request.method == "POST": 2+ if form.validate_on_submit():

追記:

環境がなくて試せないけど、render_template に sign で渡してるので

diff

1- {{content|tojson|safe}} 2+ {{sign|tojson|safe}}

問題個所の検出方法は、
テンプレートエンジンの jinja2 の StrictUndefined で flask での設定方法を調べてみてください。
未定義の変数としてエラーが得られると思います。

投稿2024/12/19 07:04

編集2024/12/19 07:41
teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kurimeshi

2024/12/20 07:24

値の特徴的にてっきりtempoは一次元のものだと思ってたので全く気にしてませんでした 無事解決しました ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問