3. 音频格式转换
任务目标
实现WAV与MP3格式的双向转换:将输入的WAV文件编码为MP3,再将生成的MP3解码回WAV,验证转换链路完整可用。本案例聚焦格式转换核心逻辑,不涉及录音、播放等外围功能。
环境与依赖
使用Python 3.8+,依赖pydub库及其底层驱动ffmpeg。安装命令:
pip install pydub
同时需在系统中安装ffmpeg并加入PATH(Windows用户请下载ffmpeg可执行文件并配置环境变量)。
完整实现代码
from pydub import AudioSegment
import os
def wav_to_mp3(wav_path, mp3_path, bitrate="192k"):
"""将WAV文件转换为MP3文件"""
audio = AudioSegment.from_wav(wav_path)
audio.export(mp3_path, format="mp3", bitrate=bitrate)
print(f"WAV → MP3 完成: {mp3_path}")
def mp3_to_wav(mp3_path, wav_path):
"""将MP3文件转换回WAV文件"""
audio = AudioSegment.from_mp3(mp3_path)
audio.export(wav_path, format="wav")
print(f"MP3 → WAV 完成: {wav_path}")
def verify_conversion(original_wav, converted_wav):
"""验证原始WAV与往返转换后的WAV是否一致"""
orig = AudioSegment.from_wav(original_wav)
conv = AudioSegment.from_wav(converted_wav)
print(f"原始WAV: 时长={len(orig)}ms, 声道={orig.channels}, 帧率={orig.frame_rate}Hz")
print(f"往返WAV: 时长={len(conv)}ms, 声道={conv.channels}, 帧率={conv.frame_rate}Hz")
if abs(len(orig) - len(conv)) < 100: # 允许100ms容差
print("验证通过: 时长基本一致")
else:
print("验证失败: 时长差异过大")
if __name__ == "__main__":
# 使用当前目录下的示例文件,若不存在则生成一个测试音
test_wav = "test_input.wav"
if not os.path.exists(test_wav):
print("未找到测试WAV文件,生成1秒440Hz正弦波测试音...")
from pydub.generators import Sine
tone = Sine(440).to_audio_segment(duration=1000)
tone.export(test_wav, format="wav")
mp3_file = "output.mp3"
roundtrip_wav = "roundtrip_output.wav"
# 执行双向转换
wav_to_mp3(test_wav, mp3_file)
mp3_to_wav(mp3_file, roundtrip_wav)
# 验证往返一致性
verify_conversion(test_wav, roundtrip_wav)
运行方式
将上述代码保存为audio_converter.py,在命令行执行:
python audio_converter.py
验证方法与判定标准
程序运行后依次完成以下步骤,满足全部条件即判定通过:
- 控制台输出
WAV → MP3 完成和MP3 → WAV 完成,且当前目录下生成output.mp3和roundtrip_output.wav两个文件; output.mp3文件大小明显小于原始WAV(MP3为有损压缩格式);- 验证输出显示原始WAV与往返转换后的WAV时长差小于100ms,并打印
验证通过; - 若本机无音频播放环境,可通过文件大小和时长信息确认转换成功;若需进一步人工验证,可播放
roundtrip_output.wav,应听到与原始WAV一致的440Hz音调。
常见问题
- File not found错误:确认ffmpeg已正确安装并加入系统PATH,pydub依赖ffmpeg处理MP3编解码。
- 时长不一致:MP3编码会引入约50ms的编解码延迟,属正常现象,代码中已设置100ms容差。
- 采样率变化:若原始WAV采样率非标准值,转换后可能被ffmpeg重采样,可通过
audio.set_frame_rate()强制指定。