multi-scrobbler 0.13.3 配置参数详解
multi-scrobbler 0.13.3 三种配置方式与全部核心参数语义、密钥插值机制、生产配置模板,逐项实测。
multi-scrobbler 0.13.3 配置参数详解
目标:系统性讲清 multi-scrobbler 0.13.3 的三种配置方式(ENV / 分文件 JSON / AIO 全量 JSON)、全部核心参数的语义与默认值、密钥不落盘的插值机制,并给出可直接套用的生产配置模板。已在 Ubuntu 22.04 / Docker Engine 29.9.2 环境以「VLC 轮询源 → Maloja 目标」最小闭环逐项实测,端到端 scrobble 与阈值行为均以真实回显为准。
一、环境信息
- 服务器系统:Ubuntu 22.04(x86_64),Docker Engine 29.9.2 / Compose v5.6.1
- multi-scrobbler:0.13.3(官方镜像
foxxmd/multi-scrobbler:0.13.3;镜像内运行时为 Node.js,package.json声明engines.node >= 24.14.0、许可证 MIT,镜像内实查) - 验证用目标:Maloja 3.2.4(
krateng/maloja:3.2.4,本地统计目标,API 密钥q1w2e3r4) - 验证用源:VLC 3.0.16 Vetinari(HTTP 接口轮询源,接口口令
q1w2e3r4) - 配置目录:
/opt/multi-scrobbler/config/(服务内/config) - 仪表盘端口:宿主
8147→ 服务内9078 - 查询日期:2026-10-29(官方参数语义按当日官方文档站核定)
💡 说明:本文的 VLC/Maloja 是验证参数行为的「源/目标」载体;生产中换成 Jellyfin、Navidrome、last.fm 等,参数体系完全一致。部署过程见《multi-scrobbler Docker Compose 部署指南》,此处直接在既有栈上操作。
二、前置条件
- 已完成《multi-scrobbler Docker Compose 部署指南》第四章部署,服务处于运行状态,健康接口返回正常:
curl -s http://127.0.0.1:8147/api/health
# 实测输出:
# {"messages":[]}
- 配置目录中已有 AIO 配置文件(无配置时服务也能启动,仅仪表盘无源/目标数据):
ls -la /opt/multi-scrobbler/config/
# 实测输出:
# -rw-r--r-- 1 911 911 610 Oct 29 22:24 config.json
# -rw-r--r-- 1 911 911 159 Oct 29 22:53 ms-scrobble.cache
- 验证用播放源已就绪(VLC HTTP 接口 8080 在栈内可达,部署指南 4.6 步骤)。
三、参数查看与修改方式
multi-scrobbler 同一套源/目标配置有三种写法,服务启动时三种同时解析、可混用(官方配置总览 Configuration Types,2026-10-29 查询),但建议统一用一种:
| 方式 | 载体 | 适用场景(官方建议) |
|---|---|---|
| ENV 环境变量 | compose environment: 或系统环境 | 单用户、一个源对一个目标的极简场景;不习惯编辑 JSON |
| 分文件 JSON | CONFIG_DIR 下按类型命名的文件(如 jellyfin.json、maloja.json),文件内是数组 | 同类型多实例(如 2 个 last.fm 账号、3 台 Jellyfin)、需要源→目标定向转发 |
| AIO 全量 JSON | CONFIG_DIR/config.json | 完整配置能力:监控通知、源/目标默认值、变换器、全局选项;AIO 是「最完整」的方式(官方原话) |
两种 JSON 形态的差异只在一点:AIO 中每个源/目标项必须带 type 字段(分文件的 type 由文件名隐含)。本文以 AIO 为主线讲解,其余两种在对应小节给出换算方式。
修改参数的标准流程(每步实测):
# 1. 编辑配置
vi /opt/multi-scrobbler/config/config.json
# 2. 重启服务使配置生效
docker compose -f /opt/multi-scrobbler/docker-compose.yml restart multi-scrobbler
# 实测输出:
# Container multi-scrobbler-0-13-3-app Restarting
# Container multi-scrobbler-0-13-3-app Started
# 3. 看日志确认加载结果
docker compose -f /opt/multi-scrobbler/docker-compose.yml logs --since 1m multi-scrobbler 2>&1 | grep -E 'Added|Initialized|Error'
# 实测输出(节选):
# multi-scrobbler-0-13-3-app | [2026-10-29 23:54:53.496 +0800] INFO : [App] [Scrobblers] [Maloja - labMaloja] Client Added from config.json
# multi-scrobbler-0-13-3-app | [2026-10-29 23:54:53.593 +0800] INFO : [App] [Sources] [Vlc - Lab VLC] Source Added from config.json
# multi-scrobbler-0-13-3-app | [2026-10-29 23:54:55.621 +0800] INFO : [App] [Sources] [Vlc - Lab VLC] Connected successfully, found VLC 3.0.16 Vetinari
Client/Source Added from config.json 即 AIO 配置加载生效的标志;若 JSON 语法有误,启动日志会直接抛出解析错误并指明行号,修正后重启即可。官方还提供 Config Playground(https://foxxmd.github.io/multi-scrobbler/playground/,官方文档站)可在网页上交互式探索完整配置模式。
四、参数总览
AIO 配置(config.json)顶层键一览(语义按官方文档核定,默认值来自官方 AIO 示例与镜像内源码实查):
| 顶层键 | 类型 | 默认值 | 作用 |
|---|---|---|---|
debugMode | 布尔 | false | 全局调试模式,输出更详细日志 |
disableWeb | 布尔 | false | 关闭 Web 仪表盘与 API(仅纯后台搬运时使用) |
baseUrl | 字符串 | http://localhost:9078 | 对外地址,用于生成 OAuth 回调 URL(ENV BASE_URL 同义) |
sourceDefaults | 对象 | 见 5.2 | 所有源的默认行为与阈值 |
clientDefaults | 对象 | 见 5.2 | 所有目标的默认重试行为 |
sources | 数组 | [] | 源实例列表 |
clients | 数组 | [] | 目标实例列表 |
webhooks | 数组 | [] | 通知推送(Gotify/ntfy) |
cache | 对象 | 内置默认 | 缓存存储位置(auth/valkey) |
环境变量侧的常设变量(Docker 形态):
| 变量 | 默认值 | 作用 |
|---|---|---|
TZ | Etc/GMT | 时区 |
PORT | 9078 | 仪表盘/API 端口 |
BASE_URL | http://localhost:9078 | 同 baseUrl |
PUID / PGID | 911 / 911 | 运行用户/组 |
CONFIG_DIR / DATA_DIR / LOGS_DIR | Docker 内自动设定 | 配置/数据/日志目录 |
CACHE_VALKEY | 未启用 | Valkey 二级缓存连接串 |
CACHE_AUTH | file | 认证缓存存储(file 或 valkey) |
SOURCE_SCROBBLE_DURATION / SOURCE_SCROBBLE_PERCENT | 无 | 以 ENV 覆盖全局 scrobble 阈值(镜像内源码实查:ScrobbleSources.ts 读取这两个变量并输出 Set default scrobble threshold ... based on env 日志) |
💡 技术拓展:配置里的「源(Source)」与「目标(Client)」是 multi-scrobbler 的两个对偶概念——源是播放记录的生产者(轮询 API 或接收 Webhook),目标是消费者(提交 scrobble 的统计服务)。一个源可经
clients字段定向转发给一个或多个目标;不指定时转发给全部目标。这与 last.fm 系统计服务里被动接收记录的「scrobbler 插件」不是同一层东西,选型辨析见《multi-scrobbler 介绍与选型指南》。
五、核心参数分类详解
5.1 全局开关(debugMode / disableWeb / baseUrl / PORT)
debugMode: false:排障时可临时改true,日志会输出每个播放的完整载荷与判定过程;生产保持false;disableWeb: false:仪表盘与 API 是状态查看的主要入口(官方 API 见《multi-scrobbler 0.13.3 API 使用详解》),一般不关;关闭后只能靠日志与目标侧核对;baseUrl/BASE_URL:影响的是回调地址的生成而非监听端口——Spotify、last.fm 等 OAuth 类配置若未显式写redirectUri,回调将拼成BASE_URL:PORT/<client|source>/callback(官方 Base URL 章节的拼装规则表)。反代子路径部署时必须以 ENV 形式设置(官方要求);PORT:仪表盘/API 监听端口(官方文档:The web UI and API is served on port 9078. This can be modified using the PORT environmental variable.)。本文实测保持 9078、宿主映射 8147。
5.2 源/目标默认值(sourceDefaults / clientDefaults)
官方 AIO 示例的完整默认集(默认值即官方示例值):
{
"sourceDefaults": {
"logPayload": false,
"logFilterFailure": "warn",
"logPlayerState": false,
"scrobbleThresholds": {
"duration": 30,
"percent": 50
},
"maxPollRetries": 1,
"maxRequestRetries": 1,
"retryMultiplier": 1.5
},
"clientDefaults": {
"maxRequestRetries": 1,
"retryMultiplier": 1.5
}
}
逐项说明:
logPayload:把源返回的原始载荷写进日志(排障元数据错乱时开);logFilterFailure:播放未达阈值/被过滤时的日志级别(warn时可在日志看到每次被过滤的原因);logPlayerState:轮询源每次查询的播放器状态落日志(调试轮询链路用);scrobbleThresholds.duration/.percent:记账双阈值——播放时长满duration秒且进度满percent% 才产生 scrobble(本文实测:150 秒曲目在约 75 秒处触发,恰为 50% 进度点,见 5.8 回显);两者都调大可有效过滤「切歌试听」;maxPollRetries/maxRequestRetries:轮询失败与请求失败的即时重试次数;retryMultiplier:重试间隔倍率(指数退避系数)。
ENV 覆盖方式(镜像内源码实查,/app/src/backend/sources/ScrobbleSources.ts):
# compose environment 中加入后,日志会输出:
# Set default scrobble threshold duration to '60' based on env SOURCE_SCROBBLE_DURATION
SOURCE_SCROBBLE_DURATION=60
SOURCE_SCROBBLE_PERCENT=60
5.3 源配置(sources[])
每个源实例的骨架(本文实测使用的 VLC 源):
{
"type": "vlc",
"enable": true,
"name": "Lab VLC",
"id": "vlc-lab",
"clients": ["labMaloja"],
"data": {
"url": "vlc:8080",
"password": "q1w2e3r4"
}
}
逐项说明:
type:源类型标识(AIO 必填;分文件 JSON 用作文件名,如vlc.json)。常用取值:jellyfin、subsonic(Navidrome/Airsonic 兼容)、plex/tautulli、mopidy、mpris、vlc、spotify、deezer、ytmusic、lastfm、listenbrainz、webscrobbler等(官方 Sources 总览);enable:临时停用某源改false即可,不必删配置;name:实例显示名(日志与仪表盘用它标识,如[Vlc - Lab VLC]);id:强烈建议显式设置——数据库按 id 关联播放记录,配置改名后数据不丢账(官方 Database 章节要求);clients:定向转发,值是目标的name数组;实测该源 scrobble 只进了labMaloja(Maloja API 查询回显见 5.8);省略则转发给所有目标;data:类型专属参数。VLC 源为url(主机:端口,栈内可用服务名)+password(VLC HTTP 接口口令);Jellyfin 源为url/user/apiKey(服务器后台生成 API Key);Subsonic 系为url/user/password(或 API Token)。
💡 技术拓展:Jellyfin/Subsonic 系源支持「轮询」与「Webhook 推送」两种接入方式——轮询由 multi-scrobbler 定期拉会话/最近播放(配置简单,秒级延迟);Webhook 由媒体服务器主动回调(实时性最好,但需媒体服务器可达本服务)。按官方各源配置页在
data中选择 endpoint 类型即可,本文验证用的 VLC 属纯轮询源。
5.4 目标配置(clients[])
每个目标实例的骨架(本文实测使用的 Maloja 目标):
{
"type": "maloja",
"enable": true,
"name": "labMaloja",
"id": "maloja-lab",
"data": {
"url": "http://maloja:42010",
"apiKey": "q1w2e3r4"
}
}
type常用取值:lastfm、listenbrainz、maloja、koito(官方 Clients 总览);data按类型而异:Maloja 为url+apiKey;ListenBrainz 为url(默认官方地址)+ 用户 Token;Koito 为url+ API Key(在其仪表盘 Settings → API Keys 创建,官方 Quickstart 说明);last.fm 需要 API Key + Secret + OAuth 授权回调;- 连通性验证不靠手工 curl:服务启动时自动做「通信测试 + 认证测试」,实测回显:
[2026-10-29 22:47:06.671 +0800] INFO : [App] [Scrobblers] [Maloja - labMaloja] [API] [API - Maloja - labMaloja] Communication test succeeded.
[2026-10-29 22:47:06.677 +0800] INFO : [App] [Scrobblers] [Maloja - labMaloja] [API] [API - Maloja - labMaloja] Maloja Server Version: 3.2.4
[2026-10-29 22:47:06.677 +0800] INFO : [App] [Scrobblers] [Maloja - labMaloja] [API] [API - Maloja - labMaloja] Auth test passed!
[2026-10-29 22:47:06.677 +0800] INFO : [App] [Scrobblers] [Maloja - labMaloja] Fully Initialized!
⚠️ 注意:last.fm / ListenBrainz 的凭据需要在其官方平台注册申请(last.fm:创建 API 账户页申请
api key/shared secret;ListenBrainz:用户设置页生成 User Token),本文无法代读者注册,下文生产模板中以${LASTFM_API_KEY}、${LISTENBRAINZ_TOKEN}占位并给出注入方式。Maloja/Koito 这类自托管目标的密钥由读者自己掌控(本文演示值q1w2e3r4)。
5.5 密钥插值([[ENV]],密钥不落盘)
JSON 配置支持把环境变量插进任意字符串值:写作 [[ENV_NAME]],服务启动时替换为同名环境变量的值(官方配置总览 Secrets Interpolation 章节,本节机制说明以官方文档为准)。要点:
- 插值键不区分大小写;只对字符串值生效;
- 环境变量缺失不报错:原样保留字符串并输出
WARN(官方示例日志格式:WARN : [App] [Sources] [spotify Secrets] Matched: None | Unmatched: SPOTIFY_SECRET); - 典型用法(官方示例结构)——
lastfm.json中写"apiKey": "[[MY_APIKEY]]",compose 的environment中注入MY_APIKEY=<真实值>,配置文件即可安全入库 git; - 注入方式:compose
environment: - MY_APIKEY=${MY_APIKEY},在宿主.env文件(compose 同目录,git 忽略)中落真实值,执行docker compose up -d时自动带入。
5.6 通知 Webhook(webhooks[])
scrobble 结果可推送到 Gotify / ntfy(官方 AIO 示例结构):
{
"webhooks": [
{
"name": "FirstGotifyServer",
"type": "gotify",
"url": "http://localhost:8070",
"token": "MyGotifyToken",
"priorities": { "info": 5, "warn": 7, "error": 10 }
},
{
"type": "ntfy",
"name": "MyNtfyFriendlyNameForLogs",
"url": "http://localhost:9991",
"topic": "MyMultiScrobblerTopic",
"username": "Optional",
"password": "Optional",
"priorities": { "info": 3, "warn": 4, "error": 5 }
}
]
}
priorities按 info/warn/error 三级映射到 Gotify/ntfy 的优先级数值;url指向自建通知服务地址;token(Gotify)/topic(ntfy)为必填,账号口令可选。本文验证栈未部署通知服务,参数语义按官方 AIO 示例核定。
5.7 缓存与二级缓存(cache / CACHE_VALKEY)
- 认证缓存默认落
DATA_DIR下的ms-auth.cache文件(本文实测配置目录中的ms-scrobble.cache即缓存文件,159 字节,首次 scrobble 后自动生成),重启不丢凭据; - 二级缓存:配置
CACHE_VALKEY=redis://valkey:6379后启用,官方说明收益为「跨重启持久化、更大容量、更长 TTL」,配合 MusicBrainz 变换器时强烈建议开启;官方给出的配套 Valkey 服务片段:
services:
valkey:
image: valkey/valkey
volumes:
- valkeydata:/data
volumes:
valkeydata:
driver: local
- 认证缓存如需也走 Valkey,显式设置
CACHE_AUTH=valkey(官方:因 Valkey 可能无卷易失,默认不把认证放进二级缓存)。
5.8 阈值行为实测(scrobbleThresholds 验证)
用 150 秒测试曲目验证默认阈值(30 秒 + 50%)的判定行为。multi-scrobbler 侧日志(实测):
[2026-10-29 22:48:22.745 +0800] INFO : [App] [Scrobblers] [Maloja - labMaloja] Scrobbled (Backlog) => (vlc) Lab Ensemble - Neon Skyline @ 2026-10-29T22:47:08+08:00 (S)
播放开始于 22:47:08,scrobble 触发于 22:48:22(约 74 秒后),恰为 50% 进度点——时长阈值(≥30 秒)早已满足,进度阈值(≥50%)成为触发条件,证明两阈值需同时满足。目标侧 Maloja 入库回显(实测):
curl -s -H 'Authorization: TOKEN q1w2e3r4' 'http://127.0.0.1:8148/apis/mlj_1/scrobbles?max=5'
# {"status": "ok", "list": [{"time": 1793285228, "track": {"artists": ["Lab Ensemble"], "title": "Neon Skyline", "album": {"artists": ["Lab Ensemble"], "albumtitle": "Test Sessions"}, "length": 150}, "duration": 75, "origin": "client:default"}], "pagination": {"page": 0, "perpage": 5, "next_page": null, "prev_page": null}}
length: 150 与曲目时长一致、duration: 75 与触发点一致,元数据(曲名/艺人/专辑)来自 ID3 标签透传。同时 /api/status 中该源播放对象记录了完整的监听区间(实测节选):listenedFor: 141、listenRanges 起止时间戳、mediaPlayerVersion: 3.0.16 Vetinari——排障时可据此核对每个播放的判定过程。
5.9 数据库与 ID 稳定性(ms.db / id)
- SQLite 数据库
ms.db首次产生数据后生成于配置目录,存储全部播放、元数据与调试信息;每个播放按「源/目标配置 + id」关联入库(官方 Database 章节); - 官方明确要求:必须为每个源/目标设置
id,否则配置项改名后数据库无法续接同一实例的记录; - 保留量级:每条播放的体积随源暴露的字段、目标数量(每多一个目标多一份记录)而变,个人规模年数据量通常在几十 MB 量级(官方 Retention 说明;本文验证栈实测
ms-scrobble.cache159 字节、Maloja 侧数据库 60KB 量级,均为小库);版本升级涉及库结构变更时官方自动备份迁移(官方 Updating 文档)。
六、生产配置模板
适用场景:家庭 NAS / 小型媒体服务器(8~16GB 内存、SSD,Jellyfin 或 Navidrome 为主要音源),目标为 last.fm + ListenBrainz 双记账并保留本地 Maloja 备份。内存占用预期:multi-scrobbler 为 Node 常驻服务,数百 MB 量级即可承载家庭规模轮询负载。
/opt/multi-scrobbler/config/config.json(密钥占位规则:第三方平台密钥一律走 [[ENV]] 插值,真实值放 compose 同目录 .env 文件;自托管目标演示值可直接替换):
{
"debugMode": false,
"disableWeb": false,
"sourceDefaults": {
"logFilterFailure": "warn",
"scrobbleThresholds": {
"duration": 30,
"percent": 50
},
"maxRequestRetries": 2,
"retryMultiplier": 2
},
"clientDefaults": {
"maxRequestRetries": 2,
"retryMultiplier": 2
},
"sources": [
{
"type": "jellyfin",
"enable": true,
"name": "Home Jellyfin",
"id": "jf-home",
"clients": ["lfm", "lbrnz", "malHome"],
"data": {
"url": "http://192.168.1.10:8096",
"user": "musicfan",
"apiKey": "[[JELLYFIN_APIKEY]]"
}
},
{
"type": "subsonic",
"enable": true,
"name": "Home Navidrome",
"id": "nd-home",
"clients": ["lfm", "lbrnz", "malHome"],
"data": {
"url": "http://192.168.1.10:4533",
"user": "musicfan",
"password": "[[NAVIDROME_PASSWORD]]"
}
}
],
"clients": [
{
"type": "lastfm",
"enable": true,
"name": "lfm",
"id": "lfm-home",
"data": {
"apiKey": "[[LASTFM_API_KEY]]",
"secret": "[[LASTFM_SHARED_SECRET]]"
}
},
{
"type": "listenbrainz",
"enable": true,
"name": "lbrnz",
"id": "lbrnz-home",
"data": {
"url": "https://api.listenbrainz.org",
"token": "[[LISTENBRAINZ_TOKEN]]"
}
},
{
"type": "maloja",
"enable": true,
"name": "malHome",
"id": "mal-home",
"data": {
"url": "http://maloja:42010",
"apiKey": "q1w2e3r4"
}
}
],
"webhooks": [
{
"type": "ntfy",
"name": "ScrobbleNotify",
"url": "http://192.168.1.10:9991",
"topic": "scrobble-alerts",
"priorities": { "info": 3, "warn": 4, "error": 5 }
}
]
}
配套 .env(与 docker-compose.yml 同目录,权限 600,不提交 git):
JELLYFIN_APIKEY=在 Jellyfin 控制台「API 密钥」页生成
NAVIDROME_PASSWORD=该用户在 Navidrome 的密码
LASTFM_API_KEY=在 last.fm 创建 API 账户页申请
LASTFM_SHARED_SECRET=同上页一并签发
LISTENBRAINZ_TOKEN=在 ListenBrainz 用户设置页生成
配套 compose 环境变量(把 .env 值透传进服务,供 [[ENV]] 插值):
environment:
- TZ=Asia/Shanghai
- JELLYFIN_APIKEY=${JELLYFIN_APIKEY}
- NAVIDROME_PASSWORD=${NAVIDROME_PASSWORD}
- LASTFM_API_KEY=${LASTFM_API_KEY}
- LASTFM_SHARED_SECRET=${LASTFM_SHARED_SECRET}
- LISTENBRAINZ_TOKEN=${LISTENBRAINZ_TOKEN}
模板要点:三个目标共用两个源(clients 数组定向);maxRequestRetries/retryMultiplier 较默认值放宽以容忍外网抖动;last.fm OAuth 首次授权需在仪表盘点击登录并回调(回调地址 = BASE_URL/lastfm/callback,BASE_URL 设为访问仪表盘的地址);自托管 Maloja 密钥 q1w2e3r4 为演示值,生产替换为强随机串。
七、常见问题
Q1:改了 config.json 不生效?
配置在启动时解析,修改后需 docker compose -f /opt/multi-scrobbler/docker-compose.yml restart multi-scrobbler;再用 docker compose logs --since 1m multi-scrobbler 确认出现对应的 Added from config.json。若日志报 JSON 解析错误,多为多写/漏写逗号,按指明行号修正。
Q2:日志出现 WARN ... Secrets Matched: None | Unmatched: XXX?
[[XXX]] 引用的环境变量没有注入到服务进程。检查 compose environment 是否透传、.env 文件是否在 compose 同目录、变量名拼写是否与插值键一致(大小写不敏感)。未修复前该字段保留 [[XXX]] 原文,认证测试会失败。
Q3:同一首歌重复入库?
确认源的 id 是否设置且稳定——同一逻辑源改名/重建后又没有固定 id,数据库会当成新实例重新记账;另 0.13.x 已内置重复 scrobble 检测(官方版本说明),若仍复现多为两个源实例覆盖了同一播放场景,梳理 clients 定向关系即可。
Q4:Maloja 目标报认证失败?
核对 data.apiKey 与 Maloja 密钥文件 maloja-data/config/apikeys.yml 中的值一致(层级易错,见部署指南 Q5);multi-scrobbler 启动日志的 Auth test passed!/Auth test failed 是最直接的判据。
Q5:想按天/按播放时长过滤(只记整曲)?
调大 scrobbleThresholds:如 duration: 60、percent: 80; ENV 也可用 SOURCE_SCROBBLE_DURATION/SOURCE_SCROBBLE_PERCENT 全局覆盖(见 5.2 源码实查依据)。
八、参考链接
- 配置总览(Configuration Types / Secrets Interpolation / Caching / Database):https://foxxmd.github.io/multi-scrobbler/configuration/
- 配置模式 playground:https://foxxmd.github.io/multi-scrobbler/playground/
- Sources 总览:https://foxxmd.github.io/multi-scrobbler/configuration/sources/
- Clients 总览:https://foxxmd.github.io/multi-scrobbler/configuration/clients/
- GitHub 仓库配置示例目录:https://github.com/FoxxMD/multi-scrobbler/tree/master/config
- 本专栏相关:《multi-scrobbler 介绍与选型指南》《multi-scrobbler Docker Compose 部署指南》《multi-scrobbler 0.13.3 API 使用详解》