当前位置: 首页 > news >正文

【Rust GUI开发入门】编写一个本地音乐播放器(8. 从文件中提取歌曲元信息)

本系列教程对应的代码已开源在 Github zeedle

目的是从.mp3/.flac/.wav/...文件中提取歌曲名称/艺术家/音频时长信息/歌词信息/专辑封面

添加依赖

使用lofty这个全能解析库,将其添加到Cargo.toml中:

lofty = "0.22.4"

解析元信息

解析歌名/歌手/时长

这些信息在应用启动后,即刻被加载到音乐列表面板中(SongInfo已于前几篇文章中定义):

/// Read meta info from audio file `fp`, return a SongInfo
pub fn read_meta_info(fp: &PathBuf) -> Option<SongInfo> {if let Ok(tagged) = lofty::read_from_path(fp) {let dura = tagged.properties().duration().as_secs_f32();if let Some(tag) = tagged.primary_tag() {let song_name = tag.title();let song_name = song_name.as_deref().unwrap_or(fp.file_stem().map(|x| x.to_str()).flatten().unwrap_or("unknown"),);let singer_name = tag.artist();let singer_name = singer_name.as_deref().unwrap_or("unknown");let item = SongInfo {id: 0,song_path: fp.display().to_shared_string(),song_name: song_name.into(),singer: singer_name.into(),duration: format!("{:02}:{:02}", (dura as u32) / 60, (dura as u32) % 60).to_shared_string(),};return Some(item);}}None
}

解析歌词

歌词只有在播放该文件时才应该被加载,所以单独解析:

/// Read lyrics from audio file `p`, return a list of LyricItem
pub fn read_lyrics(p: PathBuf) -> Vec<LyricItem> {if let Ok(tagged) = lofty::read_from_path(&p) {if let Some(tag) = tagged.primary_tag() {if let Some(lyric_item) = tag.get(&ItemKey::Lyrics) {let mut lyrics = lyric_item.value().text().unwrap().split("\n").map(|line| {let (time_str, text) = line.split_once(']').unwrap_or(("", ""));let time_str = time_str.trim_start_matches('[');let dura = time_str.split(':').map(|x| x.parse::<f32>().unwrap_or(0.)).rev().reduce(|acc, x| acc + x * 60.).unwrap_or(0.);LyricItem {time: dura,text: text.to_shared_string(),duration: 0.0,}}).filter(|ins| ins.time > 0. && !ins.text.is_empty()).collect::<Vec<_>>();for i in 0..lyrics.len() - 1 {lyrics[i].duration = lyrics[i + 1].time - lyrics[i].time;}lyrics.last_mut().map(|ins| ins.duration = 100.0);return lyrics;}}}return Vec::new();
}

解析专辑封面

同上,该图像只有在播放该文件时才应该被加载,所以单独解析:

/// Read album cover from audio file `p`
pub fn read_album_cover(p: PathBuf) -> Option<(Vec<u8>, u32, u32)> {if let Ok(tagged) = lofty::read_from_path(&p) {if let Some(tag) = tagged.primary_tag() {if let Some(picture) = tag.pictures().iter().find(|pic| {pic.pic_type() == PictureType::CoverFront|| pic.pic_type() == PictureType::CoverBack}) {if let Ok(img) = image::load_from_memory(picture.data()) {let rgba = img.into_rgba8();let (width, height) = rgba.dimensions();let buffer = rgba.into_vec();return Some((buffer, width, height));}}}}None
}
http://www.dtcms.com/a/427077.html

相关文章:

  • 国内个人网站建设贾汪城乡建设局网站
  • CentOS二进制安装包方式部署K8S集群之系统初始化
  • Spring Boot 缓存集成实践
  • 力扣Hot100--21.合并两个有序链表
  • 网络安全和NLP、CV是并行的应用吗?
  • 如何做好一个企业网站专门做图片的网站
  • 网页设计网站wordpress公告栏插件
  • C++ 位运算 高频面试考点 力扣 371. 两整数之和 题解 每日一题
  • 网络安全常见敏感目录字典
  • React学习(三)--- 组件化开发编写css
  • 设计模式(C++)详解——观察者模式(Observer)(1)
  • 网站建设报表明细新手做网站看什么书
  • 微课网站开发如何查看网站域名
  • Spring工程 生成表和mapper文件
  • 服装培训网站建设网站图片切换
  • Python爬虫实战:获取丁香人才网招聘信息与数据分析
  • 光学转镜最小长度计算模型:基于视场角与有效口径的匹配算法
  • 汉子由来 外国人做的网站网页设计的尺寸是指
  • 智能驱动与合规双赢:2025年企业DevOps平台选型深度解析
  • 2025年,如何选择Python Web框架:Django, Flask还是FastAPI?
  • FLASK与JAVA的多文件互传(多文件互传亲测)
  • 蓝牙音箱的技术演进:从便捷到高保真的音频革命
  • 打破信息孤岛,构建统一视界:视频融合平台EasyCVR在智慧校园建设中的核心作用
  • 计算机应用技术网站开发基础知识网店推广平台
  • 快速完美解决在CefSharp.WinForms.ChromiumWebBrowser浏览器中无法播放视频的问题
  • 【高并发服务器:前置知识】一、项目介绍 模块划分
  • 数据结构入门 (五):约束即是力量 —— 深入理解栈
  • 如何搭建网站的结构丰台专业网站建设公司
  • Web渗透之一句话木马
  • 网站建设如何选择服务器百度做公司网站多少钱