osu-mc-hmos-mp3:基于 HarmonyOS 的复古 ESP32 风格 MP3 播放器项目

使用 DeepSeek V4.1 Flash 基于原项目做的 HarmonyOS NEXT 像素复古风mp3小应用。ᓚᘏᗢ

分支2Tags6
文件最后提交记录最后更新时间
3 天前
3 天前
3 天前
7 天前
3 天前
7 天前
3 天前
6 天前
3 天前
5 天前
6 天前
6 天前
7 天前
6 天前

osu!mp3 for HarmonyOS(osu-mc-hmos-mp3)

一个复古 ESP32 风格的 MP3 播放器,跑在 HarmonyOS 上。

界面沿用单片机小项目 osu!mc (TinyGo + ESP32-S3 + 128×64 单色 OLED,界面仿 osu!(lazer))的屏幕与外壳, 但屏幕里装的不再是假数据,而是一个真正能用的播放器:

  • 真实文件:通过鸿蒙文件管理导入音频(「导入音频…」列出本地所有音频; 「添加文件夹…」递归扫描目录),曲库用 SQLite 持久化,重启后完整恢复。
  • 真实播放:AVPlayer 解码,播放 / 暂停 / 上下曲 / 进度拖动 / 倍速(0.5×–3.0×)/ 随机 / 单曲循环 / 列表循环。
  • 真实后台:后台长时任务 + AVSession——切后台、锁屏、耳机线控、播控中心都能控制。
  • 真实元数据:标题 / 艺术家 / 专辑 / 格式 / 时长 / 大小,完整信息进「曲目信息」子页。
  • 真实歌词:.lrc(UTF-8 / GBK / UTF-16)同名自动匹配或手动选文件; 歌词页跟随播放逐句滚动,用户上下翻看后 3 秒自动回位,MID 可跳到某一句。
  • 真实播放列表:收藏(内置列表)+ 自建列表 + 队列 + 最近播放,全部持久化。
  • 接管系统媒体音量:屏幕音量条读的是手机真实媒体音量,物理音量键改动会同步; 应用内 ± 经系统音量面板生效。
  • 真实数据:系统信息页的 循环 / 绘制 / 占用 是主循环真实帧率,播放信息 是真实播放状态。
  • 中英双语:外壳与屏幕各自独立的语言开关。

屏幕仍是软件光栅化(自建 1-bit 帧缓冲 → Canvas 逐像素 → 最近邻整数倍放大), 外壳仍是 ArkUI 原生组件 + 状态管理 V2。


文档导航

本文件只提供整个项目的缩略图;具体内容在下面的专属文档里。

文档 面向谁 内容
本文件 人(入门) 项目是什么、长什么样、页面与按键、构建运行、目录结构
docs/project-guide.md 所有人 整个项目的详细说明:分层、播放引擎、曲库、搜索、双语、验证、边界
AGENTS.md 改代码的 AI 工作准则、屏幕引擎要点、实现坑、常量、文档指针
docs/screen.md 改屏幕的人 渲染链路、动画、UI 模型、事件、主循环、屏幕页面、文案规范、常量
docs/arkui-app-guide.md 改外壳的人 Navigation 与系统路由表、设置页、MVVM、沉浸式、按键振动、主题资源
docs/harmonyos-media-api-notes.md 写媒体代码的人 AVPlayer / AVSession / 长时任务 / picker / fs / 授权 / SQLite 的精确签名与实测坑
docs/chinese-fonts.md 改中文字体的人 两套中文字形表、覆盖率、许可、生成链、切换步骤
docs/lyrics-plan.md 改歌词功能的人 .lrc 解析 / 读取 / 解码、歌词页与跟随状态机的完整方案
docs/p15-media-source-research.md 查导入方式的人 音频来源与导入方式的调研结论(权限矩阵、SD 卡、拼音 API)
docs/mp3-refactor-plan.md 接手后续工作的人 尚未完成的事项(真机回归、双语验证、溢出优化)
docs/harmonyos-port-plan.md 核对屏幕像素细节的人 与原 osu!mc 的逐文件映射、逐类要点、全部常量(参考资料)

它长什么样

  • 屏幕:128×64、1 bit/像素、固定黑底白字(OLED 语义),不走 ArkUI 主题。 自建帧缓冲逐像素绘制,再按窗口可用的最大整数倍最近邻放大 (128×64 → 例如 6× 即 768×384 px)。放大倍数上限可在应用设置页调整。 只能是整数倍:非整数倍会让最近邻放大把源像素摊成大小不一的方块(肉眼即"帧错位")。
  • 外壳:应用标题与 7 个按键是 ArkUI 原生控件,文案走 $r,深浅两套主题; 按键按下会振动一次(强度可调)。

屏幕内的页面

页面 内容
Launcher(根页) 标题 osu!mp3;入口:正在播放 / 音乐库 / 播放列表 / 设置 / 系统信息
音乐库 导入音频… / 添加文件夹… / 文件夹 (n) / 搜索… / 管理曲库… / 共 N 首 / 曲目列表
搜索 屏幕键盘([拼音首字母/英文])→ 结果页(搜索结果 / 输入行 / 共 N 首 / 匹配曲目)
正在播放 曲名 - 艺术家 / 时间 / 进度条 / 上一首·播放暂停·下一首 / -15s +15s / 循环 / 随机 / 倍速 / 收藏 / 队列 (N) / 歌词 / 曲目信息
播放列表 队列 (N) / 收藏 (N) / 最近播放 (N) / 新建播放列表… / 我的列表 (n) + 自建列表 / 清空曲库
设置(屏内) 循环 / 随机 / 倍速 / 音量(接管系统媒体音量)/ 语言 / 关闭屏幕 / 关于
系统信息 芯片 / 内存 / 固件(模拟 ESP32 数据)、主循环(真实帧率)、播放信息(真实播放状态)
子页 歌词、曲目操作、曲目信息、文件夹管理、文件夹操作、播放列表详情、批量管理、播放列表勾选、曲目多选、命名(屏幕键盘)、二次确认

屏幕内所有页面都是 List + ListItem:一页一个 List,一行一个 ListItem。 屏幕文案走 application/Lang.ets 的双语表(中英成对),长标题自动走马灯。 逐页细节见 docs/screen.md §6。


屏幕下方的 7 个按键

这 7 个按钮是 ArkUI 原生按钮,模拟真机的 6 个按键 + 1 个复位键外壳, 映射关系与原项目 cmd/osu-mc/osu-mc.go 一致。

排布(竖屏,屏幕正下方):

   [ RST ]      [ ? ]      [ SET ]     ← RST 在左 / 按键说明在中间 / SET 在右
                 [ UP ]
        [ LEFT ]  [ MID ]  [ RIGHT ]    ← 十字键
                [ DOWN ]

横屏改为左右排:左栏标题 + 屏幕,右栏按键,各占一半宽度并垂直居中。

先说结论:MID 是确认、SET 是返回、RST 是回主页。

键 说明
UP / DOWN 列表选择上下移动;到边界继续按住会让内容 + 游标反向偏移 6px,松开弹回
LEFT 横向行左移 / 进度条快退;行首再按会返回上一页(「正在播放」页例外,永不返回)
RIGHT 横向行右移 / 进度条快进;曲目行进入「曲目操作」
MID 确认:打开页面、播放 / 暂停、键盘按键、提交输入
SET 返回:按住页面右移 8px peek,松开才 pop
RST 回主页:popToRoot(),一次弹到栈底(不重启芯片)
  • 确认 / 返回 / 打开键盘都在松开时执行;按下只给反馈(游标倾斜 / 挤压、页面 peek)。
  • 关屏后任意键唤醒,唤醒的那次按键被吞掉,不会顺带确认或返回。
  • 按住方向键会加速重复(0.2s 后开始,间隔从 0.07s 逐步缩到 0.03s)。
  • 详细语义见 docs/screen.md §4。

应用外壳

完整设计见 docs/arkui-app-guide.md。

  • 导航:首页是 HdsNavigation 根页,标题栏不带标题文字,只保留右侧设置菜单; 子页面走系统路由表(router_map.json + RouteName),新增页面不必改首页。

  • 应用设置页:外观(深浅色)/ 标题栏模糊 / 沉浸光感 / 按键振动 / 屏幕旋转 / 屏幕倍数 / 语言 / 关于。卡片底色浅灰 #E8EAED、深灰 #2A2A2A; 分段控件用原生 CapsuleSegmentButtonV2(保持系统默认配色)。

  • 状态管理统一 V2:@ComponentV2 / @Local / @Param / @Event / @Monitor, 跨页共享用 @ObservedV2 + @Trace 单例 AppUiState。

  • 数据分层(MVVM):

    View(SettingsPage · @Local 快照)
      └─→ ViewModel(SettingsViewModel · 编排读写 + 发布 + 系统生效)
            └─→ Repository(SettingsRepository · 字段 ↔ KV 键)
                  └─→ KeyValueStore(Preferences / 以后可换 SQLite,只需改一行装配)
    
  • 沉浸式(组件级):页面背景 expandSafeArea 延伸到状态栏 / 导航条; 标题栏支持滚动动态模糊与沉浸光感;首页 7 键用 .systemMaterial(...)。

  • 按键振动:按下 7 键时短振一次,强度在设置页调(关闭 / 弱 / 中 / 强,默认「弱」)。

  • 平台版本:targetSdkVersion = compatibleSdkVersion = 26.0.0 (沉浸光感所用的 uiMaterial / systemMaterial 自 API 26 起提供)。

⚠️ 区分两个「Settings」:application/Settings.ets 是屏内设置页; pages/SettingsPage.ets 是应用外壳的设置页。


容易误解的地方

  • MID 为什么是确认、SET 为什么是返回? 它们是硬件按键的丝印名 (原项目 KBD_MID_PIN / KBD_SET_PIN),原作者沿用板子上的叫法,映射成 KeyEnter / KeyBack。板子上没有单独的 Back 键,所以 SET 兼作返回。
  • RST 是「复位」,但不是重启芯片。 硬件上它是 GPIO9 上的普通按键(键码 0), 功能是把界面复位回主页。
  • 按下 ≠ 执行。 事件三态 Press / Repeat / Release,动作都在松开时提交。
  • 屏幕是软件光栅化,按钮才是原生控件。
  • 屏幕上的感叹号 ! 是刻意改过的。 原固件把它画成没有点的实心竖线, 本项目用 tools/fixglyph 改成「竖线 + 点」——全项目唯一一处刻意偏离固件的像素。
  • ESP32 硬件信息是假数据,但帧率与播放信息是真的。
  • 中英文字体是两张点阵表拼起来的:ASCII 用 tinyfont notosans12pt(与固件逐像素一致), 中文用 Zpix 最像素(GB2312 汉字一个不缺)。Zpix 个人使用免费、商用收费, 所以仓库里保留了一套 OFL 的 Fusion 作为可商用回退,见 docs/chinese-fonts.md。
  • 左右键的重复只到达「接管按下」的那个元素,所以按住 LEFT 只返回一层, 在进度条上则是按住加速。

构建与运行

  • 用 DevEco Studio(推荐):拉取项目 → 配置签名 → 直接运行。
  • 用命令行 devecocli:
# 无线连接设备
hdc tconn <ip>:<port>
devecocli device list

# 检查 ArkTS 语法
devecocli check arkts
# 构建 + 安装 + 启动(--uninstall 先卸载同名旧应用)
devecocli run --device "<设备名>" --uninstall
  • Stage 模型 + ArkTS,bundleName = cn.forforio.osumchmos.mp3。
  • 后台播放需要 module.json5 的 KEEP_BACKGROUND_RUNNING 权限与 backgroundModes。
  • 字体点阵表全部由工具生成、可复现,首次构建 / 运行不需要 Go 环境。
  • ⚠️ 若显式指定了 build-profile.json5 的 output.artifactName,devecocli run 会误报 hap 未签名;此时改用:
hdc -t {实机ip} install -r "{项目路径}\entry\build\default\outputs\default\{产物}.hap"
  • 纯逻辑单测在 entry/src/test/(Hypium),在 DevEco Studio 里右键运行; devecocli 不提供本机测试运行器。

目录结构

entry/src/main/ets/
├── animation/    动画 Value(指数平滑 / 阻尼弹簧)与全局 Manager
├── screen/       FrameBuffer(1-bit 帧缓冲)/ ScreenView(最近邻放大)/
│                 Shell(主循环 / 输入分发)/ ScalePolicy(整数倍策略)
├── ui/           屏幕引擎:Canvas / Geometry / Element / Event / Cursor / Nav /
│                 Item / List / Row / Text / TextView / Input / Select / Checkbox /
│                 Chip / Keyboard / Viewer / Seekbar / Font / UiConstants
├── application/  屏幕页面与服务接缝:Launcher / Music / NowPlaying / Playlists /
│                 Settings / SysInfo / 曲目·文件夹·播放列表子页 / SearchPage /
│                 App / Services / MockServices / Lang / MediaUtil / Mp3Format /
│                 Pinyin / TextUtil
├── player/       MP3 引擎:AudioEngine / Playlist / LibraryStore(SQLite)/
│                 MediaLibrary / PermissionGuard / SessionBridge / VolumeBridge /
│                 BackgroundKeeper / PlayerHost
├── font/         内嵌点阵字模:Noto12Glyphs(ASCII)、Zpix12Glyphs(中文)
├── input/        Buttons:按键去抖 + 重复加速
├── pages/        Index(7 键外壳 + Navigation 根页);SettingsPage(应用设置页)
├── common/       外壳通用工具(AppTheme / MaterialUtil / RouteName / TitleBarUtil /
│                 VibratorUtil / AppInfo / ContextUtil / ErrorUtil)
├── components/   SegmentedControl(通用分段控件)
├── preferences/  设置模块(AppSettings / AppUiState / KeyValueStore /
│                 SettingsRepository / SettingsViewModel / DisplayController /
│                 LanguageController / ScreenLangBridge)
└── entryability/ EntryAbility(启动恢复设置、状态栏字色、旋转)

entry/src/test/   本地单元测试(动画 / 渲染 / 播放队列 / MediaUtil / 拼音)
tools/            字体点阵生成工具(exportfont / fixglyph / exportcjk / mergeglyphs,
                  各自是独立 Go module)+ font-backup(Fusion 字形表备份)
docs/             项目文档(见上方「文档导航」)

项目来源与许可

本项目的屏幕 UI/UX 完全参考自 osu!mc (TinyGo + ESP32-S3 + 128×64 单色 OLED),由 chhongzh 以 MIT 许可证发布。 本项目在其复刻版的基础上,把屏幕内容改造为一个真正可用的 MP3 播放器。

屏幕字体:

  • 英文来自 tinyfont 的 notosans12pt (BSD 3-Clause)。
  • 中文字形表有两套(见 docs/chinese-fonts.md):
    • Zpix 最像素(当前启用):个人与教育项目免费,商用收费,且禁止修改 / 拆分; 本仓库按个人项目使用,商用或公开分发前请先取得授权。
    • Fusion Pixel Font(可商用回退,SIL OFL 1.1):需要无限制分发时切回它。

项目介绍

使用 DeepSeek V4.1 Flash 基于原项目做的 HarmonyOS NEXT 像素复古风mp3小应用。ᓚᘏᗢ

定制我的领域