【免费下载链接】music-island
Music controls, local dictation, voice processing and assistant limits at the top edge of your Windows desktop.
Music Island 是一款运行在 Windows 桌面顶部的音乐控制工具,能把播放器、语音输入和助手额度管理都收纳到屏幕顶边。它接入 Yandex Music 的方式很特别:不依赖官方 API,而是通过一条仅绑定本机回环地址(127.0.0.1)的 CDP 本地通道,直接驱动已打开的 Yandex Music 桌面客户端——延迟更低、能力更全,还解锁了官方接口拿不到的 My Wave 控制。
一、先搞懂:Music Island 是什么,Yandex 接入解决什么问题
Music Island 的核心是一块"桌面之岛":音乐播放控制悬浮在 Windows 顶部,配合原生任务栏迷你播放器,不用切窗口就能暂停、切歌、拖进度、点赞。
它内置了两种媒体数据源(provider):
- Windows SMTC(默认):走 Windows 系统媒体传输控制,天然支持绝大多数播放器,无需任何登录;
- Yandex Direct(显式开启):专属于 Yandex Music 桌面客户端的直连通道,也就是本文的主角。
官方技术选型记录在 docs/YANDEX_MUSIC_API.md,架构总览见 docs/MEDIA_ARCHITECTURE.md 与 docs/ARCHITECTURE.md。
二、为什么不用官方 API:四条备选路线的取舍
很多音乐控制类工具第一反应是调用 Yandex 的云端接口,但 Music Island 团队把备选方案挨个评估后都放弃了:
| 方案 | 能力 | 为什么没选 |
|---|---|---|
| 本地 CDP 通道✅ | 播放控制、点赞、进度、My Wave 选择 | 选它:本地延迟最低,直接控制正在运行的客户端 |
| Windows SMTC | 通用播放控制 | 保留作为默认与备选,但 Windows 托管的 broker 挂死时无法自愈,且拿不到 Yandex 特色能力 |
| KM.Yandex.Music.Api(非官方 C# 封装) | 搜索、歌单、元数据 | 无法低延迟控制本地渲染器;且 Music Island 是 Rust/Tauri 技术栈,引入 .NET 包会多一层运行时边界 |
| Ynison(内部云同步协议) | 跨设备状态同步 | 未公开文档、认证敏感、随时可能变动,控制的是"账户/设备会话"而非本地进程 |
| 公开目录/网页 API | 元数据、歌单、点赞 | 需要 OAuth/令牌处理,给核心控制器引入不必要的账户与合规风险 |
关键结论:官方 API 擅长"管数据"(元数据、歌单),却不擅长"管进程"——它无法保证毫秒级地操控你电脑上正在播放的那个 Electron 窗口。这正是 Music Island 选择 CDP 的原因。
三、核心原理:本地 CDP 通道是怎么建立的
Yandex Music 桌面客户端基于 Electron(Chromium)构建,天然支持 Chromium DevTools Protocol(CDP)。Music Island 的接入流程可以概括为五步:
- 发现已开启调试端口的客户端:先扫描本机进程,寻找带
--remote-debugging-port=参数的 Yandex Music 进程,验证进程名、music-application://页面地址和回环 WebSocket 后才重新附着(reattach),全程不重启客户端。 - 需要时才请求重启:如果找不到调试端点,用户确认一次后,Music Island 会先关闭旧客户端,再用随机本地端口重新启动:
--remote-debugging-address=127.0.1、--remote-debugging-port=<随机端口>。 - 按 Content-Length 读取发现响应:CDP 端点会保持 HTTP 长连接,Rust 端按声明的
Content-Length精确读取目标列表,避免"等到连接关闭"式的死等。 - 保持一条串行化 WebSocket:整个生命周期只维护一条 CDP WebSocket,请求 ID 递增、自动重连,状态与指令共用同一通道。
- 状态归一化:读取到的 DOM 状态统一封装成标准的
MediaSnapshot,前端(React)无需关心底层 provider 差异,按canSeek、canLike等能力位渲染控件。
核心实现都在 src-tauri/src/yandex/mod.rs,其中 enable() 连接/重启流程 和 attach_existing() 无重启附着 是最值得看的两段;进程扫描逻辑见 find_running_debug_endpoint()。
四、安全设计:一条"只属于本机"的通道
直连浏览器内核听起来有风险,Music Island 在协议层做了多重约束:
- 仅回环、随机端口:调试端口随机分配且只绑定
127.0.0.1,永不暴露到局域网。WebSocket 地址必须以ws://127.0.0.1:<port>/开头才接受,见 websocket_matches_endpoint()。 - 目标白名单:只认
music-application://协议的 page 目标,其他页面一律拒绝(is_valid_target())。 - 固定指令集:所有状态读取和点击动作都由 Rust 侧的固定表达式生成,前端无法提交任意 JavaScript;My Wave 预设 ID 也经过严格字符校验,防注入(valid_dom_id())。
- 不碰账号数据:不读取、不存储 OAuth 令牌、Cookie 或会话响应,日志中也不出现敏感信息;登录、播放、推荐仍由 Yandex 客户端自己负责。
五、指令如何生效:固定选择器 + 状态确认
以播放/暂停为例,Rust 侧把命令翻译为一段查找data-test-id控件并点击的表达式(如PLAY_BUTTON、PAUSE_BUTTON、NEXT_TRACK_BUTTON),执行后还会回读状态确认结果真的变了(播放状态翻转、点赞状态翻转等),最多重试 4 次,确认失败则报错——见 send_command() 与 confirm_command()。
状态读取用的 STATE_EXPRESSION 是个精心打磨的"探测器":
- 优先使用稳定的
data-test-id,兜底再识别常见的PlayerBarDesktop类布局,这样客户端从首页切到收藏页等 SPA 路由跳转后,标题/艺人信息依然持续刷新; - 自动折叠 DOM 重复拼接产生的 "TitleTitle" 式脏标题;
- 按 track ID 缓存封面/艺人,弥补 DOM 短暂缺失;
- 时间进度优先读滑块
value/max,兜底解析 "分:秒" 文本。
六、My Wave:本地通道独有的"氛围轮盘"控制
这是官方 API 给不了的能力。Yandex 2026 年 7 月版桌面客户端把 My Wave(情绪/氛围推荐)的当前选择与轮盘暴露在 DOM 里,Music Island 通过RESET_VIBE_CONTEXT_BUTTON、WHEEL_DESKTOP、WHEEL_VIBE_ITEM等控件:
- 读取当前激活的 My Wave 标签,显示为悬浮岛下方的居中 chip;
- 清除选择时调用客户端原生的重置按钮,而不是模拟输入。
预设目录抓取在 0.9.5 中暂时关闭,代码保留为未来的可选设置项。相关实现:wave_presets() 与 select_wave_preset()。
七、新手接入教程:三步开启 Direct 模式
- 打开 Music Island 设置,进入Music source(音乐数据源);
- 选择 Yandex Music Direct 连接,首次连接会弹出确认框(DirectConnectionDialog):提示"连接仅限本机""实验性功能,Yandex 更新后可能失效""可随时切回 SMTC";
- 点击连接。若当前客户端未开启调试端口,它会在你确认后重启一次 Yandex Music,随后自动进入已连接状态。
状态机一共七态:Disabled / Connecting / Connected / Degraded / RestartRequired / Incompatible / Error,前端通过 useDirectStatus() 实时订阅展示。
八、连接掉线怎么办:自动软恢复 + 手动急救
CDP 通道是实验性路径,Yandex 客户端更新后可能失效,Music Island 的分层恢复策略值得借鉴:
- 降级不切源:探针失败时保留最后一次 Direct 快照,标记
Degraded并以有限延迟重试,绝不悄悄回落 SMTC(record_probe_failure()); - 软恢复:连续失败达到阈值(3 次)后自动重新发现并附着调试端点,不杀客户端进程(try_soft_recover());
- 需要重启:失败达到 8 次且端点确实不存在时,状态置为
RestartRequired,在悬浮岛显示"Быстрая перезагрузка(快速重连)"、设置里显示"Перезапустить",由用户显式触发重启; - 切回 SMTC:会先关闭带调试参数的客户端,再以普通方式重新启动它——这一步同样需要用户确认。
九、能力矩阵与诚实的边界
| 能力 | SMTC | Yandex Direct(CDP) |
|---|---|---|
| 元数据 / 封面 | ✅ | ✅ |
| 播放 / 暂停 / 上一首 / 下一首 | ✅ | ✅ |
| 进度拖拽 | ✅ | ✅ |
| 点赞 / 点踩 / 随机 / 循环 | 取决于播放器 | ✅(按能力位显示) |
| My Wave 选择状态与清除 | ❌ | ✅ |
| 本地延迟 | 受系统 broker 影响 | 更低 |
| 稳定性 | 高 | 实验性,随客户端版本波动 |
需要提醒的边界:这是非官方集成,Yandex Music 更新可能使其失效;它不产生新的播放会话、不串流音频,只做控制;SMTC 始终是随时可用的备选。如果你想在本地复现或研究这条通道,源码入口是 src-tauri/src/yandex/,协议与取舍全文见 docs/YANDEX_MUSIC_API.md,其中"为什么这样选"的完整论证(Alternatives 与 Recovery 两节)非常值得读完。
一句话总结:官方 API 解决"账号里有什么",本地 CDP 通道解决"此刻正在播放什么"——Music Island 用一条严格受控的本机回环通道,把后者做到了低延迟、可确认、可恢复,这正是桌面端音乐控制工具绕开云端接口限制的最佳实践。
【免费下载链接】music-island
Music controls, local dictation, voice processing and assistant limits at the top edge of your Windows desktop.
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考