Rust MP3编码库mp3lame-encoder的使用,高性能音频编码与LAME MP3格式转换
Rust MP3编码库mp3lame-encoder的使用,高性能音频编码与LAME MP3格式转换
示例代码
use mp3lame_encoder::{Builder, Id3Tag, DualPcm, FlushNoGap};
// 创建LAME编码器构建器
let mut mp3_encoder = Builder::new().expect("Create LAME builder");
// 设置双声道
mp3_encoder.set_num_channels(2).expect("set channels");
// 设置采样率44.1kHz
mp3_encoder.set_sample_rate(44_100).expect("set sample rate");
// 设置比特率192kbps
mp3_encoder.set_brate(mp3lame_encoder::Bitrate::Kbps192).expect("set brate");
// 设置最高编码质量
mp3_encoder.set_quality(mp3lame_encoder::Quality::Best).expect("set quality");
// 设置ID3标签
mp3_encoder.set_id3_tag(Id3Tag {
title: b"My title",
artist: &[],
album: b"My album",
year: b"Current year",
comment: b"Just my comment",
});
// 构建编码器
let mut mp3_encoder = mp3_encoder.build().expect("To initialize LAME encoder");
// 准备PCM音频数据(这里使用静音示例)
let input = DualPcm {
left: &[0u16, 0],
right: &[0u16, 0],
};
// 准备输出缓冲区
let mut mp3_out_buffer = Vec::new();
mp3_out_buffer.reserve(mp3lame_encoder::max_required_buffer_size(input.left.len()));
// 编码PCM数据
let encoded_size = mp3_encoder.encode(input, mp3_out_buffer.spare_capacity_mut()).expect("To encode");
unsafe {
mp3_out_buffer.set_len(mp3_out_buffer.len().wrapping_add(encoded_size));
}
// 刷新编码器缓冲区
let encoded_size = mp3_encoder.flush::<FlushNoGap>(mp3_out_buffer.spare_capacity_mut()).expect("to flush");
unsafe {
mp3_out_buffer.set_len(mp3_out_buffer.len().wrapping_add(encoded_size));
}
// 此时mp3_out_buffer包含完整的MP3数据
完整示例
use mp3lame_encoder::{Builder, Id3Tag, DualPcm, FlushNoGap};
use std::fs::File;
use std::io::Write;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 初始化MP3编码器
let mut mp3_encoder = Builder::new().expect("创建LAME构建器失败");
// 设置编码参数
mp3_encoder.set_num_channels(2).expect("设置声道数失败");
mp3_encoder.set_sample_rate(44_100).expect("设置采样率失败");
mp3_encoder.set_brate(mp3lame_encoder::Bitrate::Kbps192).expect("设置比特率失败");
mp3_encoder.set_quality(mp3lame_encoder::Quality::Best).expect("设置质量失败");
// 设置ID3标签
mp3_encoder.set_id3_tag(Id3Tag {
title: b"示例音频",
artist: b"艺术家",
album: b"示例专辑",
year: b"2023",
comment: b"使用mp3lame-encoder编码",
});
// 构建编码器实例
let mut mp3_encoder = mp3_encoder.build().expect("初始化LAME编码器失败");
// 2. 准备模拟PCM数据(2秒双声道静音)
let pcm_data_left: Vec<i16> = vec![0; 44100 * 2];
let pcm_data_right: Vec<i16> = vec![0; 44100 * 2];
// 3. 初始化MP3输出缓冲区
let mut mp3_buffer = Vec::new();
mp3_buffer.reserve(mp3lame_encoder::max_required_buffer_size(pcm_data_left.len()));
// 分块编码处理(使用LAME推荐的1152帧大小)
let chunk_size = 1152;
for i in (0..pcm_data_left.len()).step_by(chunk_size) {
let end = std::cmp::min(i + chunk_size, pcm_data_left.len());
let input = DualPcm {
left: &pcm_data_left[i..end],
right: &pcm_data_right[i..end],
};
let encoded_size = mp3_encoder.encode(input, mp3_buffer.spare_capacity_mut())
.expect("编码失败");
unsafe {
mp3_buffer.set_len(mp3_buffer.len() + encoded_size);
}
}
// 刷新编码器获取剩余数据
let encoded_size = mp3_encoder.flush::<FlushNoGap>(mp3_buffer.spare_capacity_mut())
.expect("刷新失败");
unsafe {
mp3_buffer.set_len(mp3_buffer.len() + encoded_size);
}
// 4. 写入MP3文件
let mut file = File::create("output.mp3")?;
file.write_all(&mp3_buffer)?;
println!("MP3编码完成,文件已保存为output.mp3");
Ok(())
}
关于mp3lame-encoder
mp3lame-encoder是一个基于LAME MP3编码器的高性能Rust封装库,通过Rust友好的API提供音频编码功能。
主要特点:
- 支持多种音频参数配置:比特率、采样率、声道数等
- 完整的ID3标签支持
- 优化的编码性能
- 符合Rust惯用法的API设计
安装方法
在Cargo.toml中添加依赖:
[dependencies]
mp3lame-encoder = "0.2.1"
或者使用cargo命令安装:
cargo add mp3lame-encoder
许可证说明
该库采用LGPL许可证,与底层LAME库保持一致。
1 回复
Rust MP3编码库mp3lame-encoder使用指南
简介
mp3lame-encoder是一个Rust绑定库,用于LAME MP3编码器。它提供了高性能的音频编码功能,可以将PCM音频数据转换为MP3格式。这个库特别适合需要实时音频处理或批量音频转换的应用场景。
主要特性
- 支持多种输入音频格式(16位PCM)
- 可配置的MP3编码参数(比特率、质量等)
- 线程安全的编码器实现
- 低延迟编码
- 支持可变比特率(VBR)和恒定比特率(CBR)
安装
在Cargo.toml中添加依赖:
[dependencies]
mp3lame-encoder = "0.1"
完整示例代码
下面是一个完整的MP3编码示例,包含从WAV文件读取PCM数据并编码为MP3的功能:
use mp3lame_encoder::*;
use std::fs::File;
use std::io::{BufWriter, Read};
use std::path::Path;
// WAV文件头结构
#[derive(Debug)]
struct WavHeader {
sample_rate: u32,
channels: u16,
bits_per_sample: u16,
}
fn read_wav_header(file: &mut File) -> Result<WavHeader, Box<dyn std::error::Error>> {
let mut header = [0u8; 44];
file.read_exact(&mut header)?;
// 解析WAV文件头
let channels = u16::from_le_bytes([header[22], header[23]]);
let sample_rate = u32::from_le_bytes([header[24], header[25], header[26], header[27]]);
let bits_per_sample = u16::from_le_bytes([header[34], header[35]]);
Ok(WavHeader {
sample_rate,
channels,
bits_per_sample,
})
}
fn wav_to_mp3(input_path: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
// 打开WAV文件
let mut wav_file = File::open(Path::new(input_path))?;
// 读取WAV头信息
let header = read_wav_header(&mut wav_file)?;
// 验证是否为16位PCM
if header.bits_per_sample != 16 {
return Err("只支持16位PCM WAV文件".into());
}
// 创建编码器配置
let config = Config {
channels: if header.channels == 1 {
Channels::Mono
} else {
Channels::Stereo
},
sample_rate: header.sample_rate,
quality: Quality::Good,
bitrate_kbps: 192,
};
// 初始化编码器
let mut encoder = Encoder::new(config)?;
// 读取PCM数据
let mut pcm_data = Vec::new();
wav_file.read_to_end(&mut pcm_data)?;
// 将u8转换为i16 (小端格式)
let pcm_samples: Vec<i16> = pcm_data
.chunks_exact(2)
.map(|chunk| i16::from_le_bytes([chunk[0], chunk[1]]))
.collect();
// 创建MP3输出缓冲区
let frame_size = 1152; // LAME的标准帧大小
let mut mp3_buffer = vec![0u8; pcm_samples.len()]; // 足够大的缓冲区
// 分帧编码
let mut total_bytes = 0;
for chunk in pcm_samples.chunks(frame_size * header.channels as usize) {
let bytes_written = encoder.encode(chunk, &mut mp3_buffer[total_bytes..])?;
total_bytes += bytes_written;
}
// 写入MP3文件
let file = File::create(output_path)?;
let mut writer = BufWriter::new(file);
writer.write_all(&mp3_buffer[..total_bytes])?;
println!("成功将 {} 转换为 {}", input_path, output_path);
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
wav_to_mp3("input.wav", "output.mp3")
}
代码说明
-
WAV文件处理:
read_wav_header
函数解析WAV文件头,获取采样率、通道数和位深- 验证是否为16位PCM格式,这是LAME编码器支持的格式
-
编码器配置:
- 根据WAV文件信息自动设置通道数和采样率
- 设置质量为Good,比特率为192kbps
-
数据转换:
- 将WAV文件中的u8数据转换为i16 PCM数据
- 保持小端字节序,这是LAME编码器要求的格式
-
分帧编码:
- 将PCM数据分为1152样本的帧进行编码
- 这样可以获得最佳性能,同时避免内存占用过高
-
输出处理:
- 将编码后的MP3数据写入文件
- 使用BufWriter提高写入性能
使用说明
- 将上述代码保存为
main.rs
- 准备一个16位PCM格式的WAV文件,命名为
input.wav
放在项目根目录 - 运行程序将生成
output.mp3
文件
注意事项
- 确保输入WAV文件是16位PCM格式
- 程序会跳过WAV文件头,直接处理PCM数据
- 输出MP3文件不包含ID3标签,如需添加需要额外处理