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")
}

代码说明

  1. WAV文件处理:

    • read_wav_header函数解析WAV文件头,获取采样率、通道数和位深
    • 验证是否为16位PCM格式,这是LAME编码器支持的格式
  2. 编码器配置:

    • 根据WAV文件信息自动设置通道数和采样率
    • 设置质量为Good,比特率为192kbps
  3. 数据转换:

    • 将WAV文件中的u8数据转换为i16 PCM数据
    • 保持小端字节序,这是LAME编码器要求的格式
  4. 分帧编码:

    • 将PCM数据分为1152样本的帧进行编码
    • 这样可以获得最佳性能,同时避免内存占用过高
  5. 输出处理:

    • 将编码后的MP3数据写入文件
    • 使用BufWriter提高写入性能

使用说明

  1. 将上述代码保存为main.rs
  2. 准备一个16位PCM格式的WAV文件,命名为input.wav放在项目根目录
  3. 运行程序将生成output.mp3文件

注意事项

  1. 确保输入WAV文件是16位PCM格式
  2. 程序会跳过WAV文件头,直接处理PCM数据
  3. 输出MP3文件不包含ID3标签,如需添加需要额外处理
回到顶部