Rust MP3音频处理库mp3-duration的使用:快速获取MP3文件时长的高效工具

Rust MP3音频处理库mp3-duration的使用:快速获取MP3文件时长的高效工具

这个crate只有一个目的:确定MP3文件的播放时长。

示例代码

以下是使用mp3-duration获取MP3文件时长的基本示例:

use std::path::Path;
use mp3_duration;

let path = Path::new("music.mp3");
let duration = mp3_duration::from_path(&path).unwrap();
println!("File duration: {:?}", duration);

完整示例

下面是一个更完整的示例,包含错误处理和更多功能:

use std::path::Path;
use std::time::Duration;
use mp3_duration;

fn main() {
    // 指定MP3文件路径
    let path = Path::new("music.mp3");
    
    // 获取MP3文件时长
    match mp3_duration::from_path(&path) {
        Ok(duration) => {
            // 将Duration转换为秒
            let seconds = duration.as_secs();
            println!("MP3文件时长: {}秒", seconds);
            
            // 或者格式化为更友好的时间显示
            let minutes = seconds / 60;
            let remaining_seconds = seconds % 60;
            println!("MP3文件时长: {}分{}秒", minutes, remaining_seconds);
        }
        Err(e) => {
            eprintln!("无法获取MP3文件时长: {}", e);
        }
    }
}

版本更新记录

版本 0.1.10

  • thiserror替换了failure进行错误管理(感谢@amesgen的贡献)

版本 0.1.9

  • 修复了一个bug,该bug导致自0.1.8版本以来MP3Duration错误类型不再公开(感谢@compenguy的贡献)

版本 0.1.8

  • 小幅性能改进

版本 0.1.7

  • 修复了在读取具有不可能短的MPEG帧的损坏文件时崩溃的问题

安装

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

cargo add mp3-duration

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

mp3-duration = "0.1.10"

特点

  • 轻量级,专注于单一功能
  • 快速解析MP3文件头信息
  • 返回标准库的std::time::Duration类型
  • 简单易用的API

这个库非常适合需要快速获取MP3文件时长而不需要完整音频解码功能的应用程序。


1 回复

Rust MP3音频处理库mp3-duration使用指南

mp3-duration是一个轻量级的Rust库,专门用于快速获取MP3文件的持续时间(时长),无需解码整个音频文件即可高效计算。

功能特点

  • 快速计算MP3文件时长
  • 低内存占用
  • 不依赖外部库
  • 支持标准MP3格式
  • 错误处理完善

安装方法

在Cargo.toml中添加依赖:

[dependencies]
mp3-duration = "0.1"

基本使用方法

获取MP3文件时长

use mp3_duration;
use std::path::Path;

fn main() {
    let path = Path::new("audio.mp3");
    match mp3_duration::from_path(&path) {
        Ok(duration) => {
            println!("Duration: {:?}", duration);
            println!("Seconds: {}", duration.as_secs());
        },
        Err(e) => eprintln!("Error: {}", e),
    }
}

从字节流读取

use mp3_duration;
use std::fs::File;
use std::io::Read;

fn main() {
    let mut file = File::open("audio.mp3").unwrap();
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer).unwrap();
    
    match mp3_duration::from_bytes(&buffer) {
        Ok(duration) => println!("Duration: {:?}", duration),
        Err(e) => eprintln!("Error: {}", e),
    }
}

高级用法

格式化输出时长

use mp3_duration;
use std::time::Duration;

fn format_duration(d: Duration) -> String {
    let secs = d.as_secs();
    let hours = secs / 3600;
    let minutes = (secs % 3600) / 60;
    let seconds = secs % 60;
    
    format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
}

fn main() {
    let path = "audio.mp3";
    if let Ok(duration) = mp3_duration::from_path(path) {
        println!("Formatted duration: {}", format_duration(duration));
    }
}

批量处理MP3文件

use mp3_duration;
use std::path::Path;
use std::fs;

fn main() {
    let dir = Path::new("audio_files");
    
    for entry in fs::read_dir(dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        
        if path.extension().map_or(false, |ext| ext == "mp3") {
            match mp3_duration::from_path(&path) {
                Ok(duration) => {
                    println!("{}: {:?}", path.display(), duration);
                },
                Err(e) => {
                    eprintln!("Error processing {}: {}", path.display(), e);
                }
            }
        }
    }
}

错误处理

mp3-duration提供了详细的错误信息:

use mp3_duration;

fn main() {
    let result = mp3_duration::from_path("nonexistent.mp3");
    
    match result {
        Ok(duration) => println!("Duration: {:?}", duration),
        Err(mp3_duration::Error::Io(e)) => eprintln!("IO error: {}", e),
        Err(mp3_duration::Error::NoMp3Frame) => eprintln!("Not a valid MP3 file"),
        Err(mp3_duration::Error::InfiniteDuration) => eprintln!("Invalid duration (infinite)"),
    }
}

性能提示

  • 对于非常大的MP3文件,使用from_path比先读取到内存再使用from_bytes更高效
  • 该库只读取必要的MP3帧头信息,不会解码整个音频数据

mp3-duration是一个简单高效的库,特别适合需要快速获取MP3时长而不需要完整音频处理的场景。

完整示例代码

下面是一个结合了文件读取、时长计算、格式化输出和错误处理的完整示例:

use mp3_duration;
use std::path::Path;
use std::time::Duration;
use std::error::Error;

// 格式化时长输出为HH:MM:SS
fn format_duration(d: Duration) -> String {
    let secs = d.as_secs();
    let hours = secs / 3600;
    let minutes = (secs % 3600) / 60;
    let seconds = secs % 60;
    format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
}

// 处理单个MP3文件
fn process_single_mp3(path: &Path) -> Result<(), Box<dyn Error>> {
    match mp3_duration::from_path(path) {
        Ok(duration) => {
            println!("File: {}", path.display());
            println!("Raw duration: {:?}", duration);
            println!("Formatted: {}", format_duration(duration));
            println!("Total seconds: {}\n", duration.as_secs());
            Ok(())
        },
        Err(e) => {
            eprintln!("Error processing {}: {}", path.display(), e);
            Err(Box::new(e))
        }
    }
}

// 批量处理目录中的MP3文件
fn process_directory(dir_path: &str) -> Result<(), Box<dyn Error>> {
    let dir = Path::new(dir_path);
    
    if !dir.exists() {
        return Err("Directory does not exist".into());
    }
    
    println!("Processing MP3 files in: {}", dir.display());
    
    for entry in std::fs::read_dir(dir)? {
        let entry = entry?;
        let path = entry.path();
        
        if path.extension().map_or(false, |ext| ext == "mp3") {
            process_single_mp3(&path)?;
        }
    }
    
    Ok(())
}

fn main() {
    // 处理单个文件
    let single_file = Path::new("sample.mp3");
    if let Err(e) = process_single_mp3(single_file) {
        eprintln!("Failed to process single file: {}", e);
    }
    
    // 处理整个目录
    if let Err(e) = process_directory("music") {
        eprintln!("Failed to process directory: {}", e);
    }
}

这个完整示例展示了:

  1. 单个MP3文件的时长获取和格式化输出
  2. 目录中批量处理MP3文件
  3. 完善的错误处理机制
  4. 清晰的代码组织和注释

使用时,只需将示例中的文件路径sample.mp3和目录名music替换为您实际的MP3文件和目录即可。

回到顶部