如何在FastAPI的单个请求中实现音频上传与流式返回?
解决方案:FastAPI 接收音频并流式返回结果
先明确核心结论
FastAPI 的 POST 端点完全支持返回 StreamingResponse,你遇到的「无法流式返回」大概率是客户端、中间件或代码逻辑的问题,而非框架限制。以下是几种可行方案:
方案一:修复 POST + StreamingResponse 流程
先排查并解决当前 POST 端点的流式问题:
检查客户端流式支持
部分客户端默认不处理 POST 请求的流式响应,比如浏览器原生表单提交。改用支持流式的客户端调用方式:# Python requests 示例 import requests with open("input.wav", "rb") as f: # 开启 stream=True 以接收流式响应 response = requests.post("http://localhost:8000/stream-audio", files={"audio_file": f}, stream=True) with open("output.wav", "wb") as out_f: for chunk in response.iter_content(chunk_size=1024): out_f.write(chunk)实现真正的实时流式处理
你的示例代码是先生成完整文件再读取返回,并非实时流式。如果要边处理边返回,直接从处理流程中 yield 数据:from fastapi import UploadFile from fastapi.responses import StreamingResponse def process_audio_stream(input_file: UploadFile): # 模拟边读输入边生成处理后的音频块 while chunk := input_file.file.read(1024): # 替换为你的实际音频处理逻辑 processed_chunk = chunk # 示例:直接返回原数据 yield processed_chunk @app.post("/stream-audio") def stream_audio(audio_file: UploadFile): return StreamingResponse(process_audio_stream(audio_file), media_type="audio/wav")禁用中间件缓存
若使用 Nginx 等反向代理,默认会缓冲响应导致流式失效,需配置禁用缓冲:# Nginx 配置示例 location /stream-audio { proxy_pass http://your-fastapi-server; proxy_buffering off; # 关键:禁用缓冲 proxy_set_header Connection ""; }
方案二:拆分上传与请求(两步式)
如果环境限制无法用 POST 流式返回,可拆分为两个独立端点:
POST 上传音频并触发处理
import uuid from fastapi import BackgroundTasks, UploadFile # 生产环境建议用数据库/分布式缓存替代内存存储 processed_tasks = {} def process_audio_task(file_content: bytes, task_id: str): # 音频处理逻辑,生成处理后的音频内容 processed_content = file_content # 替换为实际处理 processed_tasks[task_id] = processed_content @app.post("/upload-audio") async def upload_audio(audio_file: UploadFile, background_tasks: BackgroundTasks): task_id = str(uuid.uuid4()) file_content = await audio_file.read() background_tasks.add_task(process_audio_task, file_content, task_id) return {"task_id": task_id}GET 流式返回处理结果
def iter_processed_audio(task_id: str): yield processed_tasks.get(task_id, b"") @app.get("/get-audio/{task_id}") def get_audio(task_id: str): if task_id not in processed_tasks: return {"error": "任务未找到或处理中"} return StreamingResponse(iter_processed_audio(task_id), media_type="audio/wav")
方案三:使用 WebSocket 双向流式传输
如果需要更实时的交互(边上传边接收处理结果),用 WebSocket 实现双向流式:
from fastapi import WebSocket @app.websocket("/ws-audio") async def websocket_audio(websocket: WebSocket): await websocket.accept() while True: # 接收客户端分块发送的音频数据 chunk = await websocket.receive_bytes() # 处理当前音频块 processed_chunk = chunk # 替换为实际处理逻辑 # 实时返回处理后的音频块 await websocket.send_bytes(processed_chunk)
内容的提问来源于stack exchange,提问作者Abhisek
相关产品推荐
相关产品推荐

