Rust音频元数据处理库lofty的使用:高效读写MP3、FLAC等格式的ID3v2和APE标签
Rust音频元数据处理库lofty的使用:高效读写MP3、FLAC等格式的ID3v2和APE标签
Lofty是一个用于解析、转换和写入各种音频格式元数据的Rust库。
支持的格式
Lofty支持多种音频格式的元数据处理,包括MP3、FLAC等格式的ID3v2和APE标签。
示例
以下是使用lofty库处理音频元数据的完整示例:
读取音频文件元数据
use lofty::{AudioFile, TaggedFileExt};
use std::path::Path;
fn read_audio_tags(file_path: &str) -> Result<(), lofty::error::LoftyError> {
// 打开音频文件
let path = Path::new(file_path);
let tagged_file = lofty::read_from_path(path)?;
// 获取主要标签(通常是最相关的标签)
if let Some(tag) = tagged_file.primary_tag() {
println!("主要标签类型: {:?}", tag.tag_type());
// 读取常见元数据字段
println!("标题: {:?}", tag.title());
println!("艺术家: {:?}", tag.artist());
println!("专辑: {:?}", tag.album());
println!("年份: {:?}", tag.year());
println!("音轨号: {:?}", tag.track());
println!("流派: {:?}", tag.genre());
}
// 处理所有标签
for tag in tagged_file.tags() {
println!("标签类型: {:?}", tag.tag_type());
// 可以在这里处理特定标签类型的特殊逻辑
}
Ok(())
}
写入音频文件元数据
use lofty::{Tag, TagType, ItemKey};
use std::path::Path;
fn write_audio_tags(file_path: &str) -> Result<(), lofty::error::LoftyError> {
let path = Path::new(file_path);
// 创建一个新的ID3v2标签
let mut tag = Tag::new(TagType::Id3v2);
// 设置常见元数据字段
tag.insert_text(ItemKey::TrackTitle, "歌曲标题");
tag.insert_text(ItemKey::TrackArtist, "艺术家名称");
tag.insert_text(ItemKey::AlbumTitle, "专辑名称");
tag.insert_text(ItemKey::TrackNumber, "1");
tag.insert_text(ItemKey::Year, "2023");
tag.insert_text(ItemKey::Genre, "流行");
// 写入文件
lofty::write_to_path(path, &tag)?;
Ok(())
}
删除音频文件中的所有标签
use std::path::Path;
fn strip_all_tags(file_path: &str) -> Result<(), lofty::error::LoftyError> {
let path = Path::new(file_path);
// 从文件中读取所有标签
let mut tagged_file = lofty::read_from_path(path)?;
// 删除所有标签
tagged_file.clear();
// 保存修改
tagged_file.save_to_path(path)?;
Ok(())
}
完整示例
以下是一个完整的示例程序,演示了如何读取、修改和删除音频文件的元数据:
use lofty::{AudioFile, TaggedFileExt, Tag, TagType, ItemKey};
use std::path::Path;
fn main() -> Result<(), lofty::error::LoftyError> {
let file_path = "test.mp3";
// 示例1: 读取元数据
println!("=== 读取音频元数据 ===");
read_audio_metadata(file_path)?;
// 示例2: 写入元数据
println!("\n=== 写入音频元数据 ===");
write_audio_metadata(file_path)?;
read_audio_metadata(file_path)?;
// 示例3: 删除所有元数据
println!("\n=== 删除所有元数据 ===");
remove_all_metadata(file_path)?;
read_audio_metadata(file_path)?;
Ok(())
}
fn read_audio_metadata(file_path: &str) -> Result<(), lofty::error::LoftyError> {
let path = Path::new(file_path);
let tagged_file = lofty::read_from_path(path)?;
if let Some(tag) = tagged_file.primary_tag() {
println!("主要标签类型: {:?}", tag.tag_type());
println!("标题: {:?}", tag.title());
println!("艺术家: {:?}", tag.artist());
println!("专辑: {:?}", tag.album());
} else {
println!("文件没有元数据标签");
}
Ok(())
}
fn write_audio_metadata(file_path: &str) -> Result<(), lofty::error::LoftyError> {
let path = Path::new(file_path);
let mut tag = Tag::new(TagType::Id3v2);
tag.insert_text(ItemKey::TrackTitle, "我的歌曲");
tag.insert_text(ItemKey::TrackArtist, "音乐人");
tag.insert_text(ItemKey::AlbumTitle, "我的专辑");
lofty::write_to_path(path, &tag)?;
Ok(())
}
fn remove_all_metadata(file_path: &str) -> Result<(), lofty::error::LoftyError> {
let path = Path::new(file_path);
let mut tagged_file = lofty::read_from_path(path)?;
tagged_file.clear();
tagged_file.save_to_path(path)?;
Ok(())
}
使用说明
要使用lofty库,请将以下内容添加到您的Cargo.toml中:
[dependencies]
lofty = "0.22.4"
许可证
Lofty采用双重许可:
- Apache License, Version 2.0
- MIT license
您可以选择其中任一许可证。
1 回复
Rust音频元数据处理库lofty的使用指南
介绍
lofty是一个用于读取和写入音频文件元数据的Rust库,支持多种音频格式和标签类型。它可以高效处理MP3、FLAC、WAV、AAC等常见音频格式的ID3v2、APE和Vorbis注释等元数据标签。
主要特性:
- 支持多种音频格式:MP3、FLAC、WAV、AIFF、MP4、AAC等
- 支持多种标签类型:ID3v2、APE、Vorbis注释等
- 提供统一的API处理不同格式的元数据
- 高性能的元数据读写操作
- 纯Rust实现,无外部依赖
安装
在Cargo.toml中添加依赖:
[dependencies]
lofty = "0.15"
基本使用方法
读取音频文件元数据
use lofty::{read_from_path, TaggedFileExt};
fn main() {
// 读取音频文件
let tagged_file = read_from_path("song.mp3").expect("Failed to read file");
// 获取主标签(通常是ID3v2)
if let Some(tag) = tagged_file.primary_tag() {
println!("标题: {:?}", tag.title());
println!("艺术家: {:?}", tag.artist());
println!("专辑: {:?}", tag.album());
}
// 也可以访问特定类型的标签
if let Some(id3v2_tag) = tagged_file.id3v2() {
println!("ID3v2标签中的年份: {:?}", id3v2_tag.get("TYER").and_then(|f| f.text()));
}
}
写入元数据
use lofty::{read_from_path, TaggedFileExt, Tag};
use lofty::id3::v2::Id3v2Tag;
fn main() {
// 读取文件
let mut tagged_file = read_from_path("song.mp3").expect("Failed to read file");
// 创建或获取ID3v2标签
let id3v2_tag = match tagged_file.id3v2() {
Some(tag) => tag,
None => {
let new_tag = Id3v2Tag::new();
tagged_file.insert_tag(new_tag);
tagged_file.id3v2().unwrap()
}
};
// 设置元数据
id3v2_tag.set_title("新标题");
id3v2_tag.set_artist("新艺术家");
id3v2_tag.set_album("新专辑");
// 保存修改
tagged_file.save_to_path("song_updated.mp3").expect("Failed to save file");
}
处理FLAC文件的Vorbis注释
use lofty::{read_from_path, TaggedFileExt};
fn main() {
let tagged_file = read_from_path("song.flac").expect("Failed to read file");
if let Some(vorbis_comments) = tagged_file.vorbis_comments() {
println!("FLAC Vorbis注释:");
for (key, value) in vorbis_comments.iter() {
println!("{}: {}", key, value);
}
// 添加自定义字段
vorbis_comments.push("COMMENT", "这是一个Rust添加的注释");
}
}
高级用法
批量处理音频文件
use std::path::Path;
use lofty::{read_from_path, TaggedFileExt};
fn process_directory(dir_path: &str) {
let dir = Path::new(dir_path);
for entry in dir.read_dir().expect("读取目录失败").flatten() {
if let Some(ext) = entry.path().extension() {
if ext == "mp3" || ext == "flac" {
if let Ok(tagged_file) = read_from_path(entry.path()) {
println!("处理文件: {}", entry.path().display());
if let Some(tag) = tagged_file.primary_tag() {
println!(" 标题: {:?}", tag.title());
}
}
}
}
}
}
处理图片数据
use lofty::{read_from_path, TaggedFileExt};
fn extract_cover_art(file_path: &str) {
let tagged_file = read_from_path(file_path).expect("Failed to read file");
if let Some(id3v2_tag) = tagged_file.id3v2() {
for frame in id3v2_tag.get("APIC").into_iter().flatten() {
if let Some(picture) = frame.picture() {
println!("发现封面图片: {}x{}, {}字节",
picture.width(),
picture.height(),
picture.data().len());
// 可以将图片数据保存到文件
std::fs::write("cover.jpg", picture.data()).expect("写入图片失败");
}
}
}
}
完整示例
下面是一个完整的音频元数据管理工具示例:
use lofty::{read_from_path, TaggedFileExt, Tag};
use lofty::id3::v2::Id3v2Tag;
use std::io::{self, Write};
use std::path::Path;
fn main() -> io::Result<()> {
println!("音频元数据管理工具");
// 获取用户输入的文件路径
print!("请输入音频文件路径: ");
io::stdout().flush()?;
let mut file_path = String::new();
io::stdin().read_line(&mut file_path)?;
let file_path = file_path.trim();
// 读取音频文件
let mut tagged_file = match read_from_path(file_path) {
Ok(file) => file,
Err(e) => {
eprintln!("读取文件失败: {}", e);
return Ok(());
}
};
// 显示当前元数据
display_metadata(&tagged_file);
// 询问用户是否要修改元数据
print!("是否要修改元数据? (y/n): ");
io::stdout().flush()?;
let mut choice = String::new();
io::stdin().read_line(&mut choice)?;
if choice.trim().to_lowercase() == "y" {
// 获取用户输入的新元数据
let mut title = String::new();
let mut artist = String::new();
let mut album = String::new();
print!("输入新标题: ");
io::stdout().flush()?;
io::stdin().read_line(&mut title)?;
print!("输入新艺术家: ");
io::stdout().flush()?;
io::stdin().read_line(&mut artist)?;
print!("输入新专辑: ");
io::stdout().flush()?;
io::stdin().read_line(&mut album)?;
// 创建或获取ID3v2标签
let id3v2_tag = match tagged_file.id3v2() {
Some(tag) => tag,
None => {
let new_tag = Id3v2Tag::new();
tagged_file.insert_tag(new_tag);
tagged_file.id3v2().unwrap()
}
};
// 更新元数据
id3v2_tag.set_title(title.trim());
id3v2_tag.set_artist(artist.trim());
id3v2_tag.set_album(album.trim());
// 保存修改
if let Err(e) = tagged_file.save_to_path(file_path) {
eprintln!("保存修改失败: {}", e);
} else {
println!("元数据已成功更新!");
}
}
Ok(())
}
fn display_metadata(tagged_file: &impl TaggedFileExt) {
println!("\n当前元数据:");
// 显示主标签信息
if let Some(tag) = tagged_file.primary_tag() {
println!("标题: {:?}", tag.title().unwrap_or("无"));
println!("艺术家: {:?}", tag.artist().unwrap_or("无"));
println!("专辑: {:?}", tag.album().unwrap_or("无"));
}
// 显示特定格式的额外信息
if let Some(id3v2_tag) = tagged_file.id3v2() {
if let Some(year) = id3v2_tag.get("TYER").and_then(|f| f.text()) {
println!("年份: {}", year);
}
}
if let Some(vorbis_comments) = tagged_file.vorbis_comments() {
println!("\nVorbis注释:");
for (key, value) in vorbis_comments.iter() {
println!("{}: {}", key, value);
}
}
}
注意事项
- 修改文件时,建议先备份原始文件
- 不同音频格式支持的标签类型不同:
- MP3: ID3v1, ID3v2, APE
- FLAC: Vorbis注释
- MP4/AAC: iTunes风格标签
- 某些字段在不同标签类型中的名称可能不同
lofty提供了强大的音频元数据处理能力,适合构建音乐播放器、音乐库管理工具等需要处理音频元数据的应用。