Solution
f = request.files['audio_file']
f.save(f.filename)
from flask import (
Flask,
request,
# ...
)
from werkzeug.utils import secure_filename
import os
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(
app.instance_path,
'uploads'
)
try:
os.makedirs(app.config['UPLOAD_FOLDER'])
except:
pass
# ...
@app.post('/upload')
def upload():
# Get the FileStorage object with the name of the form's input field.
file = request.files.get('audio_file')
if file and file.filename != '':
dest = os.path.join(
app.config['UPLOAD_FOLDER'],
secure_filename(file.filename)
)
# Save the file on the server.
f.save(dest)
# Load the file by filename using librosa.
y,sr = librosa.load(dest)
# ...
'''
pip install flask librosa numpy scikit-image
'''
from flask import (
Flask,
Response,
abort,
current_app,
render_template,
redirect,
request,
send_from_directory,
stream_with_context,
url_for
)
from collections import namedtuple
from glob import glob
from mimetypes import add_type, guess_extension, guess_type
from werkzeug.utils import secure_filename
import librosa
import numpy
import os
import skimage.io
add_type('audio/aac', '.m4a', strict=True)
Record = namedtuple('Record', ('filename', 'specimage', 'created_at'))
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
try:
os.makedirs(os.path.join(
app.instance_path,
app.config.get('UPLOAD_FOLDER', 'uploads')
))
except:
pass
@app.route('/')
def audio_index():
patterns = [
'*.m4a',
'*.wav',
'*.weba'
]
path = os.path.join(
current_app.instance_path,
current_app.config.get('UPLOAD_FOLDER', 'uploads')
)
records = [
Record(fn[len(path)+1:], f'{fn[len(path)+1:]}.png', os.path.getctime(fn)) \
for ptrn in patterns for fn in glob(os.path.join(path, ptrn))
]
return render_template('index.html', records=records)
@app.route('/audio-upload', methods=['POST'])
def audio_upload():
if 'audio_file' in request.files:
file = request.files['audio_file']
extname = guess_extension(file.mimetype)
if not extname:
abort(400)
# WARNING: Check for allowed file extensions.
i = 1
while True:
dst = os.path.join(
current_app.instance_path,
current_app.config.get('UPLOAD_FOLDER', 'uploads'),
secure_filename(f'audio_record_{i}{extname}'))
if not os.path.exists(dst): break
i += 1
file.save(dst)
img = os.path.join(
current_app.instance_path,
current_app.config.get('UPLOAD_FOLDER', 'uploads'),
secure_filename(f'{os.path.basename(dst)}.png')
)
hop_length = 512
n_mels = 128
time_steps = 384
y, sr = librosa.load(dst)
spectrogram_image(y, sr=sr, out=img, hop_length=hop_length, n_mels=n_mels)
return redirect(url_for('audio_index'))
def spectrogram_image(y, sr, out, hop_length, n_mels):
mels = librosa.feature.melspectrogram(
y=y, sr=sr, n_mels=n_mels,
n_fft=hop_length*2, hop_length=hop_length
)
mels = numpy.log(mels + 1e-9)
img = scale_minmax(mels, 0, 255).astype(numpy.uint8)
img = numpy.flip(img, axis=0)
img = 255-img
skimage.io.imsave(out, img)
def scale_minmax(X, min=0.0, max=1.0):
X_std = (X - X.min()) / (X.max() - X.min())
X_scaled = X_std * (max - min) + min
return X_scaled
@app.route('/audio/stream/', methods=['GET'])
def audio_download(fn):
@stream_with_context
def generator(src):
CHUNK_SIZE = 1024
with open(src, 'rb') as fp:
while True:
data = fp.read(CHUNK_SIZE)
if not data: break
yield data
src = os.path.join(
current_app.instance_path,
current_app.config.get('UPLOAD_FOLDER', 'uploads'),
fn
)
if not os.path.exists(src):
return abort(404)
mime,_ = guess_type(src)
return Response(generator(src), mimetype=mime)
@app.route('/audio/spec/')
def audio_spec(fn):
path = os.path.join(
current_app.instance_path,
current_app.config.get('UPLOAD_FOLDER', 'uploads')
)
return send_from_directory(path, fn)
Audio Index
{% for record in records|sort(attribute='created_at', reverse=True) -%}
{{ record.filename }}
{% endfor -%}