连接 Sound Show 2
使用自己的脚本、硬件控制器或集成功能控制正在运行的 Sound Show 2。WebSocket API 可启动可播放项目、控制播放器和输出、执行提示操作,并将实时状态发回控制器。
本指南介绍协议 v2,直接连接计算机或局域网中的 Sound Show。无需网站 API 密钥或账户访问令牌。此 API 不支持编辑项目或上传文件。
启用服务器
“启用服务器”章节- 在桌面计算机上打开 Sound Show 2 并加载项目。主机需要 Pro 使用权限,有效的 Pro 试用也可以。参见 Free 与 Pro。
- 打开选项 → 集成 → 远程服务器,也可使用远程面板的设置按钮。
- 选择端口(默认为
8080),设置至少六个字符的密码并保存。请为此连接使用独立密码。 - 使用连接按钮启动服务器。如果密码为空,请确认应用关于无密码访问的警告。
- 复制 Sound Show 显示的地址。如需使用内置浏览器遥控器,请保持提供网页开启;关闭该选项也不影响 WebSocket 端点。
连接地址
“连接地址”章节浏览器遥控器与 WebSocket API 使用相同的主机和端口。
| 用途 | 在 Sound Show 计算机上的示例 |
|---|---|
| WebSocket 连接 | ws://127.0.0.1:8080/ws |
| 内置浏览器遥控器 | http://127.0.0.1:8080/ |
| 服务器健康检查 | http://127.0.0.1:8080/health |
从其他设备连接时,将 127.0.0.1 替换为 Sound Show 计算机的地址,例如 ws://192.168.1.20:8080/ws。如果配置的端口不是 8080,请使用实际端口。localhost 始终指运行客户端的设备。
健康检查端点返回类似 {"status":"ok","protocol_version":2} 的对象,只确认服务器可达,不会验证客户端身份。
从浏览器连接
“从浏览器连接”章节默认情况下,Sound Show 检查浏览器的 Origin 请求头。它必须是使用服务器端口的 HTTP 来源,主机须为 localhost、检测到的 LAN 地址或配置的通告主机。通过 Sound Show 显示的地址打开内置遥控器即可使用受允许的来源。
在其他设备、网站或开发服务器端口上托管的自定义页面,需要启用下述允许外部来源选项。原生客户端(包括本页的 JavaScript 终端示例)可以省略 Origin,不需要该选项。
允许外部来源
“允许外部来源”章节当您将自定义浏览器遥控器托管在 Sound Show 之外时,启用此选项:
- 打开选项 → 集成 → 远程服务器,或远程面板的设置。
- 设置远程密码,开启允许外部来源并应用设置。此选项默认关闭。如果找不到,请更新至包含此选项的 Sound Show 版本。
- 在能访问 Sound Show 计算机的设备上打开自定义遥控页面。将其 WebSocket 连接到 Sound Show 的地址,而不是页面托管地址,并发送包含密码的常规
hello消息。
例如,托管于 http://192.168.1.30:3000 的控制器可以连接到 ws://192.168.1.20:8080/ws 上的 Sound Show。浏览器脚本可以这样开始:
const remotePassword = window.prompt("Sound Show remote password");if (remotePassword !== null) { const socket = new WebSocket("ws://192.168.1.20:8080/ws"); socket.addEventListener("open", () => { socket.send(JSON.stringify({ type: "hello", version: 2, password: remotePassword, features: ["runtime_snapshots"], })); }); socket.addEventListener("message", (event) => { const message = JSON.parse(event.data); console.log(message); // Handle hello_rejected, errors, and snapshots here. });}将示例地址替换为您的主机和端口。收到第一条 state 后再启用播放控制,并采用完整 JavaScript 示例中的快照处理逻辑。将密码保留在控制器会话中,不要嵌入公开托管的页面。
此选项接受主机或端口不同的 HTTP 和 HTTPS 页面来源。密码握手和 Pro 要求仍然适用。保存更改会立即生效并断开客户端,因此需要重新连接和验证身份。关闭选项也会结束现有的外部会话。内置浏览器遥控器可在此选项关闭时使用。
浏览器限制仍然适用。 对于简单的 LAN 配置,请通过 HTTP 提供自定义页面。HTTPS 页面可能阻止未加密的 ws:// 连接;启用此选项不会提供安全的 wss:// 端点。HTTPS 控制器需要浏览器兼容的安全连接,例如另行配置的 TLS 代理。浏览器还可能要求本地网络权限或施加其他网络限制。此选项不会为 HTTP 端点添加 CORS 请求头。file:// 页面和不透明的 null 来源仍会被拒绝:请使用 HTTP 服务器提供本地 HTML 文件。
先完成身份验证
“先完成身份验证”章节套接字打开后立即发送一条 JSON 文本消息,须在十秒内完成。消息应包含 Sound Show 中配置的远程密码:
{ "type": "hello", "version": 2, "password": "your-remote-password", "features": ["runtime_snapshots"]}对于已确认允许无密码访问的服务器,可省略 password 或使用空字符串。features 为可选字段;请求 runtime_snapshots 后,客户端会分别收到控制状态、指令、播放列表及可播放项目活动的实时更新。
成功时服务器发送:
{ "type": "hello_ok", "protocol_version": 2, "requested_version": 2, "state_mode": "full_snapshot", "features": ["ping", "runtime_snapshots"]}随后自动发送完整的 state 消息。收到它之后,再选择目标或发送演出命令。后续消息会替换整个状态或其中一个具名部分。没有订阅命令,也没有逐条命令的成功确认:以最终状态为准。
失败时会收到包含 reason 和 message 的 hello_rejected,随后断开连接。原因包括 invalid_password、unsupported_version 和 rate_limited。参见错误与限制。
尝试 JavaScript 客户端
“尝试 JavaScript 客户端”章节将代码保存为 soundshow-client.mjs,使用 Node.js 22.12 或更新版本运行。它使用内置 WebSocket 客户端,无需安装软件包。示例列出项目中的可播放项目并跟踪实时状态;只有通过命令行参数传入可播放项目 ID 时才会开始播放。
const url = process.env.SOUNDSHOW_REMOTE_URL ?? "ws://127.0.0.1:8080/ws";const password = process.env.SOUNDSHOW_REMOTE_PASSWORD ?? "";const playableId = process.argv[2];const ws = new WebSocket(url);let state = null;let firstSnapshot = true;
const domains = { control_snapshot: "control", players_snapshot: "players", instructions_snapshot: "instructions", playlists_snapshot: "playlists", playable_runtime_snapshot: "playable_runtime", logical_devices_snapshot: "logical_devices", timers_snapshot: "timers", audio_controls_snapshot: "audio_controls", lights_snapshot: "lights",};
function send(command) { if (!state || ws.readyState !== WebSocket.OPEN) { throw new Error("Wait for the first state snapshot before sending commands."); } ws.send(JSON.stringify(command));}
ws.addEventListener("open", () => { ws.send(JSON.stringify({ type: "hello", version: 2, password, features: ["runtime_snapshots"], }));});
ws.addEventListener("message", (event) => { const message = JSON.parse(event.data); if (message.type === "hello_rejected" || message.type === "error") { console.error(message.reason ?? message.code ?? "error", message.message); return; } if (message.type === "state") { state = message.state; // Replace the entire state, even after a project change. } else { const domain = domains[message.type]; if (!state || !domain) return; // Ignore unknown additive message types. if ((domain === "audio_controls" || domain === "lights") && message.revision < (state[domain]?.revision ?? -1)) return; state = { ...state, [domain]: message[domain] }; }
if (firstSnapshot) { firstSnapshot = false; const playables = (state.project?.categories ?? []).flatMap((category) => category.playables.map((p) => ({ id: p.id, name: p.name, kind: p.kind, category: category.name, })) ); console.table(playables); if (playableId) { if (playables.some((p) => p.id === playableId)) { send({ type: "play_playable", playable_id: playableId, action: "start" }); } else { console.error("That playable ID is not in the current project."); } } console.log("Connected. Press Ctrl+C to disconnect."); } // Use `state` here to update your controller after every snapshot.});
ws.addEventListener("error", () => console.error("Connection failed. Check the server address and settings."));ws.addEventListener("close", (event) => { state = null; console.log("Disconnected:", event.code, event.reason);});process.on("SIGINT", () => ws.close());在 PowerShell 中设置地址和远程密码,然后列出可播放项目:
$env:SOUNDSHOW_REMOTE_URL = 'ws://127.0.0.1:8080/ws'$env:SOUNDSHOW_REMOTE_PASSWORD = 'your-remote-password'node soundshow-client.mjs在 macOS 或 Linux 终端中:
export SOUNDSHOW_REMOTE_URL='ws://127.0.0.1:8080/ws'export SOUNDSHOW_REMOTE_PASSWORD='your-remote-password'node soundshow-client.mjs不要在共享脚本中写入真实密码。无密码服务器使用空值。按 Ctrl+C 停止脚本,从表中复制一个可播放项目 ID,然后重新运行,将该项目触发一次:
node soundshow-client.mjs "paste-a-playable-id-here"示例不会自动重连或重放命令。构建长期运行的控制器前,请加入连接恢复逻辑,并从命令参考选择命令。
故障排查
“故障排查”章节| 症状 | 检查事项 |
|---|---|
| 连接被拒绝或超时 | 保持 Sound Show 打开并启动服务器。检查端口、主机地址、防火墙以及两台设备能否在网络上互相访问。 |
| 服务器无法启动 | 检查 Pro 权限、连接日志以及端口是否被其他应用占用。 |
连接时出现 HTTP 403 |
检查 Pro 权限和浏览器来源。页面托管于其他设备、端口或网站时,在 Sound Show 中开启允许外部来源。 |
| 允许外部来源后仍无法连接自定义遥控器 | 检查 Sound Show 主机地址、防火墙和浏览器控制台。该选项不会绕过混合内容或本地网络限制;请使用上文的 HTTP LAN 配置。 |
invalid_password |
使用远程服务器密码,而不是 Sound Show 账户密码。 |
unsupported_version |
发送 version: 2 并使用 /ws。Sound Show 1 消息不兼容。 |
HTTP 429 或 rate_limited |
停止快速重试或发送命令,并遵循重试指引。 |
| 已连接但没有状态 | 先发送 hello,检查拒绝消息或格式错误的 JSON。 |
| 命令无效 | 从最新状态获取 ID;检查锁定、目标可用性、许可证和 error 消息。 |
| 控制器显示过时 | 同时处理域快照和完整 state 消息。没有消息本身并不意味着连接已断开。 |
从 Sound Show 1 迁移
“从 Sound Show 1 迁移”章节使用 /ws 代替 /SoundShow,使用小写 type 字段代替 $type 和 .NET 类名。发送 v2 hello 握手。使用播放器 ID 和逻辑设备 ID,而不是播放器或输出的数字索引。图标是 HTTP icon_url 资源,状态则以完整快照或域快照发送。