如何将numpy数组波形转换为可上传S3的wav类文件对象
实现方案
直接使用Python标准库的io.BytesIO作为内存类文件载体,搭配音频编码库将numpy数组写入标准WAV格式字节即可,全程不会生成本地文件,完全满足boto3的上传要求。
io.BytesIO原生实现了read()方法,调用后直接返回字节类型数据,和本地打开的rb模式文件对象行为完全一致。
方法1:基于soundfile实现(无额外依赖)
librosa本身依赖soundfile作为音频IO后端,不需要额外安装第三方包即可使用:
import io import numpy as np import soundfile as sf import boto3 def numpy_to_wav_obj(y: np.ndarray, sr: int) -> io.BytesIO: buffer = io.BytesIO() # 写入WAV格式数据到内存流 sf.write(buffer, y, sr, format="WAV") # 关键:将流读取指针重置到起始位置,否则read()会返回空 buffer.seek(0) return buffer # 调用示例 if __name__ == "__main__": import librosa y, sr = librosa.load("something.wav", sr=44100) wav_object = numpy_to_wav_obj(y, sr) s3 = boto3.resource("s3") bucket = s3.Bucket("mybucket") bucket.upload_fileobj(wav_object, "something.wav")
方法2:基于scipy实现
如果你的环境已经安装了scipy,也可以用scipy.io.wavfile完成编码:
import io import numpy as np from scipy.io import wavfile import boto3 def numpy_to_wav_obj(y: np.ndarray, sr: int) -> io.BytesIO: buffer = io.BytesIO() # 若需要兼容性最好的16位PCM格式,取消下面这行注释即可 # y = (y * np.iinfo(np.int16).max).astype(np.int16) wavfile.write(buffer, sr, y) buffer.seek(0) return buffer
关键注意点
- 写入数据后必须调用
seek(0)重置流指针,这是内存流操作最容易遗漏的步骤,会导致上传的文件为空。 - 不要直接将numpy数组用
tobytes()转成字节传入,这样得到的是裸PCM数据,没有WAV文件头,无法被正常识别为音频文件。
内容的提问来源于stack exchange,提问作者piccolo
相关产品推荐
相关产品推荐

