FastAPI双API间BytesIO音频文件传输损坏问题排查
问题原因与解决方案
原因分析
核心问题是BytesIO的文件指针位置错误:
- API1中调用
sf.read(audio)读取音频内容时,会将BytesIO对象的内部指针移动到文件末尾。 - 后续执行
audio.read()时,指针已处于末尾位置,无法读取到任何音频数据,导致返回的Response内容为空。 - API1中pickle保存的33KB文件是完整的BytesIO对象(包含原始内容和指针状态),但返回给API2的是空数据,所以API2生成的BytesIO仅保留了对象本身的结构(42字节),没有实际音频内容。
解决办法
方法1:重置BytesIO指针
在需要读取BytesIO内容前,调用seek(0)将指针重置到开头:
# API1 修改后的代码 (...) audio = tts.generate_audio(translation,final,wavdata) samples, samplerate = sf.read(audio) audio.seek(0) # 重置指针到开头,保证后续操作能读取完整内容 sd.play(samples, samplerate) sd.wait() with open("obj1.pickle", "wb") as f: pickle.dump(audio, f) audio.seek(0) # 再次重置指针,确保返回完整音频数据 return Response(content=audio.read(), media_type="audio/wav")
方法2:提前提取字节内容
如果需要多次使用音频数据,建议先将BytesIO的全部内容提取为bytes变量,避免指针问题:
# API1 修改后的代码 (...) audio = tts.generate_audio(translation,final,wavdata) audio_bytes = audio.getvalue() # 一次性获取全部音频字节 # 用新的BytesIO包装字节数据给sf.read使用 samples, samplerate = sf.read(io.BytesIO(audio_bytes)) sd.play(samples, samplerate) sd.wait() with open("obj1.pickle", "wb") as f: pickle.dump(io.BytesIO(audio_bytes), f) # 直接返回字节数据,无需处理指针 return Response(content=audio_bytes, media_type="audio/wav")
API2的代码无需修改,只要API1返回了完整的音频数据,r.content就会包含完整内容,生成的BytesIO也会和API1的一致。
内容的提问来源于stack exchange,提问作者DesperateStudent
相关产品推荐
相关产品推荐

