You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask字母识别API无法加载Android录音:Librosa格式识别失败

解决Flask API中Librosa无法加载Android录制WAV文件的问题

问题分析

你的核心问题有两个:

  • Librosa无法直接处理Flask的FileStorage对象,需要先将其转换为可读取的文件流或临时文件
  • Android设备录制的WAV文件通常采用IMA ADPCM压缩编码,而Librosa依赖的Soundfile仅原生支持未压缩的PCM编码WAV,这会导致格式识别失败

解决方案

下面是修改后的完整代码,结合临时文件处理+强制转码为PCM WAV的方案,确保Librosa能正常加载:

import os
import tempfile
from pydub import AudioSegment
import librosa
import numpy as np
import statistics
from flask import Flask, request, jsonify

app = Flask(__name__)
# 假设你的model已经提前加载完成
# model = ...

@app.route('/pred_alphabet', methods=['POST'])
def prediction():
    audio_file = request.files.get('audio_file')
    if not audio_file:
        return jsonify({'code':400, 'message': '未上传音频文件'})
    
    # 步骤1:将FileStorage保存为临时WAV文件
    with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_wav:
        audio_file.save(temp_wav.name)
        temp_path = temp_wav.name
    
    try:
        # 步骤2:用pydub将音频转码为未压缩的PCM WAV
        audio = AudioSegment.from_file(temp_path, format='wav')
        # 导出为PCM编码的WAV(16位,单声道,16kHz采样率,适配Librosa常用配置)
        converted_temp_path = temp_path.replace('.wav', '_converted.wav')
        audio.set_frame_rate(16000).set_channels(1).set_sample_width(2).export(converted_temp_path, format='wav', codec='pcm_s16le')
        
        # 步骤3:用Librosa加载转码后的音频
        y, sr = librosa.load(converted_temp_path, sr=16000)
        
        # 后续特征提取与预测逻辑保持不变
        X = np.mean(librosa.feature.mfcc(y=y, sr=sr, n_mfcc=40).T, axis=0)
        X = np.array(X)
        X = np.expand_dims(X, -1)
        
        predictions = model.predict(X)
        labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
        predicted_labels = [labels[np.argmax(pred)] for pred in predictions]
        mode = statistics.mode(predicted_labels)
        
        return jsonify({'code':200, 'result': str(mode)})
    
    finally:
        # 清理临时文件,避免磁盘占用
        if os.path.exists(temp_path):
            os.remove(temp_path)
        if os.path.exists(converted_temp_path):
            os.remove(converted_temp_path)

if __name__ == '__main__':
    app.run(debug=True)

关键细节说明

  • 临时文件处理:Flask的FileStorage对象不能直接传给Librosa,通过临时文件可以确保音频数据被正确写入磁盘后再处理
  • 强制转码:pcm_s16le是Librosa/Soundfile原生支持的未压缩编码,同时设置16kHz采样率、单声道,能统一输入格式,避免因Android录制参数差异导致的问题
  • 资源清理:使用finally块确保临时文件无论成功失败都会被删除,避免服务器磁盘占用

额外排查点

如果仍有问题,可以检查:

  • 确认Android端录制的音频确实是WAV格式(部分设备可能实际是MP3但后缀标为WAV)
  • 安装pydub依赖时确保已安装ffmpeg:pip install pydub,并在系统环境变量中配置ffmpeg路径

内容的提问来源于stack exchange,提问作者Muhammad Rizki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:35:15