Rust MP4元数据处理库mp4ameta_proc的使用:高效解析和操作MP4音频文件元数据

Rust MP4元数据处理库mp4ameta_proc的使用:高效解析和操作MP4音频文件元数据

安装

在项目目录中运行以下Cargo命令:

cargo add mp4ameta_proc

或者在Cargo.toml中添加以下行:

mp4ameta_proc = "0.6.0"

使用示例

以下是使用mp4ameta_proc库解析和操作MP4音频文件元数据的完整示例:

use mp4ameta_proc::{Tag, Data};
use std::fs::File;
use std::io::BufReader;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 打开MP4文件
    let file = File::open("audio.mp4")?;
    let mut reader = BufReader::new(file);

    // 读取元数据标签
    let tag = Tag::read_from(&mut reader)?;

    // 打印所有元数据
    println!("MP4文件元数据:");
    for data in tag.data() {
        match data {
            Data::Album(album) => println!("专辑: {}", album),
            Data::Artist(artist) => println!("艺术家: {}", artist),
            Data::Title(title) => println!("标题: {}", title),
            Data::Genre(genre) => println!("流派: {}", genre),
            Data::TrackNumber(track) => println!("音轨号: {}", track),
            Data::DiscNumber(disc) => println!("光盘号: {}", disc),
            Data::Year(year) => println!("年份: {}", year),
            Data::Comment(comment) => println!("注释: {}", comment),
            Data::CoverArt { data, format } => {
                println!("封面艺术: {}格式, {}字节", format, data.len())
            }
            _ => {} // 其他元数据类型
        }
    }

    // 修改元数据
    let mut tag = tag;
    tag.set_title("新标题");
    tag.set_artist("新艺术家");
    tag.set_album("新专辑");

    // 将修改后的元数据写回文件
    let file = File::create("audio_modified.mp4")?;
    let mut writer = BufReader::new(file);
    tag.write_to(&mut writer)?;

    Ok(())
}

完整示例代码

以下是一个更完整的示例,展示了如何批量处理MP4文件的元数据:

use mp4ameta_proc::{Tag, Data};
use std::fs::{self, File};
use std::io::{BufReader, BufWriter};
use std::path::Path;

// 处理单个MP4文件的元数据
fn process_mp4_metadata(file_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 打开文件
    let file = File::open(file_path)?;
    let mut reader = BufReader::new(file);
    
    // 读取元数据
    let tag = Tag::read_from(&mut reader)?;
    
    // 打印文件基本信息
    println!("\n处理文件: {}", file_path);
    println!("包含的元数据类型:");
    
    // 统计各类元数据的数量
    let mut metadata_count = 0;
    for data in tag.data() {
        match data {
            Data::Album(_) => println!("- 专辑信息"),
            Data::Artist(_) => println!("- 艺术家信息"),
            Data::Title(_) => println!("- 标题信息"),
            Data::Genre(_) => println!("- 流派信息"),
            Data::TrackNumber(_) => println!("- 音轨号"),
            Data::DiscNumber(_) => println!("- 光盘号"),
            Data::Year(_) => println!("- 年份信息"),
            Data::Comment(_) => println!("- 注释信息"),
            Data::CoverArt { .. } => println!("- 封面图片"),
            _ => println!("- 其他元数据类型"),
        }
        metadata_count += 1;
    }
    
    println!("共找到 {} 个元数据项", metadata_count);
    
    // 创建修改后的文件
    let modified_path = Path::new(file_path)
        .with_file_name("modified_audio.mp4");
    
    // 修改并写入元数据
    let mut tag = tag;
    tag.set_title("修改后的标题");
    tag.set_artist("修改后的艺术家");
    
    let output_file = File::create(modified_path)?;
    let mut writer = BufWriter::new(output_file);
    tag.write_to(&mut writer)?;
    
    println!("已创建修改后的文件: {:?}", modified_path);
    
    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例:处理当前目录下的MP4文件
    let dir_entries = fs::read_dir(".")?;
    
    for entry in dir_entries {
        let entry = entry?;
        let path = entry.path();
        
        if path.extension().map_or(false, |ext| ext == "mp4") {
            if let Some(file_name) = path.to_str() {
                process_mp4_metadata(file_name)?;
            }
        }
    }
    
    Ok(())
}

功能说明

  1. 读取MP4元数据Tag::read_from方法可以从MP4文件中读取所有元数据
  2. 访问元数据:通过tag.data()可以遍历所有元数据项
  3. 修改元数据:提供set_*系列方法来修改各种元数据
  4. 写入元数据write_to方法将修改后的元数据写回文件

支持的元数据类型

  • 标题(title)
  • 艺术家(artist)
  • 专辑(album)
  • 流派(genre)
  • 音轨号(track number)
  • 光盘号(disc number)
  • 年份(year)
  • 注释(comment)
  • 封面艺术(cover art)

许可证

该库采用MIT或Apache-2.0双重许可证。


1 回复

Rust MP4元数据处理库mp4ameta_proc的使用指南

mp4ameta_proc 是一个用于高效解析和操作MP4音频文件元数据的Rust库。它专注于处理MP4容器格式(如.m4a文件)中的元数据信息,提供了一套简洁的API来读取和修改这些数据。

安装

Cargo.toml中添加依赖:

[dependencies]
mp4ameta_proc = "0.1"

基本使用方法

读取MP4文件元数据

use mp4ameta_proc::{Tag, Data};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 从文件加载元数据
    let tag = Tag::read_from_path("audio.m4a")?;
    
    // 获取常用元数据字段
    if let Some(title) = tag.title() {
        println!("标题: {}", title);
    }
    
    if let Some(artist) = tag.artist() {
        println!("艺术家: {}", artist);
    }
    
    if let Some(album) = tag.album() {
        println!("专辑: {}", album);
    }
    
    Ok(())
}

写入元数据

use mp4ameta_proc::{Tag, Data};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建新标签或加载现有标签
    let mut tag = Tag::read_from_path("audio.m4a").unwrap_or_default();
    
    // 设置元数据字段
    tag.set_title("新歌曲名称");
    tag.set_artist("艺术家名称");
    tag.set_album("专辑名称");
    tag.set_track_number(1);
    tag.set_total_tracks(10);
    
    // 保存回文件
    tag.write_to_path("audio.m4a")?;
    
    Ok(())
}

高级功能

处理封面艺术

use mp4ameta_proc::{Tag, Data, ImgFmt};
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut tag = Tag::read_from_path("audio.m4a")?;
    
    // 读取封面
    if let Some(artwork) = tag.artwork() {
        fs::write("cover.jpg", artwork.data)?;
        println!("封面格式: {:?}", artwork.format);
    }
    
    // 添加新封面
    let cover_data = fs::read("new_cover.jpg")?;
    tag.set_artwork(ImgFmt::Jpeg, cover_data);
    
    tag.write_to_path("audio.m4a")?;
    
    Ok(())
}

处理自定义元数据

use mp4ameta_proc::{Tag, Data, Freeform};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut tag = Tag::read_from_path("audio.m4a")?;
    
    // 添加自定义元数据
    tag.insert(Freeform::new("com.myapp.custom", "自定义值").into());
    
    // 读取自定义元数据
    if let Some(custom) = tag.get("com.myapp.custom") {
        println!("自定义字段值: {}", custom);
    }
    
    tag.write_to_path("audio.m4a")?;
    
    Ok(())
}

性能提示

mp4ameta_proc 在设计上考虑了性能:

  1. 它只解析和修改元数据部分,不会处理音频数据本身
  2. 提供了流式API,可以高效处理大文件
  3. 修改元数据时会尽量保留文件原有结构,减少重写量

错误处理

大多数操作返回Result类型,建议使用?操作符或适当处理错误:

match Tag::read_from_path("audio.m4a") {
    Ok(tag) => {
        // 处理标签
    },
    Err(e) => eprintln!("读取元数据失败: {}", e),
}

完整示例代码

下面是一个综合使用mp4ameta_proc库的完整示例:

use mp4ameta_proc::{Tag, Data, ImgFmt, Freeform};
use std::fs;
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 读取MP4文件元数据
    let file_path = "song.m4a";
    let mut tag = match Tag::read_from_path(file_path) {
        Ok(t) => t,
        Err(_) => {
            println!("文件不存在或无法读取,创建新标签");
            Tag::default()
        }
    };

    // 2. 打印现有元数据
    println!("=== 当前元数据 ===");
    println!("标题: {:?}", tag.title());
    println!("艺术家: {:?}", tag.artist());
    println!("专辑: {:?}", tag.album());
    println!("音轨号: {:?}", tag.track_number());
    println!("总音轨数: {:?}", tag.total_tracks());

    // 3. 更新元数据
    println!("\n=== 更新元数据 ===");
    tag.set_title("Rust编程之歌");
    tag.set_artist("Rust开发者");
    tag.set_album("Rust音频合集");
    tag.set_track_number(3);
    tag.set_total_tracks(12);
    
    // 4. 处理封面图片
    if Path::new("cover.jpg").exists() {
        println!("\n=== 处理封面 ===");
        let cover_data = fs::read("cover.jpg")?;
        tag.set_artwork(ImgFmt::Jpeg, cover_data);
        println!("已添加封面图片");
    }

    // 5. 添加自定义元数据
    println!("\n=== 添加自定义数据 ===");
    tag.insert(Freeform::new("com.example.rating", "5").into());
    if let Some(rating) = tag.get("com.example.rating") {
        println!("自定义评分: {}", rating);
    }

    // 6. 保存修改
    tag.write_to_path(file_path)?;
    println!("\n元数据已保存到文件");

    Ok(())
}

这个完整示例展示了:

  1. 读取现有MP4文件元数据或创建新标签
  2. 打印当前元数据信息
  3. 更新基本元数据字段
  4. 添加或更新封面图片
  5. 处理自定义元数据字段
  6. 将修改保存回文件

使用前请确保:

  • 已添加mp4ameta_proc依赖
  • 有可操作的.m4a文件
  • 如需处理封面,准备cover.jpg文件
回到顶部