Python如何将内存中WebM音频文件转换为MP3音频文件
核心问题原因
你无法获取输出文件的原因有两点:
- PyAv的输出容器上下文管理器(
with av.open(...) as out)退出时才会把容器剩余缓冲区的内容完全刷写到传入的文件对象,在上下文块内部读取只能拿到不完整的片段 - 文件写入完成后,文件指针默认停在写入的末尾位置,直接调用
read()会返回空值,必须手动将指针重置到文件起始位置才能读到完整内容
修复方案
修正后的实现全程在内存中完成转码,不会产生磁盘IO,最终直接返回可直接使用的MP3类文件对象:
from tempfile import SpooledTemporaryFile import av # 输入WebM文件指针重置到起始位置,避免读空 webm_file.seek(0) with av.open(webm_file, "r") as inp_container: # 初始化内存中存储MP3的临时文件,默认不会落盘 mp3_file = SpooledTemporaryFile(mode="w+b") # 输出容器指定MP3格式 with av.open(mp3_file, "w", format="mp3") as out_container: # 添加MP3编码流,可按需调整比特率、采样率参数 mp3_stream = out_container.add_stream("mp3", bit_rate=192000) # 初始化音频重采样器,兼容不同源音频格式,避免编码报错 resampler = av.AudioResampler( format="s16p", layout="stereo", rate=44100 ) # 逐帧解码转码 for audio_frame in inp_container.decode(audio=0): resampled_frame = resampler.resample(audio_frame) resampled_frame.pts = None for packet in mp3_stream.encode(resampled_frame): out_container.mux(packet) # 刷出编码器缓存的剩余帧 for packet in mp3_stream.encode(None): out_container.mux(packet) # 退出输出容器上下文后,所有转码内容已完整写入mp3_file,重置指针到起始位置 mp3_file.seek(0) # 此处mp3_file即为内存中的MP3类文件对象,可直接调用read()获取二进制内容、或传给其他需要文件对象的业务接口 # 示例:获取MP3二进制数据 mp3_data = mp3_file.read()
注意事项
- 如果需要完全禁止任何落盘可能,可以将
SpooledTemporaryFile替换为io.BytesIO,用法完全一致 - 转码完成后不要提前关闭
mp3_file对象,该对象会在被回收时自动释放内存,无资源泄漏风险
内容的提问来源于stack exchange,提问作者Denys Ivanenko
相关产品推荐
相关产品推荐

