FastAPI保存WAV音频后wavfile读取报错:仅支持RIFF/RIFX格式
问题解决:wavfile读取FastAPI保存的音频报错
问题原因
你保存的文件虽然后缀是.wav,但实际不是标准RIFF结构的WAV格式——大概率是上传的音频本身是MP3、OGG这类其他编码格式,播放器能自动识别并解码播放,但wavfile只认RIFF/RIFX开头的标准WAV,所以触发报错。
解决办法
办法1:保存时转成标准WAV格式
用FFmpeg把上传的音频转码为标准WAV,这样wavfile就能正常读取了。先确保服务器安装了FFmpeg,再用以下方式实现:
用ffmpeg-python库的示例代码:
from fastapi import APIRouter, Form import uuid import ffmpeg import os router = APIRouter() @router.post('/save') async def save_audio(audio = Form()): filename = str(uuid.uuid4()) temp_path = f"{filename}_temp" out_file_path = f"{filename}.wav" # 先保存上传的临时文件 with open(temp_path, "wb") as buffer: buffer.write(await audio.read()) # 用FFmpeg转码为标准WAV try: ffmpeg.input(temp_path).output(out_file_path, format='wav').run(quiet=True) finally: # 清理临时文件 if os.path.exists(temp_path): os.remove(temp_path) return {"file_path": out_file_path}
用subprocess直接调用FFmpeg的示例:
from fastapi import APIRouter, Form import uuid import subprocess import os import shutil router = APIRouter() @router.post('/save') async def save_audio(audio = Form()): filename = str(uuid.uuid4()) temp_path = f"{filename}_temp" out_file_path = f"{filename}.wav" with open(temp_path, "wb") as buffer: shutil.copyfileobj(audio.file, buffer) # 调用FFmpeg转码为PCM编码的标准WAV subprocess.run([ 'ffmpeg', '-i', temp_path, '-acodec', 'pcm_s16le', '-ar', '44100', out_file_path ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) os.remove(temp_path) return {"file_path": out_file_path}
办法2:改用支持多格式的读取库
如果不需要转码,只是要读取音频数据,可以用librosa或soundfile这类支持更多编码格式的库,它们能自动识别文件类型:
用soundfile读取:
import soundfile as sf data, rate = sf.read(f"{filename}.wav")
用librosa读取:
import librosa data, rate = librosa.load(f"{filename}.wav", sr=None)
办法3:在接口里校验上传文件的格式
提前拦截非标准WAV的文件,从源头避免问题:
from fastapi import APIRouter, Form, HTTPException import magic # 需要安装python-magic库 router = APIRouter() @router.post('/save') async def save_audio(audio = Form()): # 检测文件实际MIME类型 file_content = await audio.read() file_type = magic.from_buffer(file_content, mime=True) if file_type != 'audio/wav': raise HTTPException(status_code=400, detail="请上传标准WAV格式音频") # 保存文件 filename = str(uuid.uuid4()) out_file_path = f"{filename}.wav" with open(out_file_path, "wb") as buffer: buffer.write(file_content) return {"file_path": out_file_path}
内容的提问来源于stack exchange,提问作者Hanie Asemi
相关产品推荐
相关产品推荐

