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

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

本系列教程对应的代码已开源在 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.jsqmd.com/news/6508/

相关文章:

  • Tita项目与绩效一体化管理:重构组织效能的数字化中枢
  • 深入解析:【网络编程】套接字入门:网络字节序与套接字种类剖析
  • 地产行业,居然还有这样的开发商 - 智慧园区
  • 【半导体物理 | 笔记】 第三章 半导体中的载流子分布
  • vscode提交github时报错:fatal: origin does not appear to be a git repository
  • 2025.9.30——1黄
  • VMware vSphere Replication 9.0.4 发布 - 虚拟机复制和数据保护
  • 【半导体物理 | 笔记】第二章 半导体中杂质和缺陷能级
  • VMware Live Site Recovery 9.0.4 发布 - 数据中心灾难恢复 (DR)
  • 【kafka】基于python发送kafka消息
  • VMware Tools 13.0.5.0 发布 - 客户机操作系统无缝交互必备组件
  • 使用openresty+lua来实现grafana中自动切换实时群集/历史群集对应的vmselect
  • 【python】根据给定的协议,解析一个hexdump 字符串
  • 读博期间的工作节奏与身心状态管理经验总结
  • 【Rust GUI开发入门】编写一个本地音乐播放器(7. 制作歌词显示面板) - Jordan
  • 基于内容可信空间的医疗行业机遇研究报告
  • 2025 年成型机厂商最新权威推荐排行榜:冷弯 / 光伏支架 / 门业等设备企业精度耐用性测评底樑/光伏支架/C型钢/彩钢瓦/快速门成型机厂商推荐
  • .Net Core MVC + Vue + SignalR 实现 后端数据主动推送到前端
  • js 获取下一个月时间和下一年的时间
  • 【Rust GUI开发入门】编写一个本地音乐播放器(5. 制作音乐列表组件) - Jordan
  • 【Nordic】nRF9151的SLM例程常用AT指令说明
  • sql server经典语句「转」
  • Codeforces 2149G Buratsuta 3 题解 [ 蓝 ] [ 摩尔投票 ] [ 线段树 ] [ 随机化 ] [ 主席树 ] [ 根号分治 ]
  • 2025 年最新推荐软件开发机构榜:聚焦微服务架构与 724 小时服务的优质厂商精选指南人力资源管理系统/资产管理系统/数据中台管理系统/流程管理系统软件开发公司推荐
  • 【半导体物理 | 学习笔记】第一章 半导体中的电子状态
  • 计数(5):多项式相关
  • 最新WTAPI开发微信机器人教程说明
  • 线性DP - 学习笔记
  • 2025 年最新制氮机厂家权威推荐排行榜:聚焦行业优质厂商综合实力,助力企业精准选购优质设备制氮机产生氮气/氮气纯化/设备改造/维修/保养/半导体用制氮机厂家推荐
  • idea打包推送maven仓库及同时推送到不同的maven仓库,本地和云上的腾讯云