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);
}
}
这个完整示例展示了:
- 单个MP3文件的时长获取和格式化输出
- 目录中批量处理MP3文件
- 完善的错误处理机制
- 清晰的代码组织和注释
使用时,只需将示例中的文件路径sample.mp3
和目录名music
替换为您实际的MP3文件和目录即可。