使用 DeepSeek V4.1 Flash 基于原项目做的 HarmonyOS NEXT 像素复古风mp3小应用。ᓚᘏᗢ
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 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):需要无限制分发时切回它。