2. Python音频处理入门:Librosa库安装与核心API、音频文件的读取与写入、波形可视化

好,咱们正式开始动手了。

上一章聊了音频的基础概念,采样率、位深、声道这些。但光有理论不行,得有个趁手的工具。Python 生态里做音频处理,Librosa 几乎是绕不开的库。我个人习惯把它叫做「音频处理的瑞士军刀」——读取、分析、特征提取、可视化,一条龙搞定。

这一章,我们就从零开始,把 Librosa 装好,然后走一遍最核心的流程:读音频、写音频、看波形。

2.1 安装Librosa:别踩这些坑

安装本身不复杂,但有几个细节我建议你注意一下。

推荐环境:Python 3.8 及以上,建议用虚拟环境(venv 或 conda),别直接往系统 Python 里装,不然以后项目多了容易乱。

最直接的安装方式:

pip install librosa

嗯,就这一行。但实际跑起来,你可能会遇到两个常见问题。

问题一:依赖冲突。 Librosa 底层依赖 numpy、scipy、soundfile 这些。如果你之前装过旧版本的 numpy,可能会报错。我的建议是:

pip install --upgrade numpy scipy
pip install librosa

问题二:音频解码器。 Librosa 默认用 soundfile 读写 WAV 文件。但如果你要读 MP3、FLAC 这些格式,需要额外装 ffmpeg。我在项目中遇到过好几次,明明代码没问题,就是读不了 MP3,最后发现是 ffmpeg 没装。

解决方案:

# 安装 ffmpeg(Windows 用户去官网下载,macOS 用 brew)
brew install ffmpeg   # macOS
# 或者让 Librosa 使用 audioread 后端
pip install audioread
注意:Librosa 0.10.0 之后,读取 MP3 默认依赖 audioread + ffmpeg。如果你用的是旧版本,建议升级到最新版。

装完之后,验证一下:

import librosa
print(librosa.__version__)

能看到版本号,就说明装好了。

2.2 核心API:音频文件的读取与写入

Librosa 读取音频的核心函数就一个:librosa.load()。但别看它简单,参数里藏着不少门道。

2.2.1 读取音频:librosa.load()

基本用法:

import librosa

# 读取音频文件
audio_path = 'example.wav'
y, sr = librosa.load(audio_path)

print(f"音频数据形状: {y.shape}")
print(f"采样率: {sr} Hz")

这里返回两个东西:

  • y:一维 numpy 数组,代表音频的时域信号值,范围在 [-1.0, 1.0] 之间。
  • sr:采样率,默认是 22050 Hz。

等等,默认 22050?我明明录的是 44100 的 WAV 啊。没错,Librosa 默认会重采样到 22050 Hz。为什么?因为大部分音频分析任务不需要那么高的采样率,22050 已经能覆盖人耳范围(20Hz-11kHz),而且数据量减半,处理更快。

但如果你需要原始采样率,可以这样:

y, sr = librosa.load(audio_path, sr=None)  # 保持原始采样率

或者指定你想要的采样率:

y, sr = librosa.load(audio_path, sr=16000)  # 重采样到 16kHz
避坑指南:我曾经在处理一批电话语音数据时,没注意采样率,直接用了默认的 22050。结果后面提取的 MFCC 特征跟基线对不上,排查了半天才发现是采样率不一致导致的。所以,读取时明确指定 sr,养成好习惯。

其他常用参数:

参数 默认值 说明
sr 22050 目标采样率,None 表示保持原始采样率
mono True 是否混音为单声道。立体声会取左右声道平均
offset 0.0 从第几秒开始读取
duration None 读取多少秒,None 表示读到结尾
res_type 'kaiser_best' 重采样算法,'kaiser_best' 质量最高但慢,'kaiser_fast' 更快

举个例子,只读取音频的前 5 秒:

y, sr = librosa.load(audio_path, sr=16000, offset=0, duration=5)

2.2.2 写入音频:librosa.output 已废弃

这里有个历史遗留问题。老版本的 Librosa 有 librosa.output 模块,但新版本已经移除了。现在官方推荐用 soundfile 或 scipy.io.wavfile 来写文件。

我个人习惯用 soundfile,因为它支持更多格式:

import soundfile as sf

# 写入 WAV 文件
sf.write('output.wav', y, sr)

# 写入 FLAC 文件(无损压缩)
sf.write('output.flac', y, sr)

如果你非要用 Librosa 的风格,可以这样:

# 注意:这不是 librosa 的函数,是 soundfile 的
# 但 librosa 官方文档推荐这种方式
sf.write('output.wav', y, sr, subtype='PCM_16')
小技巧:写入时指定 subtype='PCM_16' 可以控制位深。常见的有 'PCM_16'(16位)、'PCM_24'(24位)、'FLOAT'(32位浮点)。

2.3 波形可视化:看一眼你的音频长什么样

读进来之后,第一件事是什么?我个人习惯先看一眼波形。波形图能直观告诉你:音频有没有削波、有没有静音段、动态范围怎么样。

Librosa 提供了 librosa.display.waveshow() 来画波形。注意,它依赖 matplotlib。

import librosa.display
import matplotlib.pyplot as plt

# 读取音频
y, sr = librosa.load('example.wav', sr=None)

# 创建画布
plt.figure(figsize=(12, 4))

# 绘制波形
librosa.display.waveshow(y, sr=sr)

# 添加标签
plt.title('Waveform')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')

plt.tight_layout()
plt.show()

运行之后,你会看到一条上下波动的曲线。横轴是时间(秒),纵轴是振幅(归一化到 [-1, 1])。

你想想看,如果波形上下都顶到了 -1 和 1,说明音量太大,可能削波了。如果波形几乎是一条直线,那可能是静音段。

2.3.1 多段波形对比

有时候需要对比两段音频,比如原始音频和处理后的音频。可以画在同一个图上:

plt.figure(figsize=(12, 6))

plt.subplot(2, 1, 1)
librosa.display.waveshow(y_original, sr=sr)
plt.title('Original')

plt.subplot(2, 1, 2)
librosa.display.waveshow(y_processed, sr=sr)
plt.title('Processed')

plt.tight_layout()
plt.show()

2.3.2 波形图的参数调整

waveshow 还有一些参数可以调:

参数 说明
alpha 透明度,0-1,多个波形叠加时有用
color 波形颜色,默认蓝色
max_points 最大采样点数,超过时会降采样显示,提高绘图速度
x_axis 横轴单位,'time' 或 'samples'

举个例子,画一个半透明的红色波形:

librosa.display.waveshow(y, sr=sr, alpha=0.7, color='red')

2.4 本章知识体系

下面这张图总结了本章的核心流程和知识点,你可以对照着梳理一下:

Librosa音频处理入门知识体系 Librosa 音频处理入门知识体系 1. 安装与环境 pip install librosa ffmpeg 安装 依赖冲突解决 2. 音频读取 librosa.load() sr 参数控制 offset/duration mono 混音 3. 音频写入 soundfile.write() subtype 位深控制 格式支持(WAV/FLAC) 4. 波形可视化 waveshow() 绘图 多段波形对比 参数调整(alpha/color) 核心流程

这张图把本章内容分成了四个模块:安装、读取、写入、可视化。箭头表示流程方向,你可以看到,从安装开始,到读取音频,再到写入或可视化,是一个完整的链路。

2.5 完整示例:一条龙走一遍

最后,我们写一个完整的脚本,把今天学的串起来:

import librosa
import librosa.display
import soundfile as sf
import matplotlib.pyplot as plt
import numpy as np

# 1. 读取音频
audio_path = 'speech.wav'
y, sr = librosa.load(audio_path, sr=16000, duration=10)
print(f"读取完成:{len(y)/sr:.2f}秒,采样率{sr}Hz")

# 2. 查看基本信息
print(f"数据范围:{y.min():.3f} ~ {y.max():.3f}")
print(f"数据形状:{y.shape}")

# 3. 可视化
plt.figure(figsize=(12, 4))
librosa.display.waveshow(y, sr=sr, alpha=0.8, color='#2c3e50')
plt.title('Speech Waveform (16kHz)')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.tight_layout()
plt.savefig('waveform.png', dpi=150)
plt.show()

# 4. 写入处理后的音频(这里只是复制,实际可以加处理逻辑)
sf.write('speech_copy.wav', y, sr, subtype='PCM_16')
print("写入完成:speech_copy.wav")

这个脚本跑完之后,你会得到一张波形图和一个新的 WAV 文件。嗯,这就是最基础的音频处理流程了。

总结一下:Librosa 的 load() 和 waveshow() 是你最常用的两个函数。前者把音频变成数据,后者让你看到数据。记住采样率要明确指定,写入用 soundfile,波形图用 waveshow。这三板斧练熟了,后面的特征提取、音频增强才能玩得转。