인터페이스는 현지화되어 있으며, Skill 소개와 설명 문서는 선택한 언어로 AI가 자동 번역합니다. 코드·명령어·경로·전문 용어는 원문을 유지하며 원작자 문서가 우선합니다.
Skills 둘러보기
개발 및 엔지니어링 · SKILL.md

music

music

播放音乐、控制播放。当用户想听歌、播放歌曲、暂停/继续/切歌、调节音量、单曲循环等音乐相关操作时触发。支持 B站、mail.ru、SoundCloud 等多音源播放,使用 mpv 播放。适配 opencode、codex、OpenClaw、Cursor、Gemini 等智能体编码助手。

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill 문서

GitHub

name: music description: "播放音乐、控制播放。当用户想听歌、播放歌曲、暂停/继续/切歌、调节音量、单曲循环等音乐相关操作时触发。支持 B站、mail.ru、SoundCloud 等多音源播放,使用 mpv 播放。适配 opencode、codex、OpenClaw、Cursor、Gemini 等智能体编码助手。" license: MIT

Music Player Skill

在线音乐播放和播放控制技能。模型直接调用 yt-dlp 和 mpv CLI,music.mjs 负责播放控制(IPC)与 B站搜索(search-bili)。多音源(B站 / mail.ru / SoundCloud)按固定 fallback 顺序播放,YouTube 预留插槽。

支持平台:Git Bash (Windows)、Linux、macOS。不支持 PowerShell。

依赖检查(首次使用)

在首次使用前,在终端尝试运行以下命令。如果提示"找不到命令",则说明未安装:

node --version
yt-dlp --version
mpv --version

如果缺少依赖,提示用户安装:

意图识别与处理

意图判断依据处理流程
明确搜索含歌曲名、艺人、心情、场景、曲风等清洗输入 → 多态接口(搜索 → 选择 → 播放)
需要澄清只说"放点歌""来首音乐",没有具体偏好先问 1-2 个问题
播放控制暂停、继续、下一首、音量等调用 music.mjs

澄清优先级:先问心情或场景 → 再问偏中文还是英文 → 不问播放器、脚本等技术细节。

推荐澄清句:想听什么心情或场景的?偏中文还是英文?

输入清洗

搜索前,模型先将用户输入清洗并构造为干净的搜索词:去除命令词(播放/play/来点等)、标点和多余空格,必要时补全艺人信息。

多态接口契约(核心)

架构

flowchart LR
  subgraph 契约层["契约层 SKILL.md"]
    A1["统一 3 步接口<br/>search / select / play"]
    A2["Fallback 链<br/>B站 → mail.ru → SoundCloud"]
    A3["统一播放参数<br/>--no-video / --ytdl-format=bestaudio<br/>+ 模型自生成 UA + Referer"]
  end
  subgraph 实现层["实现层 sources/*.md"]
    B1["bilibili.md"]
    B2["mailru.md"]
    B3["soundcloud.md"]
    B4["youtube.md"]
  end
  subgraph 控制层["控制层 music.mjs"]
    C1["IPC 播放控制 + status 结构化判定"]
    C2["search-bili 子命令(/all/v2 免 412 搜索)"]
  end
  模型 --> 契约层
  模型 --> 实现层
  控制层 --> mpv
  契约层 -.约束.-> 实现层

三层结构:契约层(SKILL.md,统一接口与参数)→ 实现层(sources/*.md,每音源一个适配文件)→ 控制层(music.mjs,IPC 控制、status 结构化判定、search-bili 搜索)。

统一接口定义

每个音源实现同一套 3 步接口,参数/返回由契约统一:

  1. search(keyword):给定清洗后的关键词,返回候选列表(含 id / 标题 / 时长 / 播放定位;B站返回 bvid,其余返回 URL)。
  2. select(candidates):选择最佳候选(标题匹配 + 时长 120-420s + 优先原唱/官方版本)。
  3. play(playUrl):music.mjs stop → 启动 mpv(统一参数固定)→ sleep 5 后 music.mjs status 验证存活。

Fallback 链(固定顺序)

B站 → mail.ru → SoundCloud → YouTube
  └ 失败则降级下一源(无结果 / yt-dlp 报错 / mpv 启动后退出)
全失败 → 按下方「回复要求」播放失败规则回复

多态执行规则

  • 模型必须先 read sources/<音源>.md 读取对应实现,再按其模板执行;不得跨文件混用命令。
  • 每个音源独立完成「搜索 → 选择 → 播放 → 验证」四步,失败才降级下一源。

统一播放参数(契约固定,所有音源无条件添加)

本技能定位是听歌(非看视频),以下参数对所有音源无条件固定加,与音源无关:

参数作用
--no-video只播放音频,不渲染视频画面
--ytdl-format=bestaudio优先选最佳音质音频流(mail.ru 直链不经 yt-dlp,参数被忽略,无害)
--input-ipc-server=<pipe>IPC 控制必需(music.mjs 依赖)

各音源实现文件(sources/*.md)的 play 模板里不再重复列这三个参数,只写差异化参数。

防风控统一参数(所有音源一律携带)

  • 随机 UA:模型每次执行 read reference/ua-spec.md 读取生成规范,按份额权重 + 模板现场生成随机桌面 UA,加在每次 search(B站 search-bili / 其余 yt-dlp)和 mpv 播放命令中。不使用硬编码 UA 池,不依赖 npm 包。
  • Referer 统一必加:
音源Referer传参位置
B站https://www.bilibili.com/mpv --ytdl-raw-options=add-header=Referer:...(经 yt-dlp)
SoundCloudhttps://soundcloud.com/mpv --ytdl-raw-options=add-header=Referer:...(经 yt-dlp)
mail.ruhttps://my.mail.ru/mpv --http-header-fields="Referer: https://my.mail.ru/"(直链不经 yt-dlp)
YouTubehttps://www.youtube.com/mpv --ytdl-raw-options=add-header=Referer:...(经 yt-dlp)

参数分层总结:--no-video --ytdl-format=bestaudio --input-ipc-server + 随机 UA + 对应 Referer = 契约统一固定;各源实现文件只写「搜索命令 + 播放 URL + 差异化边界」。

随机 UA 生成

每次搜索/播放前,先 read reference/ua-spec.md 读取生成规范,按其份额权重 + 模板 + 版本范围生成随机桌面 UA,拼入 search(B站 search-bili / 其余 yt-dlp)与 mpv 命令。同一首歌的搜索与播放复用同一 UA。

播放验证机制(结构化 status)

mpv 启动后 sleep 5,调用 node <skill-dir>/scripts/dist/music.mjs status,解析结构化 JSON。单一 state 字段,值域固定 4 态,无冗余:

state含义判定
playing播放中(存活)✅ 成功
paused已暂停(存活)✅ 成功
stopped未运行❌ 失败,fallback
errorIPC/内部异常❌ 失败,fallback

播放中 / 已暂停(mpv 存活):

{ "state": "playing", "pid": 25116, "title": "心之火", "duration": 293, "position": 12.3, "volume": 80 }
{ "state": "paused", "pid": 25116, "title": "心之火", "duration": 293, "position": 45.1, "volume": 80 }

未运行:

{ "state": "stopped" }

异常:

{ "state": "error", "code": "IPC_TIMEOUT", "message": "..." }

判定规则(只判一个字段,无歧义):

  • state === "playing" 或 state === "paused" → 播放成功,回复用户
  • state === "stopped" → 判定失败,fallback 下一源
  • state === "error" → 判定失败(异常),fallback 下一源

播放时序

sequenceDiagram
  participant M as 模型(Agent)
  participant Y as yt-dlp
  participant MS as music.mjs
  participant MPV as mpv
  M->>M: read sources/音源实现.md
  M->>M: read reference/ua-spec.md 生成 UA
  M->>MS: search(B站走 search-bili,其余走 yt-dlp)
  MS-->>M: 候选列表(bvid/title/duration/play)
  M->>M: select 最佳候选
  M->>MS: stop(停止旧播放)
  M->>MPV: 启动 mpv(统一参数 + 差异参数 + UA)
  M->>M: sleep 5
  M->>MS: status
  MS-->>M: state 字段(playing/paused 或 stopped/error)
  alt 存活
    M->>M: 回复播放成功
  else 失败
    M->>M: 降级下一音源
  end

各音源实现

每个音源一个实现文件,播放命令由「契约统一参数 + 各源差异化参数」拼接而成:

  • sources/bilibili.md — B站(中文曲极全;搜索走 music.mjs search-bili /all/v2 免 412)
  • sources/mailru.md — mail.ru(英文曲直链)
  • sources/soundcloud.md — SoundCloud(独立音乐/翻唱)
  • sources/youtube.md — YouTube(默认无 cookie,英文曲极全)
  • reference/ua-spec.md — 随机桌面 UA 生成规范(所有音源通用)

执行流程:先 read 上方 SKILL.md 契约取统一参数,再 read sources/<音源>.md 取差异化参数,拼接成完整命令。

音源支持度参考(帮助判断候选匹配度):

音源中文曲英文曲风控级别
B站极全(华语流行/OST/翻唱)少(官方MV/搬运)低(搜索走 search-bili /all/v2 免 412;播放需 UA+Referer)
mail.ru几乎无有一些(欧美主流歌手)低(无需登录,直链即得)
SoundCloud很少好(独立音乐人/翻唱/remix)中(需完整 URL,偶发 DRM)
YouTube好极全中-高(搜索无 cookie;播放偶发 bot 检测)

播放控制

所有控制命令通过 music.mjs 调用(播放命令详见 sources/ 下对应音源文件):

node <skill-dir>/scripts/dist/music.mjs <command>
用户输入命令说明
播放 歌曲名、play 歌曲名、我想听 歌曲名-清洗 → 多态接口(搜索 → 选择 → 播放)
暂停、pausepause暂停播放
继续播放、resumeresume恢复播放
下一首、nextnext下一首
上一首、prevprev上一首
声音大一点、volume upvolume-up音量 +10
声音小一点、volume downvolume-down音量 -10
静音、mutemute切换静音
单曲循环、looploop开启单曲循环
关闭循环、loop-offloop-off关闭单曲循环
退出音乐、停止播放、stopstop停止播放并退出
播放状态、statusstatus查看播放状态(结构化 JSON)

输出格式:控制命令输出 JSON;status 输出结构化 JSON(见「播放验证机制」)。

{ "status": "success", "action": "pause" }
{ "state": "stopped" }
{ "error": "mpv not running" }

回复要求(必须)

  1. 播放状态

    • 播放成功:转述歌曲信息(正在播放:Numb - Linkin Park)+ 1 段 2-4 句歌曲简介
    • 播放失败(全部音源失败):告知 未找到匹配的歌曲,建议 可以尝试更具体的歌曲名或艺人名
  2. 推荐歌曲(仅播放成功时;优先利用模型自身知识库,信息不足时可联网搜索补充)

    • 两组分组,组标题用三级标题 ### 更多<歌手名> / ### 同风格推荐,每组 5 首,编号连续 1-10
    • 每组歌曲用行内紧凑格式横向排列(一行内 1. 歌名 2. 歌名 3. 歌名 4. 歌名 5. 歌名,两空格分隔)
    • 列表后引导序号点播:想听哪首?回复 **序号** 或 **歌名** 即可切换
  3. 引导播放控制:告知用户可直接回复以下指令控制播放:暂停、继续播放、停止播放、单曲循环

저장한 Skills