// Data Types

数据结构

插件返回的 JSON 会被反序列化为 mio-music-sdk 里的 Rust 类型。字段名与类型必须对得上,否则整次调用会失败。本页列出每一种结构。

先记住这三条

下面表格的「必填」列表示:缺少该字段时反序列化是否失败。「可选」字段缺失时取默认值(空串、null 或 0)。

MusicItem(歌曲)

歌曲在列表里出现、被收藏、加入歌单、下载,最后又作为 song 参数传回你的 musicUrl / lyrics 等方法,都是这个结构。所有字段都是可选的,但实际上请至少填写前面几项。

字段类型说明
songmidstring | number歌曲在来源里的唯一 ID。建议用字符串。
namestring歌名。
singerstring歌手名,多个歌手自行拼接。
albumNamestring专辑名。
albumIdstring | number专辑 ID,之后可用于 albumDetail。
singerIdstring歌手 ID,用于跳转到歌手页。
sourcestring来源 ID。宿主会改写成本次调用的来源,但仍建议填写。
intervalstring时长,格式 mm:ss(或 hh:mm:ss)。
imgstring封面 URL,没有则空串。
typesstring[]这首歌可用的音质名称(128k、320k、flac …),由差到好。
_typesobject各音质的补充信息:{ "320k": { size: "9.8MB", hash?: "…" } }。size 是字符串。
typeUrlobject私有数据的容器,见下文。
lrcstring | null已经附带的歌词文本,通常为 null。
hash、songId、strMediaMid、albumMid、copyrightId、lrcUrl、mrcUrl、trcUrl各异原版若干来源用到的额外字段,自建来源一般不需要。

字符串类型的字段(name、singer、albumName、interval、img 等)如果传了数字,整个结果都会被拒绝。服务器返回数字的时候,用 String(v) 转换一下。

私有数据放在哪里

歌曲会被缓存、写入收藏与歌单、交给下载器,再在播放时传回你的方法。这个过程通过 MusicItem 结构往返,所以结构里没有的字段会丢失——你自己加的 serverPath、token 之类的顶层字段,到 musicUrl 时已经不在了。两个办法:

function toSong(v) {
  return {
    songmid: String(v.id),
    name: String(v.title || ''),
    singer: String(v.artist || ''),
    albumName: String(v.album || ''),
    source: 'myid',
    interval: mmss(Math.trunc(v.duration) || 0),
    img: coverUrl(v),
    types: ['128k', '320k'],
    typeUrl: { path: v.path },   // 私有数据:播放时从 song.typeUrl.path 读回
  };
}

SearchResult

search、singerSongs 的返回值。

字段类型必填说明
listMusicItem[]是本页歌曲。
allPageinteger是总页数。
limitinteger是本页大小,通常原样返回参数里的 limit。
totalinteger是总条数。
sourcestring是来源 ID(宿主会改写,但字段本身必须存在)。

PlaylistResult 与 PlaylistItem

searchPlaylist、getPlaylists 的返回值,以及发现页里歌单列表的元素。

PlaylistResult类型必填
listPlaylistItem[]是
allPage、limit、totalinteger是
sourcestring是
PlaylistItem类型必填说明
idstring | number是之后作为 playlistDetail 的 id 传回。
namestring是
imgstring是封面 URL,可为空串。
sourcestring是
descstring否简介。
authorstring否创建者。
playCountnumber | string | null否播放量。
totalnumber | string | null否歌曲数。

PlaylistDetail

playlistDetail、albumDetail、chartDetail 的返回值:一页歌曲,加上歌单自身的信息。

字段类型必填说明
listMusicItem[]是本页歌曲。
infoobject是{ name, img, desc, author },四项均为可选字符串,没有就给 {}。
allPage、limit、totalinteger是
sourcestring是

歌手

SingerInfo

字段类型必填
id、source、name、desc、avatarstring是
genderstring | null否
musicCount、albumCountinteger是

SingerAlbumPage

字段类型必填
listSingerAlbum[]是
allPage、limit、totalinteger是
sourcestring是

其中 SingerAlbum 为 { id, count, name, author, img, desc }:id、name、author、img 是字符串(ID 不能是数字),count 是整数,desc 是字符串或 null。id 之后会作为 albumDetail 的 id 传回。

发现页

这里的字段是 snake_case 发现页的结构沿用了原版的序列化格式:用 has_more 和 update_frequency,不是 hasMore 和 updateFrequency。写成 camelCase 会得到「字段缺失」的错误。其中嵌套的 PlaylistItem、MusicItem 仍然是 camelCase。

DiscoveryCategories(discoveryCategories)

{
  groups: [
    { name: '专辑', list: [{ id: 'newest', name: '最新添加', source }] },
  ],
  hot: [{ id: 'newest', name: '最新添加', source }],
  source,
}

groups 与 hot 都是必填;分类里的 id 是字符串,会作为 discoveryPlaylists 的 category 传回。

DiscoveryPlaylistPage(discoveryPlaylists)

字段类型必填说明
listPlaylistItem[]是
pageinteger是当前页码。
totalinteger | null否来源不提供总数时给 null,不要估算。
has_moreboolean是是否还有下一页。
sourcestring是

DiscoveryChart(discoveryCharts 的数组元素)

{ id: 'random', name: '随机歌曲', img: '', source, update_frequency: '' }

全部字段必填且都是字符串,id 最长 40 个字符,会作为 chartDetail 的 id 传回。

Lyric(歌词)

字段类型说明
lyricstring逐行 LRC 文本,每行形如 [mm:ss.xx]歌词。既没有 lyric 也没有可解析的 ttml,就视为没有歌词。
tlyricstring翻译 LRC,时间轴与 lyric 对应,没有就留空。
rlyricstring音译(罗马音)LRC,没有就留空。
crlyricstring逐字歌词文本,没有就留空。排版由 crlyricFormat 说明。
crlyricFormatstring可选,crlyric 的逐字排版。wordTagBefore(默认):[start,duration] 之后是若干 (start,duration,0)词,标签在词前;wordTagAfter:[start,duration] 之后是若干 词(start,duration),标签在词后;wordTagAfterWithProperty:行首是 [属性](0–8,表示对唱与背景声),之后同样是 词(start,duration)。时间单位都是毫秒。不符合任何一种的文本只显示逐行歌词。
sourcestring来源 ID。
ttmlstring可选。带逐字时间的 TTML 文档。提供它,歌词页就能做逐字高亮。可用 cerumusic.utils.lyric.validTtml 事先校验。

来源自己的加密、压缩或私有排版格式(例如 KRC、MRC、QRC、LYRICX)由插件自己解码成上面的通用字段;宿主不提供这些来源专用的解码,只提供 zlib 解压与字符集解码这类通用工具。

整个返回值序列化后不得超过 4 MB。服务器没有歌词时,throw new Error('没有找到歌词'),而不是返回空对象。

Comments(评论)

{
  comments: [
    {
      id: '123',               // 用于去重,必须唯一
      userName: 'Mio',
      avatar: 'https://…',
      timeStr: '2026-10-01',
      text: '好听!',
      likedCount: 42,
      images: ['https://…'],   // 可选
      reply: [ /* 同结构的回复,可选 */ ],
    },
  ],
  total: 1280,        // 总评论数
  maxPage: 43,        // 总页数
  cursor: '',         // 下一页游标,没有就空串或省略
}