Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Freq · 人和 AI 共用的播放器

一个共享播放状态的 PWA 音乐播放器:人在页面里使用迷你播放器和完整播放页,AI 通过 MCP 搜歌、播放、排队和控制同一个房间。

The human-facing PWA and the AI-facing MCP server control the same music room.

这个公开版从真实家庭 PWA 的现役播放器中独立抽出,保留了核心体验:

  • 固定在页面底部的迷你播放器:封面、进度、上/下一首、播放暂停、快速队列
  • 正式播放页:大封面、同步歌词、拖动进度、循环、随机、曲库搜索、队列与红心
  • 浏览器自动播放被拦截时,给出明确的一次点击恢复卡片
  • PWA manifest、离线壳与三段可自由分发的原创合成演示音频
  • 七个 stdio MCP 工具:读取、搜索、立即播放、排队、暂停、继续、下一首
  • Cookie 即用的网易云适配器;不填 Cookie 时自动回到零框架本地演示源

仓库不包含家庭 App、聊天页、聊天记录、私有音乐账号、生产域名、Cookie、签名媒体地址或任何凭据。

Cookie 即用(真实网易云)

把仓库交给安装 Agent 时,只需让它执行:

npm install
cp .env.example .env

然后把你从已登录 music.163.com 浏览器会话复制出的完整 Cookie header 写进本地 .env

MUSIC_SOURCE=netease
NETEASE_COOKIE="MUSIC_U=...; __csrf=...; ..."

再启动:

npm run demo

打开 http://127.0.0.1:8788,点“打开播放器”→右上角音乐库,就能搜索账号可播放的真实歌曲;MCP 同时使用同一曲库和播放房间。

.env 已被 Git 忽略。Cookie 只存在 Node 音源进程里,不返回给 PWA 或 MCP;限时音频地址也不进入播放状态、工具结果或持久化文件,而是由浏览器播放时通过同源解析端点按需取得。

如果播放接口提示 NetEase login expired,说明 Cookie 已失效:替换 .env 里的 Cookie 后重启进程即可。

无 Cookie 演示模式

需要 Node.js 20+。

npm install
npm run demo

不创建 .env,或设置 MUSIC_SOURCE=demo,再打开 http://127.0.0.1:8788。默认停在第一首演示曲,点迷你播放器即可展开完整页面。

另开一个终端启动 MCP:

MUSIC_RELAY_URL=http://127.0.0.1:8788 npm run mcp

此时页面和 MCP 会共享同一个内存播放房间。模型调用 music_play 后,打开着的 PWA 会在下一次轮询中收到新曲目;若浏览器的自动播放策略要求手势,页面会出现“点一下发出声音”的恢复卡片。

接入 MCP 客户端

Claude Desktop、Claude Code 或其他支持 stdio MCP 的客户端可使用:

{
  "mcpServers": {
    "music-player": {
      "command": "node",
      "args": ["/absolute/path/to/Freq/src/mcp-server.js"],
      "env": {
        "MUSIC_RELAY_URL": "http://127.0.0.1:8788"
      }
    }
  }
}

如果 Relay 开启了 token,再加入:

"MUSIC_TOKEN": "your-relay-token"

工具语义:

  • music_state():读取当前曲目、播放状态和队列
  • music_search(query):只搜索,不改播放状态
  • music_play(query):立即播放唯一匹配的曲目
  • music_queue(query):把唯一匹配的曲目加入队列
  • music_pause():暂停
  • music_resume():继续播放;浏览器仍可能要求一次用户手势
  • music_next():播放队列下一首;队列为空时顺序进入下一首演示曲

模糊查询命中多首时,MCP 会返回候选并要求模型说得更具体,不会擅自挑第一首。

PWA 结构

公开版没有把播放器绑死在 demo 首页里:

web/index.html             迷你播放器与完整播放页的语义化结构
web/player.css             独立播放器视觉、响应式布局与 Reduced Motion
web/player.js              音频生命周期、轮询、搜索、队列、歌词与红心
web/manifest.webmanifest   PWA 安装信息
web/sw.js                  离线壳和演示音频缓存

要嵌进已有 PWA,可把 index.html 中的 [data-music-player] 节点及其完整播放页移入你的页面,并引入:

<link rel="stylesheet" href="/player.css">
<script type="module" src="/player.js"></script>

组件只依赖下方 API 合同,不依赖聊天 App、前端框架或特定音乐平台。红心默认存在浏览器 localStorage;共享队列与当前播放状态存在 Relay。

Relay API 合同

现有后端不必使用 demo server,只要实现五个请求:

GET  /api/state
GET  /api/tracks?q=<query>
GET  /api/tracks/<track-id>/lyrics
POST /api/queue
POST /api/control

搜索返回:

{
  "tracks": [
    {
      "id": "blue-hour",
      "title": "Blue Hour",
      "artist": "Open Signals",
      "duration_sec": 24,
      "audio_url": "/audio/blue-hour.mp3",
      "palette": ["#7695ad", "#c19caf"]
    }
  ]
}

立即播放或排队:

POST /api/queue
Content-Type: application/json

{ "track_id": "blue-hour", "play_now": true }

控制请求:

POST /api/control
Content-Type: application/json

{ "action": "pause", "position_sec": 8.25 }

action 支持 playpauseseeknextpreviousended。响应都返回最新播放快照。

换成其他音乐源

网易云适配器在 src/netease-source.js,演示适配器在 src/music-source.js。要接其他平台,实现同样的 initialTracks/search/track/lyrics/resolve 五个方法即可。

audio_url 应保持为同源解析路径;若供应商返回签名地址,只在 resolve() 当次请求里使用,不要把它写入日志、MCP 工具返回或持久化存储。

生产场景通常会把 demo 的内存 MusicRoom 换成数据库或现有播放服务,同时保持 API 合同不变。播放器本身不要求网易云、Spotify、Apple Music 或任何特定供应商。

本地 Relay 配置

HOST=127.0.0.1 \
PORT=8788 \
MUSIC_TOKEN=choose-a-token \
npm run demo
  • 默认只监听 127.0.0.1
  • 设置 MUSIC_TOKEN 后,MCP 使用 Bearer token;demo 首页会写入同值的 HttpOnly/SameSite cookie,浏览器仍可直接运行
  • 播放房间在 demo 进程内存中,重启后恢复到第一首暂停状态

测试

npm test
npm run check

聚焦测试覆盖播放房间状态转换、立即播放后把被打断曲目放回队首、PWA 静态资源和音频可用、token 的浏览器/MCP 两条路径、Cookie 不下传的网易云搜索/解析边界,以及 stdio MCP 工具声明。

来历与署名

它诞生于一个家庭 AI 伴侣项目:迷你播放器常驻聊天页,完整页面承载一起听、歌词、队列和模型点歌。

共创人:小cc桑尼(Sunnymilk / Sunny)

公开版由 词词 发起并授权;Sunnymilk(Sunny,家里的 Codex) 从现役实现中抽取、去除家庭耦合、补齐通用 MCP 与独立 demo。

Co-created by CC and Sunnymilk (Sunny). Open-source edition initiated by Cici and extracted/generalized by Sunnymilk (Sunny, the household Codex).

License

代码使用 MIT License。web/audio/ 下三段原创合成演示音频另以 CC0 1.0 释出,方便 fork 直接保留演示。

About

A shared PWA music player with mini/full player UI and MCP controls

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages