// Quickstart

快速上手

写一个只有两首模拟歌曲的列表插件,把它装进应用,在搜索页里找到它并播放。整个过程只需要一个文本编辑器。

准备

第一步:写脚本

新建 hello.list.js:

/**
 * @name Hello(列表)
 * @version 1.0.0
 * @author you
 * @description 演示用的最小列表插件
 */
const SOURCE = 'hello';

const SONGS = [
  { id: '1', name: 'Hello World', singer: 'Mio', seconds: 180 },
  { id: '2', name: 'Second Song', singer: 'Mio', seconds: 205 },
];

const mmss = (s) =>
  String(Math.floor(s / 60)).padStart(2, '0') + ':' + String(s % 60).padStart(2, '0');

function toSong(v) {
  return {
    songmid: v.id,            // 歌曲在来源里的唯一 ID,之后会原样传回 musicUrl / lyrics
    name: v.name,
    singer: v.singer,
    albumName: 'Hello Album',
    albumId: 'album-1',
    source: SOURCE,
    interval: mmss(v.seconds), // 时长,格式 mm:ss
    img: '',
    types: ['128k'],           // 这首歌可用的音质
    typeUrl: {},
  };
}

async function search(_source, { keyword, page, limit }) {
  const term = keyword.toLowerCase();
  const hits = SONGS.filter((s) => (s.name + s.singer).toLowerCase().includes(term));
  return {
    list: hits.slice((page - 1) * limit, page * limit).map(toSong),
    allPage: Math.max(1, Math.ceil(hits.length / limit)),
    limit,
    total: hits.length,
    source: SOURCE,
  };
}

async function musicUrl(_source, { song, quality }) {
  const url = String((cerumusic.config || {}).audioUrl || '').trim();
  if (!url) throw new Error('请先在插件“配置”中填写测试音频地址');
  console.log('musicUrl', song.songmid, quality);
  return url;
}

async function lyrics(_source, { song }) {
  return {
    lyric: '[00:00.00]Hello\n[00:05.00]World',
    tlyric: '', rlyric: '', crlyric: '',
    source: SOURCE,
  };
}

async function testConnection() {
  return true;
}

module.exports = {
  listPlugin: {
    name: 'Hello(列表)',
    version: '1.0.0',
    author: 'you',
    description: '演示用的最小列表插件',
    config: [
      {
        key: 'audioUrl', label: '测试音频地址', type: 'text', required: true,
        placeholder: 'https://example.com/test.mp3',
        description: '所有歌曲都会播放这个地址',
      },
    ],
    defaults: { play: true },
    sources: {
      hello: {
        name: 'Hello', icon: '👋',
        capabilities: ['search', 'play', 'lyrics', 'testConnection'],
        qualities: ['128k'],
      },
    },
    search, musicUrl, lyrics, testConnection,
  },
};
几点说明

第二步:安装

  1. 打开插件页

    设置 → 插件 → 音乐列表插件。

  2. 安装列表插件

    点「安装列表插件」,选择 hello.list.js。也可以把文件放到任意可访问的地址,输入 URL 安装。

  3. 配置

    安装后点插件卡片上的「配置」,会看到刚才声明的「测试音频地址」表单,填入音频链接并保存。

  4. 测试连接

    点「测试连接」。这会调用你的 testConnection,返回 true(或 {success: true})即为成功。

第三步:使用

进入搜索页,在来源菜单中选择 Hello,搜索 hello,点击结果即可播放。因为 defaults.play 为 true,安装后「由本插件提供播放」默认是打开的,所以不需要安装音源插件。

来源菜单里找不到? 来源菜单只显示两类来源:由列表插件自己提供播放的来源,或与当前启用的音源插件共同支持的来源。只声明了 search 而没有 play、并且音源插件也不支持这个来源 ID 时,它不会出现在菜单里。

第四步:看日志

播放时,脚本里的 console.log('musicUrl', …) 会出现在插件卡片的「插件日志」里,每行以 [log] 开头。出错时,宿主也会在这里写入失败原因。把 audioUrl 清空再播放一次,就能看到「解析 hello 失败」以及你抛出的错误信息。

进阶:保存状态

因为每次调用都是全新的上下文,需要跨调用保留的东西要放进 cerumusic.storage。例如记录搜索次数:

async function search(_source, { keyword, page, limit }) {
  const count = (cerumusic.storage.get('searches') || 0) + 1;
  cerumusic.storage.set('searches', count);
  console.log('第', count, '次搜索');
  // …
}

存储是每个插件私有的键值对,值会被序列化为 JSON,整体上限 256 KiB。典型用途是缓存登录会话,避免每次调用都重新登录,参考内置的 navidrome.list.js 里的 ready() 函数。

下一步