Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NeriPlayer 一起听服务端

这是 NeriPlayer 一起听功能当前使用的 Cloudflare Workers 服务端实现, 以 np-submodule/NeriPlayer-LTW 的形式随主仓库一起维护。

当前能力

  • 创建房间 / 加入房间,并直接返回可用的 wsUrl
  • 控制者 / 听众双角色与 HMAC Token 鉴权
  • 邀请链接必须携带首次加入所需的 joinSecret;已有成员重连使用自己的 memberSecret,这些密钥不会写入脱敏房间状态
  • WebSocket 实时同步播放状态、队列、切歌、循环模式、随机播放和房间设置
  • 听众可发起控制请求,由 Worker 校验房间策略、房主在线状态和目标歌曲后直接提交
  • 可选共享房主解析出的多个播放直链,减少听众端重复取流压力;Worker 会持久缓存 房主当前曲目最多三条有序候选,缓存命中时听众无需等待房主在线,且只会公开当前曲目的链接
  • 本地歌曲不能创建房间或进入同步事件;关闭 shareAudioLinks 后会立刻清空 房间里已缓存的直链
  • 房间状态持久化、控制者离线检测与自动关房
  • 新成员加入时可按房间设置自动暂停;同一成员使用 memberSecret 或 Token 重连不会触发暂停
  • 控制事件可携带 clientInstanceIdclientSequenceclientTimeMs,Worker 会 过滤过期顺序;WebSocket 支持 np_ping / np_pong 返回服务端时钟并刷新房主存活时间
  • 支持 Deploy to Cloudflare 一键部署或本地源码手动部署

适合场景

  • 自己部署一个轻量的一起听同步服务
  • 给 NeriPlayer Android 客户端配置自定义服务端地址
  • 本地调试一起听协议、房间状态和 WebSocket 消息

它不是媒体代理或公共曲库服务。音频播放能力仍来自 NeriPlayer 客户端本身, Worker 只负责房间状态、权限、队列和同步事件。

仓库结构

.
├─ src/
│  └─ worker.js            # Worker 入口 + ListeningRoomDO
├─ .dev.vars.example       # 本地开发示例密钥
├─ package.json
├─ README.md
└─ wrangler.toml           # Durable Object 绑定与迁移配置

HTTP API

  • POST /api/rooms:创建房间
  • POST /api/rooms/:roomId/join:加入房间
  • GET /api/rooms/:roomId/state:获取房间快照
  • POST /api/rooms/:roomId/control:通过 Authorization: Bearer <token> 提交控制事件
  • GET /api/rooms/:roomId/ws?token=...:建立 WebSocket
  • GET /healthz:健康检查

事件模型

典型流程:

[创建/加入房间] → [HTTP 返回 wsUrl + token]
        ↓
[WebSocket 连接] → [welcome 消息携带 state 快照]
        ↓
[控制事件/听众请求] → [Durable Object 校验与落盘] → [广播 room_state_updated]

控制类事件

  • PLAY
  • PAUSE
  • SEEK
  • PLAYBACK_MODE
  • SET_TRACK
  • SET_QUEUE
  • HEARTBEAT
  • TRACK_FINISHED

听众请求事件

  • REQUEST_PLAY
  • REQUEST_PAUSE
  • REQUEST_SEEK
  • REQUEST_PLAYBACK_MODE
  • REQUEST_SET_TRACK

allowMemberControl=true 且控制者在线时,Worker 会直接仲裁并提交这些请求, 不会再等待控制者客户端弹出确认。REQUEST_PLAYREQUEST_PAUSEREQUEST_SEEKREQUEST_PLAYBACK_MODE 必须携带能匹配当前歌曲的 requestTrackStableKey(也可从事件里的 trackqueue[currentIndex] 推导), 避免延迟请求误操作已经切换的歌曲。REQUEST_SET_TRACK 只能选择服务端当前队列 中已有的曲目,成员携带的队列不会写入房态。控制事件如果带有同一客户端实例的 clientSequence 或较旧的 clientTimeMs,也会被 Worker 丢弃。

其他事件

  • REQUEST_LINK
  • LINK_READY
  • UPDATE_SETTINGS

房间与身份约束

  • 房间号固定为 6 位,使用大写字母和数字的可读字符集
  • nickname 长度为 1-24,当前允许中文、英文字母和数字
  • 每个房间对应一个 ListeningRoomDO
  • Durable Object storage 持久化房间快照与成员状态
  • 新成员必须提供正确的 joinSecret 才能加入;已有成员只能用自己的 memberSecret 或有效 Token 重连
  • 创建快照和后续控制事件均拒绝本地歌曲;旧房态中的本地歌曲会在加载时剔除
  • allowMemberControlautoPauseOnMemberChangeshareAudioLinks 三个房间设置都可由控制者通过 UPDATE_SETTINGS 更新
  • playback.repeatMode 只接受 0(关闭)、1(单曲循环)、2(列表循环), playback.shuffleEnabled 为布尔值;旧客户端缺少这些字段时,Android 客户端 仍按可选字段兼容
  • shareAudioLinks=false 时,HTTP state 快照,以及 WebSocket welcome / room_state_updated 消息里的 state,都会把 track.streamUrltrack.streamUrls 与队列对应字段清空
  • UPDATE_SETTINGS 关闭 shareAudioLinks 后,会立即清空房间里已缓存的直链
  • 重新开启 shareAudioLinks 后,房主客户端会立即重新上传当前歌曲的候选直链;房态只会 公开当前曲目的缓存链接,历史缓存不会泄漏到队列中的其他歌曲
  • REQUEST_LINKshareAudioLinks=false 时会直接失败,返回 audio link sharing disabled
  • 命中当前曲目缓存的 REQUEST_LINK 会直接广播权威房态;forceRefresh=true 会绕过 缓存并向在线房主请求刷新,用于直链失效后的恢复
  • Token 有效期为 24 小时,由 LISTEN_TOGETHER_TOKEN_SECRET 参与 HMAC 签名
  • /state/control 都需要有效的 Authorization: Bearer <token>;WebSocket 连接使用返回的 wsUrl 中的 token
  • 队列上限为 2000 首,避免房间状态无限膨胀
  • 控制者心跳超过 45 秒未更新后房间会进入挂起状态;控制者在 10 分钟 宽限期内重连可恢复房间,超时后房间自动关闭并清理 Durable Object 存储

安全与隐私边界

  • Worker 不存储平台 Cookie、账号密码或 GitHub/WebDAV 凭据
  • HTTP/WS Token 只用于房间控制鉴权,不代表第三方音乐平台授权
  • GET /api/rooms/:roomId/state 需要房间成员的 Bearer Token;健康检查 /healthz 仍保持公开
  • shareAudioLinks 开启时会同步房主解析出的播放直链,请只在可信房间使用
  • 自建实例的日志、访问控制和域名策略由部署者自己负责

环境要求

  • Node.js >= 20
  • Cloudflare 账号
  • Wrangler 4

一键部署到 Cloudflare Workers

下面的按钮会从公开模板仓库拉起 Cloudflare 部署流程 如果你直接使用当前子模块源码,请走后面的手动部署

Deploy to Cloudflare

本地检查与开发

npm ci
npm run check
npx wrangler dev

npm run check 会依次执行 node --check src/worker.js、缓存与协议测试和 wrangler deploy --dry-run。它不替代真实 Cloudflare 环境中的 create/join/WebSocket 流程验证。

本地开发可复制 .dev.vars.example.dev.vars,并填入 LISTEN_TOGETHER_TOKEN_SECRET。建议使用下面的命令生成密钥:

openssl rand -hex 32

手动部署到 Cloudflare Workers

1. 登录 Cloudflare

npx wrangler login

2. 配置生产密钥

npx wrangler secret put LISTEN_TOGETHER_TOKEN_SECRET

3. 部署

npm ci
npm run check
npm run deploy

部署完成后,Wrangler 会输出对应的 *.workers.dev 地址。

在 NeriPlayer 中使用

  1. 打开 NeriPlayer 设置页
  2. 进入一起听服务端配置
  3. 填入你的 Workers 地址,例如 https://example.workers.dev
  4. 点击可用性测试
  5. 通过创建房间或加入邀请链接验证 WebSocket 同步

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages