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

Flask接收JS上传录音Librosa加载报未知音频格式错误排查

问题现象

浏览器录制6秒时长音频上传至Flask后端,计划后续将音频转换为频谱图、转为Numpy数组供模型推理时,抛出如下报错:

RuntimeError: Error opening <FileStorage: 'audio_file.wav' ('audio/wav')>: File contains data in an unknown format.

调整多版配置仍无法定位问题出在文件上传逻辑还是Librosa调用环节。

根因说明

问题共涉及4处前后端代码错误,没有单一诱因:

  • 前端伪造音频格式:MediaRecorder默认录制的音频为webm/opus编码,手动给Blob设置type: "audio/wav"仅修改了MIME标记和文件名后缀,没有做实际转码,文件本质不是WAV格式,Librosa无法识别伪装后缀的文件。
  • 后端文件读取key不匹配:前端formData.append传入的字段名是audio_file,后端写的是request.files["audio_file.wav"],字段名对应错误。
  • 后端文件指针位置错误:先调用f.save(audio)把上传文件存到本地后,FileStorage对象的指针已经移到文件末尾,直接把f传入lb.load()读不到任何有效内容。
  • 路由地址不匹配:前端AJAX请求的路径是/LungUploader,后端定义的路由是/LUploader,路径少了ng字符,正常情况下会直接返回404。
  • 缺失依赖导入:代码中直接调用specshow()但没有从librosa.display导入该方法,就算音频读取成功也会抛出名称错误。
修复方案

前端修复

不要硬编码音频MIME类型,优先调用浏览器支持的录制格式,若必须输出标准WAV格式需要引入专门的PCM转码库(如recorder.js),不能靠改MIME伪装格式,最小改动可用代码如下:

function lDUp(){
    var formData = new FormData();
    const startButton = document.getElementById("startLungBtn");
    startButton.addEventListener("click", function() {
      if (!navigator.mediaDevices) {
        console.error("getUserMedia not supported.")
        return;
      }
  
    const constraints = { audio: true };
    navigator.mediaDevices.getUserMedia(constraints)
    .then(function(stream) {
        var chunks = [];
        // 优先选用浏览器支持的录制格式,不硬写wav
        let supportMime = '';
        if (MediaRecorder.isTypeSupported('audio/wav;codecs=1')) supportMime = 'audio/wav;codecs=1';
        else if (MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) supportMime = 'audio/webm;codecs=opus';
        const recorder = new MediaRecorder(stream, {mimeType: supportMime});
        recorder.ondataavailable = event => {
            chunks.push(event.data);
        };

        recorder.onstop = event => {
            console.log("Recording stopped.")
            // 用录制器实际输出的MIME生成Blob
            let blob = new Blob(chunks, { type: recorder.mimeType }); 
            chunks = [];
            startButton.disabled = false;
  
            formData.append("audio_file", blob, "audio_file");
            $.ajax({
                type: "POST",
                // 路径和后端路由对齐
                url: "http://127.0.0.1:5000/LUploader",
                processData: false,
                contentType: false,
                cache: false,
                data: formData,
                success: function(response) {
                    console.log(response);
                    console.log("This is class: ", response)
                },
                error: function(err) {
                    console.log(err);
                }
            });   
          };
        recorder.onstart = event => {
            console.log("Recording started.");
            startButton.disabled = true;
            setTimeout(function() { recorder.stop(); }, 6000);
        };
        recorder.start();
    })
    .catch(function(err) {
          console.error(err);
      });
    });
}

后端修复

修正字段名、路由、导入问题,直接从内存读取音频字节流,避免文件指针偏移问题,代码如下:

import librosa as lb
import soundfile as sf
import io
from flask import request
import matplotlib.pyplot as plt
# 补全缺失的导入
from librosa.display import specshow

# 路由和前端请求路径对齐
@app.route('/LUploader', methods=["GET", 'POST'])
def lUploader():
    if request.method == "POST":
        # 字段名和前端append的参数对齐
        f = request.files["audio_file"]
        # 直接读内存字节流,避免指针偏移问题
        audio_bytes = f.read()
        # 保留原生采样率不做重采样,减少失真
        y, sr = lb.load(io.BytesIO(audio_bytes), sr=None)

        print("Checkpoint")
        plt.figure(figsize=(10,3))
        src_ft = lb.stft(y)
        src_db = lb.amplitude_to_db(abs(src_ft))
        specshow(src_db, sr=sr, x_axis='time', y_axis='hz')  
        plt.ylim(0, 5000)
        # 补全保存逻辑,否则生成的图会丢失
        plt.savefig('lung_spec.png')
        plt.close()

        # 后续可直接用y(音频numpy数组)做模型推理
        return {"code": 0, "msg": "process success"}

若读取webm格式音频时报解码错误,先安装ffmpeg并加入环境变量,Librosa会自动调用ffmpeg完成非WAV格式的解码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:24:23