Snapcast 0.35.0 常用 CLI 命令与工具详解
Snapcast 0.35.0 命令全解:snapserver -hh 选项表、snapclient 全参数要点、JSON-RPC 三入口实测回显(含 -32601 排障)、日志形态速查与三则排障实录。
Snapcast 0.35.0 常用 CLI 命令与工具详解
目标:备齐 Snapcast 0.35.0 日常操作的全套命令——snapserver/snapclient 全部命令行选项(真实默认值)、JSON-RPC 控制命令(含实测回显与错误示范)、日志出口与排障实录。已在 Debian 12(x86_64)实测全部命令。
一、环境信息
本文所有命令与回显均在以下实测环境采集:
- 操作系统:Debian GNU/Linux 12 (bookworm)
- 架构:x86_64
- Snapserver / Snapclient:v0.35.0 (rev f1237347),deb 安装
- 拓扑:1 台服务器(10.89.61.2)+ 2 台客户端(10.89.61.3 / 10.89.61.4),客户端 ID 实测为
86:4c:86:eb:df:d7与1e:66:50:a2:56:b7 - 端口:1704(流)/ 1705(TCP JSON-RPC)/ 1780(HTTP JSON-RPC)
- 音源:
pipe:///serverdata/snapfifo?name=SineTest(440Hz 正弦波,44100:16:2,pcm) - 实测数据日期:2026-10-30
二、工具概览
Snapcast 的日常操作面由「两个二进制 + 一个控制协议 + 日志」构成:
| 工具/入口 | 类型 | 用途 |
|---|---|---|
snapserver | 服务端二进制 | 启动流服务器;全部参数支持配置文件与命令行双轨 |
snapclient | 客户端二进制 | 接入服务器并播放;全部参数走命令行 |
| JSON-RPC 2.0 | 控制协议 | HTTP(1780)/TCP(1705)/WebSocket 三入口等价,管理分组/音量/切流 |
| Snapweb | 网页控制台 | 1780 端口内置前端,可视化等价 JSON-RPC |
| systemd 单元 | 进程托管 | snapserver.service / snapclient.service(deb 自带) |
| journald | 日志 | systemd 模式下 journalctl -u snapserver 查看日志 |
💡 说明:deb 安装的 systemd 单元实测原文——
snapserver.service的ExecStart=/usr/bin/snapserver --logging.sink=system --server.datadir=${HOME} $SNAPSERVER_OPTS(User=snapserver),snapclient.service的ExecStart=/usr/bin/snapclient --logsink=system $SNAPCLIENT_OPTS(User=snapclient)。$SNAPSERVER_OPTS/$SNAPCLIENT_OPTS来自/etc/default/snapserver、/etc/default/snapclient,是追加命令行参数的正规入口。
三、前置条件
- 服务端已安装 snapserver 并运行(
systemctl is-active snapserver→active); - 客户端已安装 snapclient;
- 版本确认(两台机器同版本,避免协议不兼容):
snapserver --version | head -1
snapclient --version | head -1
snapserver v0.35.0 (rev f1237347)
snapclient v0.35.0 (rev f1237347)
四、snapserver 命令行详解
4.1 基础选项
snapserver -h 实测输出(前 8 行):
Allowed options
-h, --help Produce help message, use -hh to show options from config file
-v, --version Show version number
-d, --daemon [=arg(=0)] Daemonize
optional process priority [-20..19]
-c, --config arg (=/etc/snapserver.conf)
Path to the configuration file
-h:只看基础选项;-hh:追加打印全部可覆盖的配置文件选项(见 4.2);-d:守护化,可带进程优先级(-20~19,默认 0);systemd 托管时不要用;-c:指定配置文件路径,默认/etc/snapserver.conf。
4.2 配置覆盖选项(-hh 全量)
--<section>.<name> 形式的选项与 /etc/snapserver.conf 一一对应,命令行优先。snapserver -hh 实测输出全文按段整理(默认值为实测值):
| 选项 | 默认值 | 说明 |
|---|---|---|
| --server.threads | -1 | 工作线程数 |
| --server.pidfile | /var/run/snapserver/pid | 守护模式 pid 文件 |
| --server.user / --server.group | snapserver / (空) | 守护模式运行账号/组 |
| --server.datadir | (空) | server.json 持久化目录 |
| --server.mdns_enabled | 1 | mDNS 发布开关 |
| --ssl.certificate / --ssl.certificate_key | (空) | TLS 证书/私钥(PEM) |
| --ssl.key_password | (空) | 私钥口令 |
| --ssl.verify_clients | 0 | 客户端证书校验 |
| --ssl.client_cert | (空,可多次) | 客户端 CA 列表 |
| --authorization.enabled | 0 | JSON-RPC 鉴权开关 |
| --authorization.role | (空) | 角色定义 <Role name>:<permissions> |
| --authorization.user | (空) | 用户定义 <User name>:<password>:<role> |
| --http.enabled / --http.port | 1 / 1780 | HTTP JSON-RPC 开关/端口 |
| --http.bind_to_address | :: | HTTP 监听地址 |
| --http.ssl_enabled / --http.ssl_port | 0 / 1788 | HTTPS 开关/端口 |
| --http.doc_root | (空) | 静态站点根目录(Snapweb) |
| --http.host | <hostname> | 封面外链主机名 |
| --http.url_prefix | (空) | 封面外链 URL 前缀 |
| --http.publish_http / --http.publish_https | 1 / 1 | mDNS 发布开关 |
| --tcp.enabled / --tcp.port | 1 / 1705 | (已弃用别名,等价 tcp-control) |
| --tcp-control.enabled / --tcp-control.port | 1 / 1705 | TCP JSON-RPC 开关/端口 |
| --tcp-streaming.enabled / --tcp-streaming.port | 1 / 1704 | 音频流开关/端口 |
| --stream.plugin_dir | /usr/share/snapserver/plug-ins | meta 插件目录 |
| --stream.sandbox_dir | /usr/share/snapserver/sandbox | 可执行源沙箱目录 |
| --stream.stream | pipe:///tmp/snapfifo?name=default | (已弃用别名,等价 stream.source) |
| --stream.source | pipe:///tmp/snapfifo?name=default | 音源 URI(可多次) |
| --stream.default_source | (空) | 新客户端默认流 |
| --stream.sampleformat | 48000:16:2 | 默认采样格式 |
| --stream.codec | flac | 默认传输编码 |
| --stream.stream_buffer | 20 | (已弃用别名,等价 chunk_ms) |
| --stream.chunk_ms | 20 | 读取/编码时间片(ms) |
| --stream.buffer | 1000 | 端到端同步缓冲(ms) |
| --stream.send_to_muted | 0 | 静音客户端是否推流 |
| --streaming_client.initial_volume | 100 | 新客户端初始音量 |
| --logging.sink | (空) | 日志出口 |
| --logging.filter | *:info | 日志级别 |
💡 说明:三个
deprecated选项(--tcp.*、--stream.stream、--stream.stream_buffer)是旧版本拼写,新配置一律用--tcp-control.*、--stream.source、--stream.chunk_ms;codec 专属参数实测见站内《Snapcast 0.35.0 配置参数详解》5.2 节。
五、snapclient 命令行详解
5.1 基础用法与服务器地址
snapclient --help 实测输出的头部(url 语义官方原文):
Usage: snapclient [options...] [url]
With 'url' = <tcp|ws|wss>://<snapserver host or IP or mDNS service name>[:port]
For example: 'tcp://192.168.1.1:1704', or 'ws://)homeserver.local' or 'wss://_snapcast-https._tcp'
If 'url' is not configured, snapclient defaults to 'tcp://_snapcast._tcp'
三种写法(实测以显式 tcp 连接):tcp://10.89.61.2:1704(生产标配)、ws://10.89.61.2:1780(走 HTTP 端口)、不写 url(mDNS 自动发现,需服务器与客户端同网段且 avahi 可用)。连接成功日志实测:
2026-10-30 00-51-59.275 [Info] (Snapclient) Version 0.35.0, revision f1237347
2026-10-30 00-51-59.276 [Info] (Connection) Resolving host IP for: server
2026-10-30 00-51-59.277 [Info] (Connection) Connecting to host: 10.89.61.2:1704, port: 1704, protocol: tcp
2026-10-30 00-51-59.277 [Notice] (Connection) Connected to server
2026-10-30 00-51-59.277 [Info] (Connection) My MAC: "ae:91:13:92:a7:29", socket: 8
2026-10-30 00-51-59.287 [Info] (Controller) ServerSettings - buffer: 1000, latency: 0, volume: 100, muted: 0
2026-10-30 00-51-59.298 [Info] (Controller) diff to server [ms]: -0.001
diff to server [ms] 即客户端与服务器时钟差估计值,是同步质量的直接指标(局域网通常在 ±1ms 内)。
5.2 设备与音频参数
-l, --list:列出 PCM 设备,无声卡环境实测:
0: null
Discard all samples (playback) or generate zero samples (capture)
-s, --soundcard:设备索引或名称,默认default;无声卡机器接 ALSA null 设备即可验证同步链路(实测--soundcard null连接后正常收流);--latency:声卡固有延迟补偿(毫秒),默认 0;--sampleformat:强制客户端重采样为<rate>:<bits>:<channels>;--player:输出后端,默认alsa;file后端把原始 PCM 写到 stdout(实测日志:Player name: file, device: stdout, description: Raw PCM file output),适合管道转接,例如把客户端输出交给本地 recorder 分析:
snapclient tcp://10.89.61.2:1704 --player file | head -c 1000000 > /dev/null
--mixer:混音器实现,默认software(客户端软件调音量,最通用);hardware走声卡硬件混音(音质最好,依赖驱动支持)、script自定义脚本(联动外部功放)、none禁用(音量/静音控制失效)。
💡 技术拓展:mixer 四选对比——
mixer 原理 取舍 software 客户端进程内软件缩放采样 通用性最好,默认;CPU 略耗 hardware ALSA 混音器硬件通道 零 CPU、音质无损,需声卡支持 script 调用外部脚本 可联动功放串口/网络控制 none 不做音量处理 音量/静音键失效,仅特殊场景 树莓派等板载声卡用默认
software即可;有硬件混音的 USB 声卡可切hardware。
5.3 身份与安全参数
--hostID:客户端唯一身份,默认 MAC。实测环境客户端以 MAC 形式出现在服务器(如86:4c:86:eb:df:d7);虚拟机/重建环境 MAC 会变,导致服务器端的名字/音量/分组失联,此类环境必须显式固定(--hostID living-room);--instance:同机多实例编号,默认 1(一块声卡跑多路时区分);--cert/--cert-key/--key-password/--server-cert:对接服务器 TLS 的客户端证书三件套与 CA 校验(对应服务器--ssl.verify_clients)。
5.4 运行方式参数
-d, --daemon:守护化,默认 nice -3;--user:守护化降权账号(user[:group]);--logsink:日志出口(null/system/stdout/stderr/file:),--logfilter:级别过滤,默认*:info;排障改--logfilter '*:debug'。
六、JSON-RPC 控制命令详解
6.1 入口与约定
三个等价入口(实测均可用):HTTP POST http://<server>:1780/jsonrpc、TCP 1705 每行一个请求、WebSocket(1780 同端口)。协议版本查询:
curl -s http://10.89.61.2:1780/jsonrpc -H 'Content-Type: application/json' \
-d '{"id":3,"jsonrpc":"2.0","method":"Server.GetRPCVersion"}'
{
"id": 3,
"jsonrpc": "2.0",
"result": {
"major": 23,
"minor": 0,
"patch": 0
}
}
TCP 入口实测(裸 TCP 发一行 JSON):
{"id":1,"jsonrpc":"2.0","method":"Server.GetRPCVersion"}
{"id":1,"jsonrpc":"2.0","result":{"major":23,"minor":0,"patch":0}}
方法命名空间:Server.*(全局)、Group.*(分组)、Client.*(单客户端)、Stream.*(流属性)。参数中的客户端 ID 即 --hostID 值(默认 MAC),组 ID 为服务器生成的 UUID。以下全部回显为实测原文。
6.2 Server.* 全局命令
Server.GetStatus——全栈状态(组/客户端/流),最常用。实测回显(节选):
{
"id": 2,
"jsonrpc": "2.0",
"result": {
"server": {
"groups": [
{
"clients": [
{
"config": {
"instance": 1,
"latency": 0,
"name": "",
"volume": {
"muted": false,
"percent": 100
}
},
"connected": true,
"host": {
"arch": "x86_64",
"ip": "::ffff:10.89.61.3",
"mac": "66:5f:2e:b8:5e:7f",
"name": "a2cb3822d765",
"os": "Debian GNU/Linux 12 (bookworm)"
},
"id": "66:5f:2e:b8:5e:7f",
"snapclient": {
"protocolVersion": 2,
"version": "0.35.0"
}
}
],
"id": "49007f3a-2eef-a835-23a5-7cbe99977a2c",
"muted": false,
"name": "",
"stream_id": "SineTest"
}
],
"server": {
"host": {
"name": "snapserver",
"os": "Debian GNU/Linux 12 (bookworm)"
},
"snapserver": {
"controlProtocolVersion": 1,
"protocolVersion": 1,
"version": "0.35.0"
}
},
"streams": [
{
"id": "SineTest",
"properties": {
"canControl": false,
"canPause": false,
"canPlay": false
},
"status": "playing"
}
]
}
}
}
解读:groups[].clients[] 是拓扑,streams[] 是流列表;properties.canControl=false 表示 pipe 源不支持播放/暂停类控制(上游是裸 PCM 管道,没有元数据通道),meta 源(librespot 等)则为 true。
Server.DeleteClient——清理失联客户端记录(客户端 MAC 变更/退役后残留 connected: false 记录):
curl -s http://10.89.61.2:1780/jsonrpc -H 'Content-Type: application/json' \
-d '{"id":11,"jsonrpc":"2.0","method":"Server.DeleteClient","params":{"id":"42:f4:13:da:e0:32"}}'
{"id":11,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":1,"latency":10,"name":"LivingRoom","volume":{"muted":false,"percent":65}},"connected":true,"host":{"arch":"x86_64","ip":"::ffff:10.89.61.3","mac":"66:5f:2e:b8:5e:7f","name":"a2cb3822d765","os":"Debian GNU/Linux 12 (bookworm)"
(输出节选:返回删除后的全栈状态,孤儿记录已消失。)
6.3 Group.* 分组命令
Group.SetClients——把客户端并入/移出组(多房间同播的核心命令)。实测把第二台客户端并入第一台所在组:
curl -s http://10.89.61.2:1780/jsonrpc -H 'Content-Type: application/json' \
-d '{"id":7,"jsonrpc":"2.0","method":"Group.SetClients","params":{"id":"49007f3a-2eef-a835-23a5-7cbe99977a2c","clients":["66:5f:2e:b8:5e:7f","ae:91:13:92:a7:29"]}}'
{
"id": 7,
"jsonrpc": "2.0",
"result": {
"server": {
"groups": [
{
"clients": [
{ "id": "66:5f:2e:b8:5e:7f", "connected": true },
{ "id": "ae:91:13:92:a7:29", "connected": true }
],
"id": "49007f3a-2eef-a835-23a5-7cbe99977a2c",
"muted": false,
"name": "",
"stream_id": "SineTest"
}
]
}
}
}
(输出节选:两客户端已同组。)被移出的客户端会自动落入新建组,无需手工建组。
Group.SetName / Group.SetMute / Group.SetStream——组命名、组级静音、整组切流:
curl -s http://10.89.61.2:1780/jsonrpc -H 'Content-Type: application/json' \
-d '{"id":8,"jsonrpc":"2.0","method":"Group.SetName","params":{"id":"49007f3a-2eef-a835-23a5-7cbe99977a2c","name":"GroundFloor"}}'
{
"id": 8,
"jsonrpc": "2.0",
"result": {
"name": "GroundFloor"
}
}
== Group.SetMute true ==
{"id":9,"jsonrpc":"2.0","result":{"mute":true}}
== Group.SetStream ==
{"id":10,"jsonrpc":"2.0","result":{"stream_id":"SineTest"}}
6.4 Client.* 客户端命令
Client.GetStatus——单客户端详情:
curl -s http://10.89.61.2:1780/jsonrpc -H 'Content-Type: application/json' \
-d '{"id":2,"jsonrpc":"2.0","method":"Client.GetStatus","params":{"id":"66:5f:2e:b8:5e:7f"}}'
{
"id": 2,
"jsonrpc": "2.0",
"result": {
"client": {
"config": {
"instance": 1,
"latency": 0,
"name": "",
"volume": {
"muted": false,
"percent": 100
}
},
"connected": true,
"host": {
"arch": "x86_64",
"ip": "::ffff:10.89.61.3",
"mac": "66:5f:2e:b8:5e:7f",
"name": "a2cb3822d765",
"os": "Debian GNU/Linux 12 (bookworm)"
},
"id": "66:5f:2e:b8:5e:7f",
"lastSeen": {
"sec": 1793322353,
"usec": 286198
},
"snapclient": {
"name": "Snapclient",
"protocolVersion": 2,
"version": "0.35.0"
}
}
}
}
Client.SetVolume——音量与静音(客户端静音的唯一入口,见下方排障实录):
== Client.SetVolume 65 ==
{
"id": 4,
"jsonrpc": "2.0",
"result": {
"volume": {
"muted": false,
"percent": 65
}
}
}
== 静音(volume.muted 置 true)==
{"id":1,"jsonrpc":"2.0","result":{"volume":{"muted":true,"percent":100}}}
Client.SetName / Client.SetLatency——命名与延迟补偿:
== Client.SetName ==
{"id":5,"jsonrpc":"2.0","result":{"name":"LivingRoom"}}
== Client.SetLatency 10 ==
{"id":6,"jsonrpc":"2.0","result":{"latency":10}}
错误示范排障实录:想当然地调用 Client.SetMute 会得到 Method not found(实测原文):
{
"error": {
"code": -32601,
"message": "Method not found"
},
"id": 1,
"jsonrpc": "2.0"
}
结论:JSON-RPC 23 中没有 Client.SetMute 方法,客户端静音必须走 Client.SetVolume 并把 volume.muted 置 true(见上方实测回显);组级静音用 Group.SetMute。遇到 -32601 优先核对该版本 RPC 方法名(方法集随 major 版本演进)。
6.5 Stream.* 流属性观测
流列表与属性在 Server.GetStatus 的 streams[] 中(见 6.2)。pipe/file/process 类「裸 PCM 源」canControl 为 false——没有可控制的播放器元数据;librespot/airplay/meta 源由上游暴露播放/暂停/切曲能力,属性为 true 后 Snapweb 才显示播放控制按钮。本文实测流状态:
{
"id": "SineTest",
"properties": {
"canControl": false,
"canGoNext": false,
"canGoPrevious": false,
"canPause": false,
"canPlay": false,
"canSeek": false
},
"status": "playing",
"uri": {
"raw": "pipe:///serverdata/snapfifo?chunk_ms=20&codec=pcm&name=SineTest&sampleformat=44100%3A16%3A2",
"scheme": "pipe"
}
}
七、日志与排障
7.1 日志出口与级别
- 出口:
--logging.sink(server)/--logsink(client),可选 null、system、stdout、stderr、file:<路径>;systemd 托管默认 system,用journalctl -u snapserver -f跟踪; - 级别:
--logging.filter(server)/--logfilter(client),格式<tag>:<level>逗号组合,级别 trace/debug/info/notice/warning/error/fatal;排障临时用*:debug,恢复*:info。
7.2 常见日志形态速查(全部实测原文)
正常连接(客户端):
[Notice] (Connection) Connected to server
[Info] (Controller) ServerSettings - buffer: 1000, latency: 0, volume: 100, muted: 0
[Info] (Controller) diff to server [ms]: -0.001
正常启动(服务器,输出节选):
[Info] (Snapserver) Version 0.35.0, revision f1237347
[Info] (Snapserver) Adding source: pipe:///serverdata/snapfifo?name=SineTest&sampleformat=44100:16:2
[Info] (PipeStream) PipeStream mode: create
[Info] (StreamServer) Creating TCP stream acceptor for address: ::, port: 1704
[Info] (ControlServer) Creating TCP control acceptor for address: ::, port: 1705
[Info] (ControlServer) Creating HTTP acceptor for address: ::, port: 1780
mDNS 不可用(无 avahi 守护进程环境,不影响 TCP 直连):
[Error] (Avahi) Failed to create client: Daemon not running
源无数据(pipe 写端断开/未启动):
[Info] (Stream) No chunks available
[Info] (Alsa) Failed to get chunk
缓冲告警(网络抖动或 buffer 过小):
[Info] (Stream) abs(age > 500): 559969
7.3 排障实录
实录一:pipe 写端 BrokenPipe
现象:宿主侧 PCM 生成进程退出,日志报(实测原文):
Traceback (most recent call last):
File "sine_writer.py", line 20, in <module>
f.write(bytes(frames))
BrokenPipeError: [Errno 32] Broken pipe
定位:命名管道读端(snapserver)重启期间管道被重置,写端进程未捕获信号直接崩溃;重新拉起写端即可(数据流本身无状态)。预防:写端进程用 systemd/脚本守护或对 BrokenPipe 做重连重试。
实录二:客户端记录残留与身份漂移
现象:Server.GetStatus 出现多个 connected: false 的旧客户端记录;重启后新记录的 MAC 与旧配置对不上。定位:客户端唯一身份默认是 MAC,环境重建后 MAC 变化(实测 66:5f:2e:b8:5e:7f → 86:4c:86:eb:df:d7),旧记录残留且配置失联。解决:①稳定环境给 snapclient 显式 --hostID;②残留记录用 Server.DeleteClient 清理(6.2 实测)。
实录三:Method not found(-32601)
现象与解决见 6.4 排障实录:方法名与 RPC major 版本强相关,Client.SetMute 在 v23 不存在,静音走 Client.SetVolume 的 volume.muted。
八、注意事项
- 服务器与客户端必须同大版本部署(协议版本随 Release 演进,本文实测双方均为 0.35.0、协议 v2);
--stream.source可配置多行,但每行 URI 的name必须唯一,重名会导致源注册失败;- JSON-RPC 改动即时生效且写入运行态,服务器重启后按 datadir 的
server.json恢复——重要分组/音量变更前确认 datadir 已持久化; - 控制面(1705/1780)默认无鉴权,公网暴露前必须配置 TLS+authorization 或防火墙限制;
-d守护模式与 systemd 托管二选一,混用会产生双进程抢占端口。
九、常见问题
Q1:snapclient 连不上服务器?
按序检查:ss -lntp | grep -E '1704|1705|1780' 确认服务器三端口监听;客户端 url 的 IP/端口正确;防火墙放行 1704;客户端日志若停在 Resolving host IP 则是 DNS/主机名问题,改用 IP 直连。
Q2:如何只看某个模块的调试日志?
filter 按 tag 过滤,例如只看流模块:snapserver --logging.filter 'Stream:debug,*:info'(tag 即日志行中的 (Stream) 名)。
Q3:Client.SetVolume 的 percent 和 muted 是同时设置吗?
是。volume 是整体对象,请求里两个都要给(省略 muted 按false 处理),返回值即设置后的完整音量状态(见 6.4 实测回显)。
Q4:批量查所有客户端的音量/延迟?
无单独列表方法,用 Server.GetStatus 一次拿全(groups[].clients[].config),脚本按 id 遍历即可。
Q5:Snapweb 打不开?
确认 /etc/snapserver.conf 的 [http] doc_root = /usr/share/snapserver/snapweb(deb 默认已带)且 http.enabled = true;访问 http://<server>:1780/ 应返回 200(实测 HTTP/1.1 200 OK、Server: Snapcast)。
十、参考链接
- JSON-RPC API 文档(方法全集,按 RPC 版本对照):https://github.com/snapcast/snapcast/blob/develop/doc/json_rpc_api/
- 官方仓库 man 手册(snapserver/snapclient):https://github.com/snapcast/snapcast/tree/develop/doc
- 站内相关篇目:《Snapcast 0.35.0 介绍与选型指南》、《Snapcast 0.35.0 Docker Compose 部署指南》、《Snapcast 0.35.0 配置参数详解》