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

FastAPI上传音频文件遇Internal Server Error及文件未找到问题求助

问题分析与解决方案

你遇到的Internal Server Error核心原因是:FastAPI的UploadFile对象的filename只是上传文件的原始名称,并不是服务器本地的文件路径——上传的文件此时仅存在于内存中,librosa.load()找不到对应的本地文件,自然会抛出"文件未找到"的错误。

你确实需要处理上传文件的读取逻辑,不一定非要保存到永久文件夹,用临时文件或者直接在内存中处理都可以,下面给你两种可行方案:


方案1:使用临时文件处理(简单直观)

利用Python的tempfile模块创建临时文件,把上传的文件内容写入后,再用librosa加载这个临时文件:

import tempfile
from fastapi import FastAPI, File, UploadFile
import librosa
import numpy as np
from tensorflow.keras.models import load_model
import os

app = FastAPI()

# 提前加载模型,避免每次请求都加载,节省资源
model = load_model("trained_heartbeat_classifier.h5")

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    # 创建临时文件,保留原文件的后缀格式
    with tempfile.NamedTemporaryFile(delete=False, suffix=f".{file.filename.split('.')[-1]}") as temp_file:
        # 把上传文件的内容写入临时文件
        temp_file.write(await file.read())
        temp_file_path = temp_file.name
    
    try:
        # 从临时文件加载音频数据
        y, sr = librosa.load(temp_file_path)
        # 提取音频特征
        S = librosa.feature.melspectrogram(
            y, sr=sr, n_fft=2048, hop_length=512, n_mels=128)
        mfccs = librosa.feature.mfcc(S=librosa.power_to_db(S), n_mfcc=40)
        
        # 适配模型输入格式并完成预测
        x_test = np.asarray([mfccs])
        x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1)
        pred = model.predict(x_test, verbose=1)
        # 替代已弃用的predict_classes方法
        pred_class = np.argmax(pred, axis=1)
        
        # 整理返回结果
        result = {
            "filename": file.filename,
            "prediction": "Normal heartbeat" if pred_class[0] else "Abnormal heartbeat",
            "confidence": float(pred[0][1] if pred_class[0] else pred[0][0])
        }
        return result
    finally:
        # 用完临时文件后删除,避免磁盘占用
        os.unlink(temp_file_path)

if __name__ == "__main__":
    # 启动FastAPI服务,而非直接处理命令行参数
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

方案2:内存中直接处理(更高效,无需磁盘IO)

librosa.load()支持读取类文件对象,所以可以直接把上传的文件内容读取到BytesIO中,不用写入磁盘,减少IO开销:

from fastapi import FastAPI, File, UploadFile
import librosa
import numpy as np
from tensorflow.keras.models import load_model
import io

app = FastAPI()
model = load_model("trained_heartbeat_classifier.h5")

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    # 读取上传文件内容到内存中的BytesIO对象
    file_content = await file.read()
    audio_file = io.BytesIO(file_content)
    
    # 直接从内存对象加载音频
    y, sr = librosa.load(audio_file)
    # 特征提取逻辑和方案1一致
    S = librosa.feature.melspectrogram(
        y, sr=sr, n_fft=2048, hop_length=512, n_mels=128)
    mfccs = librosa.feature.mfcc(S=librosa.power_to_db(S), n_mfcc=40)
    
    # 模型预测与结果返回
    x_test = np.asarray([mfccs])
    x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1)
    pred = model.predict(x_test, verbose=1)
    pred_class = np.argmax(pred, axis=1)
    
    result = {
        "filename": file.filename,
        "prediction": "Normal heartbeat" if pred_class[0] else "Abnormal heartbeat",
        "confidence": float(pred[0][1] if pred_class[0] else pred[0][0])
    }
    return result

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

额外注意点

  1. 你原代码的main函数逻辑有误:create_upload_file是异步的API端点函数,不能像普通同步函数那样直接调用;同时Keras的predict_classes方法已被弃用,改用np.argmax(pred, axis=1)替代更稳妥。
  2. 模型要提前加载(放在API端点外部),避免每次请求都重新加载模型,大幅降低服务响应时间。

内容的提问来源于stack exchange,提问作者Faizan.shaikh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 00:27:39