English | 简体中文
OpenRemoteShouter 是一个局域网远程喊话工具。它在电脑上启动一个本地网页服务,其他设备可以通过浏览器或 HTTP API 发送文字,让目标电脑以 Fluent 风格的全屏动态提示显示并使用 EdgeTTS 语音播报。
⚠️ 有人工智能参与编写
⚠️ 除 Windows 和 LoongArch64 Old World ABI 1.0 构建外,其他平台构建目前仅确认能够在 GitHub Actions 中完成打包,尚未经过实机运行测试。
- 提供 LoongArch64 Old World ABI 1.0 专用构建包。
- 局域网网页喊话,默认监听
21212端口。 - 支持主题色驱动的全屏动态渐变提示,标题和正文以非线性动画进入。
- 显示时间按 TTS 实际返回的音频文件时长自动分配,最少显示 10 秒。
- 支持 EdgeTTS 中文语音播报。
- 支持网页表单、JSON API 和表单 POST。
- 支持 Windows、Linux、macOS 的多架构构建。
- WebUI 内置 Fluent UI Web Components,发送按钮与成功提示采用从下往上的动效;发送成功后可直接取消当前显示。
- 提供 20 个可分配给账户的明亮/深色主题色。
- 下载适合当前系统的构建包。
- 解压后运行:
- Windows:运行
run.bat(不建议)或OpenRemoteShouter.exe;run.bat启动后会自动关闭。 - Linux/macOS:运行
./run.sh,默认后台启动;如需在终端内查看输出,运行./run.sh --foreground。 - Portable 包:需要先安装 .NET 8 Runtime,再运行
run.sh或run.bat
- Windows:运行
- 打开控制台窗口或托盘菜单,复制访问地址。
- 默认服务只监听本机回环地址;可在本机浏览器初始化,也可按“可信中转”章节显式配置远程初始化。
登录 WebUI 后默认进入喊话页,只显示消息内容和发送按钮。主题色、置顶、语音、说话人、语速、音量以及关闭当前显示等低频选项位于“调试设置”中。每位老师的设置按用户名保存在本地浏览器 Cookie,可从调试设置导出为 JSON,也可在另一台浏览器导入。主题色会作用于目标电脑的动态渐变显示窗口,文字颜色会根据背景亮度自动选择黑色或白色。显示窗口不再提供手动自动关闭计时;启用语音时使用 TTS 返回文件的实际时长并至少保留 10 秒,语音关闭或合成失败时保留 10 秒。
WebUI 控件使用本地内置的 Fluent UI Web Components 资源,不依赖外部 CDN。发送成功后会显示“取消显示”按钮,可中止当前客户端的全屏显示;成功提示和发送按钮使用与客户端一致的上行/渐变动效。创建管理员或新用户时,页面会明确提示:显示名称会显示在客户端喊话标题中。
桌面控制台和托盘菜单中的“停止网页服务”“退出软件”都会要求输入任意一个启用中的管理员账户密码。密码只用于本次本地确认,不会创建 WebUI 会话;系统任务管理器等操作系统级强制结束进程不在软件拦截范围内。
启用远程访问后仍无法访问,请检查防火墙是否放行 21212 端口以及证书/监听模式是否配置正确。
首次打开 WebUI 时,需要创建管理员账户。默认只接受本机 localhost / 127.0.0.1 初始化;只有显式配置可信中转、强令牌和 HTTPS 后,远程教师才可以完成初始化。初始化后,WebUI 和喊话 API 都需要登录。
已实现的安全措施:
- 密码使用 PBKDF2-SHA256 加随机盐保存,不保存明文密码。
- 同一来源地址对同一用户名连续失败 5 次会锁定该组合 5 分钟;已存在的账户累计失败 20 次会进入 5 分钟账户级软限流,保护期内每 10 秒最多执行一次真实密码校验,错误尝试返回 429,正确密码可在下一个校验窗口登录并解除账户桶;来源地址还有 100 次失败/5 分钟的来源级上限。账户桶只对已存在账户建立,因此直接暴露到公网时
401/429差异可能形成用户名存在性侧信道,建议在可信网关统一响应并做集中限流。限流记录只保存在当前进程内,重启或多实例部署不会共享,不能替代网关/WAF 的集中限流。 - 登录会话使用 HttpOnly、SameSite=Strict Cookie,并带过期时间。
- 所有修改类 API 都需要 CSRF 令牌。
- 修改密码、禁用用户或删除用户会使相关会话失效。
- 管理员不能禁用或删除自己的当前账户,系统至少保留一个启用的管理员。
- 首次管理员初始化默认只能从本机完成;远程初始化必须同时满足固定中转 IP、显式开关、HTTPS 和高熵令牌。
- WebUI 响应包含基础安全头和 CSP。
- 登录校验会限制单个来源的失败次数,并限制内存中的限流/会话记录数量。
- 账户数据库启动时会校验文件大小、结构、用户数量和密码哈希参数,损坏文件会拒绝加载而不会重新进入初始化。
- 从旧版本升级时,缺失或重复的账户主题色会按账户文件中的稳定顺序自动分配到未使用的主题色,并写回
accounts.json;超过 20 个账户时无法继续保证唯一,需要在用户管理中手动处理重复项。 - TTS 缓存和日志文件都有大小上限,超出时按最旧文件自动清理或轮转,避免磁盘被请求持续占满。
如果全新解压后页面显示“账户服务不可用”或仍显示登录,不要反复尝试登录:先检查实际运行账户的数据目录(Windows 默认是 %LOCALAPPDATA%\\OpenRemoteShouter\\accounts.json)以及文件权限、完整性和日志。升级或重新解压不会自动清空旧账户;已有有效账户时显示登录是正常行为,损坏或空的 accounts.json 会被安全地拒绝加载。
未配置证书时,服务默认只监听本机回环地址上的 HTTP,适合首次初始化或本机使用。HTTP 不会加密密码、会话 Cookie 或 CSRF 令牌,不能把“局域网”视为可信网络。需要让其他设备访问时,优先配置 HTTPS PFX 证书:
export OPEN_REMOTE_SHOUTER_HTTPS_CERT_PATH=/path/to/server.pfx
read -r -s -p 'PFX password: ' OPEN_REMOTE_SHOUTER_HTTPS_CERT_PASSWORD
printf '\n'
export OPEN_REMOTE_SHOUTER_HTTPS_CERT_PASSWORD
./OpenRemoteShouter
unset OPEN_REMOTE_SHOUTER_HTTPS_CERT_PASSWORD密码通过交互式静默输入,不会写入 shell 历史;在生产环境中更建议由服务管理器或密钥存储注入环境变量。
PFX 文件包含私钥,应限制为运行账户可读(Linux/macOS 可执行 chmod 600 /path/to/server.pfx,并确保其父目录不可被其他账户写入)。
默认情况下,程序不信任任何转发头。若要让固定中转节点代为终止 HTTPS,请显式设置 OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_IPS,只填写应用实际看到的 TCP 对端 IP,例如同机反代的 127.0.0.1 或 VPN 中转地址;只对白名单中的精确 IP 启用 X-Forwarded-For、X-Forwarded-Host 和 X-Forwarded-Proto。
若还要允许第一次管理员创建也走远程中转,再额外设置 OPEN_REMOTE_SHOUTER_ALLOW_TRUSTED_PROXY_SETUP=1 和至少 32 字节的随机 OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_SETUP_TOKEN。只要请求的原始 TCP 对端命中中转白名单,服务端就一律按中转请求处理,不会因为中转改写了 Host 或删掉转发头而降级成免令牌本机路径;远程初始化开关未打开时会拒绝该请求,打开后则必须同时满足有效令牌和 HTTPS。令牌只通过 X-OpenRemoteShouter-Setup-Token 请求头提交,服务端只在空账户库时接受,并在本次进程成功初始化后失效。开关开启但缺少白名单或令牌时,程序会拒绝启动。
export OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_IPS=127.0.0.1
export OPEN_REMOTE_SHOUTER_ALLOW_TRUSTED_PROXY_SETUP=1
export OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_SETUP_TOKEN="$(openssl rand -base64 48)"中转必须覆盖(而不是追加)客户端提交的 X-Forwarded-Host、X-Forwarded-Proto 和 X-Forwarded-For,并通过 FRP TLS、WireGuard、SSH 隧道或其他受保护链路连接班级端。不要把令牌放在 URL;不要把跨机器回源配置成裸 HTTP。远程初始化页面会显示令牌输入框;如果把同机 127.0.0.1 也列入中转白名单,应用无法再区分同一地址上的反代和本机浏览器,因此二者都按中转请求处理。若必须无令牌本机初始化,请在配置该回环白名单前先完成初始化,或暂时移除该地址并关闭远程初始化开关后重启服务。
命令行远程初始化时,把令牌放在请求头(不要放进 URL 或日志):
read -r -s -p 'Setup token: ' ORS_SETUP_TOKEN
printf '\n'
curl --fail-with-body -sS \
-H 'Content-Type: application/json' \
-H 'Origin: https://class.example.test' \
-H "X-OpenRemoteShouter-Setup-Token: $ORS_SETUP_TOKEN" \
-X POST 'https://class.example.test/api/auth/setup' \
-d '{"username":"teacher","displayName":"Teacher","password":"CHANGE-ME"}'
unset ORS_SETUP_TOKENNginx/Caddy 等反代至少要把外部主机名和协议写入这些头(示意:Host $host、X-Forwarded-Host $host、X-Forwarded-Proto $scheme、X-Forwarded-For $remote_addr),并确保客户端不能预先注入同名值。若使用 FRP,应用看到的 TCP 对端通常是同机 frpc 的 127.0.0.1,此时白名单应填写 127.0.0.1,而不是想当然填写 frps 的公网地址;请以日志/网络实际观察到的对端地址为准。
推荐让公网入口上的 frps 只转发到班级电脑上的 frpc,再由公网入口上的 Nginx/Caddy 负责 HTTPS。班级端应用监听 127.0.0.1:21212,frpc 映射到服务端 127.0.0.1:22122,反代再把 https://class.example.test 转到 http://127.0.0.1:22122。
服务端 frps.toml:
bindPort = 7000
auth.method = "token"
auth.token = "CHANGE_TO_A_LONG_RANDOM_FRP_TOKEN"班级端 frpc.toml:
serverAddr = "relay.example.test"
serverPort = 7000
auth.method = "token"
auth.token = "CHANGE_TO_A_LONG_RANDOM_FRP_TOKEN"
[[proxies]]
name = "open-remote-shouter"
type = "tcp"
localIP = "127.0.0.1"
localPort = 21212
remoteIP = "127.0.0.1"
remotePort = 22122公网入口 Nginx 示例:
location / {
proxy_pass http://127.0.0.1:22122;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-OpenRemoteShouter-Setup-Token $http_x_openremoteshouter_setup_token;
}班级端应用环境变量(设置给 OpenRemoteShouter,不是给 frpc):
export OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_IPS=<班级端实际看到的frpc对端IP>
export OPEN_REMOTE_SHOUTER_ALLOW_TRUSTED_PROXY_SETUP=1
export OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_SETUP_TOKEN='至少32字节的随机值'更推荐直接编辑发布目录中的 run.bat(Windows)或 run.sh(Linux/macOS),取消三行中转配置前的注释,把 REPLACE_WITH_AT_LEAST_32_RANDOM_BYTES 换成真实随机值,再用脚本启动应用。默认保持注释,因此普通本机部署不会意外开启远程初始化。frpc 只读取上面的 frpc.toml;不要把 OPEN_REMOTE_SHOUTER_* 变量写进 FRP 配置。
下面按操作系统列出完整的落地步骤。先从 FRP 官方发布包中取出对应平台的 frps(公网中转机)和 frpc(班级电脑),并确保两端版本一致。
Windows 公网中转机
-
将
frps.exe和配置保存到C:\frp\,文件为C:\frp\frps.toml。 -
在“高级防火墙”中允许入站 TCP
7000;22122只允许本机访问(不要对公网放行)。 -
PowerShell 启动:
C:\frp\frps.exe -c C:\frp\frps.toml
需要常驻时,可在任务计划程序中创建“系统启动时运行”的任务,程序填写
C:\frp\frps.exe,参数填写-c C:\frp\frps.toml。
Linux 公网中转机
-
将
frps和配置保存为/opt/frp/frps、/etc/frp/frps.toml。 -
防火墙只开放 FRP 端口和 HTTPS 端口,例如:
sudo ufw allow 7000/tcp sudo ufw allow 80,443/tcp sudo ufw deny 22122/tcp
-
先前台验证:
sudo /opt/frp/frps -c /etc/frp/frps.toml。确认无误后,用 systemd 运行(/etc/systemd/system/frps.service):[Unit] Description=FRP server After=network-online.target [Service] ExecStart=/opt/frp/frps -c /etc/frp/frps.toml Restart=on-failure [Install] WantedBy=multi-user.target
执行
sudo systemctl daemon-reload && sudo systemctl enable --now frps。
macOS 公网中转机
- 将
frps和frps.toml放到~/frp/(或/usr/local/etc/frp/)。 - 在系统防火墙/云主机安全组中允许 TCP
7000、80、443,不要开放22122。 - 终端启动:
~/frp/frps -c ~/frp/frps.toml。需要开机常驻时,用“登录项”或 launchd 的~/Library/LaunchAgents/服务调用同一命令。
Windows 班级电脑(运行 OpenRemoteShouter 和 frpc)
将 frpc.exe、frpc.toml 放到 C:\frp\。编辑 OpenRemoteShouter 同目录的 run.bat,设置其中三个 OPEN_REMOTE_SHOUTER_* 值,然后双击或在 PowerShell 中运行 run.bat。也可以临时在 PowerShell 中设置后启动应用:
[Environment]::SetEnvironmentVariable("OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_IPS", "127.0.0.1", "User")
[Environment]::SetEnvironmentVariable("OPEN_REMOTE_SHOUTER_ALLOW_TRUSTED_PROXY_SETUP", "1", "User")
[Environment]::SetEnvironmentVariable("OPEN_REMOTE_SHOUTER_TRUSTED_PROXY_SETUP_TOKEN", "至少32字节的随机值", "User")
C:\path\to\OpenRemoteShouter\run.bat另开一个 PowerShell 窗口运行 FRP:C:\frp\frpc.exe -c C:\frp\frpc.toml。
设置环境变量后要重启 OpenRemoteShouter;如果应用与 frpc 不在同一台电脑,把 127.0.0.1 换成应用日志中看到的实际 TCP 对端 IP。
Linux 班级电脑
将配置保存为 /etc/frp/frpc.toml。编辑发布目录中的 run.sh,设置令牌和中转 IP 后执行 ./run.sh 启动应用;另开终端运行 FRP:
chmod +x ./run.sh
./run.sh另开终端运行 FRP:/opt/frp/frpc -c /etc/frp/frpc.toml。
若用 systemd 启动应用,请把这些变量写入该服务的 Environment= 或 EnvironmentFile=,不要只写在交互式 shell。
macOS 班级电脑
将 frpc、frpc.toml 放到 ~/frp/。编辑发布目录中的 run.sh,设置令牌和中转 IP 后执行 ./run.sh 启动应用;另开终端运行 FRP:
chmod +x ./run.sh
./run.sh另开终端运行 FRP:~/frp/frpc -c ~/frp/frpc.toml。
如果应用由 launchd 启动,请把同样的变量写进对应 plist 的 EnvironmentVariables,然后重新加载该 plist。
验证
Windows PowerShell:
Invoke-RestMethod https://class.example.test/api/auth/state | ConvertTo-JsonLinux/macOS:
curl -fsS https://class.example.test/api/auth/state结果应包含 setupRequired: true(空账户库)和 remoteSetupEnabled: true。页面提交初始化令牌后再创建管理员。FRP 的 auth.token 与 OpenRemoteShouter 初始化令牌是两套不同的密钥,不能混用。
来源地址限流按应用实际看到的 TCP 对端地址计算;若中转节点没有正确传递客户端地址,多个用户可能共用一个来源桶。成功登录只清除该来源+用户名桶,不会清除来源级失败计数;需要多人共享出口时,应在可信网关上做更细粒度的限流,并避免把应用直接暴露在明文 HTTP 上。
在部署脚本中希望证书缺失时直接拒绝启动,可以再设置 OPEN_REMOTE_SHOUTER_REQUIRE_HTTPS=1。
配置证书后服务只在该端口提供 HTTPS,并会在访问地址中显示 https://;Cookie 会自动启用 Secure 属性。若改由可信中转终止 TLS,则应用本身可以继续只在本机回环上跑 HTTP,但必须完成上面的白名单配置,并让中转节点正确设置转发头;应用会据此恢复外部 HTTPS 的同源校验和安全 Cookie。若还要让首次初始化也走这个中转,需要同时打开远程初始化开关并配置令牌。
如果必须兼容旧的局域网明文部署,需显式设置 OPEN_REMOTE_SHOUTER_ALLOW_INSECURE_HTTP=1 才会监听所有网卡;启动日志会持续提示风险。此模式下密码、会话 Cookie 和 CSRF 令牌均可能被网络窃听,生产环境不应使用。
如果需要打开局域网使用(包括直接通过本机 IP 访问),可在 run.bat 或 run.sh 中设置 OPEN_REMOTE_SHOUTER_ALLOW_LAN=1。未设置或设为 0 时,无论是否配置证书都只监听 localhost / 127.0.0.1;设为 1 后才会监听所有网卡。无证书时这会明确开启明文 HTTP 暴露,请优先配置 HTTPS 或使用可信 FRP/Nginx 中转。旧参数 OPEN_REMOTE_SHOUTER_ALLOW_DIRECT_IP 和 OPEN_REMOTE_SHOUTER_ALLOW_INSECURE_HTTP 仍兼容,但新部署应使用 OPEN_REMOTE_SHOUTER_ALLOW_LAN。
账户数据默认保存到系统用户数据目录的 accounts.json。如需指定数据目录,可以设置:
OPEN_REMOTE_SHOUTER_DATA_DIR=/path/to/data ./OpenRemoteShouter自定义数据目录和 OPEN_REMOTE_SHOUTER_LOG_FILE 指向的父目录必须由运行账户独占,不能放在其他账户可写的共享目录中;Windows 下程序不强制修改 ACL,文件权限依赖目录本身的安全设置。
EdgeTTS 默认生成 MP3 音频。Linux 下程序会按顺序寻找以下播放器:
启用语音播报时,喊话文本会发送到 Microsoft Bing EdgeTTS 服务进行合成;包含敏感信息的内容请关闭语音或采用自托管 TTS。
ffplaympvpw-playcvlcvlc
如果需要兼容只支持 WAV 的旧环境,可以切换 EdgeTTS 输出格式:
OPEN_REMOTE_SHOUTER_EDGE_TTS_FORMAT=wav ./OpenRemoteShouter切换为 WAV 后,程序也会继续尝试 paplay 和 aplay。LoongArch64 Old World ABI 1.0 打包脚本会默认使用 WAV。
如果某个播放器在当前桌面环境中退出成功但实际没有声音,可以临时指定播放器:
OPEN_REMOTE_SHOUTER_AUDIO_PLAYER=ffplay ./OpenRemoteShouter常见安装命令:
# Debian/Ubuntu
sudo apt install pulseaudio-utils alsa-utils ffmpeg
# Fedora
sudo dnf install pulseaudio-utils alsa-utils ffmpeg
# Arch Linux
sudo pacman -S libpulse alsa-utils ffmpeg如果没有可用播放器,控制台会显示语音后端错误,但文字喊话仍可使用。
程序会写入轻量级运行日志,用于排查 EdgeTTS 合成、音频缓存、播放器选择和播放器错误。
常见日志位置:
- 使用打包脚本启动:解压目录下的
logs/openremoteshouter.log - Windows:
%LOCALAPPDATA%\OpenRemoteShouter\OpenRemoteShouter.log - Linux/macOS:
~/.local/share/OpenRemoteShouter/OpenRemoteShouter.log
Linux/macOS 直接从终端运行主程序,或使用 ./run.sh --foreground 时,日志会同步输出到终端。也可以用 OPEN_REMOTE_SHOUTER_LOG_CONSOLE=1 强制开启控制台日志。
日志文件默认限制为 10 MiB,并保留最多 3 个轮转文件(例如 .1、.2、.3)。可以按部署环境调整,单位分别是字节和轮转文件数量:
export OPEN_REMOTE_SHOUTER_LOG_MAX_BYTES=10485760
export OPEN_REMOTE_SHOUTER_LOG_MAX_FILES=3程序还会限制 TTS 缓存默认最多 256 MiB、512 个音频文件;缓存只保留当前目录中的程序生成音频,超过限制时优先删除最旧文件。可用以下环境变量调整:
export OPEN_REMOTE_SHOUTER_TTS_CACHE_MAX_BYTES=268435456
export OPEN_REMOTE_SHOUTER_TTS_CACHE_MAX_FILES=512单次 TTS WebSocket 消息和音频响应也有 16 MiB 上限,异常或失控的上游响应不会无限占用内存。
无效或过小的值会回退到安全默认值。缓存和日志的限额只影响持久化文件,不会改变文字喊话功能。
管理员调用 GET /api/status 会看到实际使用的 logFilePath 字段;普通用户会看到脱敏提示。控制台窗口出现语音错误时,也会显示日志路径。
如果 Linux x64 或龙芯平台 TTS 没有声音,请优先查看日志中的 Audio backend candidates、Trying audio player、Audio player failed 和 EdgeTTS synthesis completed。
龙芯旧世界构建参考 ClassIsland 的 X11 兼容策略:
- 默认启用 Avalonia 软件渲染。
- 默认设置
LIBGL_ALWAYS_SOFTWARE=1、GALLIUM_DRIVER=llvmpipe和AVALONIA_RENDERING_FORCE_SOFTWARE=1。 - 默认禁用 DBus 菜单和 DBus 文件选择器。
OPEN_REMOTE_SHOUTER_X11_ENABLE_IME=auto会自动检测 Fcitx DBus;没有可用 Fcitx 时禁用 IME,避免 X11 输入法链路异常影响 UI。- 默认继续使用 WAV EdgeTTS 输出,减少旧环境音频解码依赖变化。
可手动覆盖:
OPEN_REMOTE_SHOUTER_SOFTWARE_RENDERING=0 ./run.sh --foreground
OPEN_REMOTE_SHOUTER_X11_ENABLE_IME=1 ./run.sh --foreground服务启动后可访问:
GET /:网页喊话表单GET /api/auth/state:当前登录/初始化状态POST /api/auth/login:登录并建立会话POST /api/auth/logout:退出当前会话POST /api/auth/password:修改当前账户密码GET /api/status:服务状态GET /api/voices:可用语音列表POST /api/shout:发送喊话POST /api/close:关闭当前显示GET/POST/PUT/DELETE /api/users:管理员用户管理
除登录和首次初始化外,修改类 API 需要同时发送登录 Cookie 和 X-OpenRemoteShouter-CSRF 令牌。登录响应中的 state.csrfToken 就是当前会话令牌。下面是一个不会把密码直接写进命令行参数的 curl 示例(需要 jq):
set -eu
umask 077
base_url=http://127.0.0.1:21212
cookie_file="$(mktemp)"
trap 'rm -f "$cookie_file"; unset ORS_PASSWORD' EXIT
read -r -s -p 'Password: ' ORS_PASSWORD
printf '\n'
login_json="$(jq -n --arg username 'admin' --arg password "$ORS_PASSWORD" \
'{username: $username, password: $password}')"
login_response="$(curl --fail-with-body -sS -c "$cookie_file" \
-H 'Content-Type: application/json' \
-X POST "$base_url/api/auth/login" -d "$login_json")"
csrf_token="$(printf '%s' "$login_response" | jq -r '.state.csrfToken')"
curl --fail-with-body -sS -b "$cookie_file" \
-H 'Content-Type: application/json' \
-H "X-OpenRemoteShouter-CSRF: $csrf_token" \
-X POST "$base_url/api/shout" \
-d '{
"title": "通知",
"message": "这是一条远程喊话。",
"mode": "fullscreen",
"durationSeconds": 10,
"topmost": true,
"speechEnabled": true,
"voiceName": "zh-CN-XiaoyiNeural",
"speechRate": 0,
"speechVolume": 1.0,
"theme": "cyan"
}'如果服务启用了 HTTPS,将 base_url 改为 https://主机名:21212,并按证书部署策略配置 curl 的证书校验。首次初始化可以在本机直接完成,或者通过白名单中的可信中转完成;远程 curl 需要额外发送 X-OpenRemoteShouter-Setup-Token 请求头。
字段说明:
| 字段 | 说明 |
|---|---|
title |
保留用于兼容旧客户端;服务端会统一显示为“(显示名称)发送了一条消息” |
message |
喊话内容,必填 |
mode |
保留用于兼容旧客户端,当前始终按 fullscreen 显示 |
durationSeconds |
保留用于兼容旧客户端;实际显示时长由 TTS 音频时长决定,至少 10 秒 |
topmost |
是否置顶 |
speechEnabled |
是否语音播报 |
voiceName |
EdgeTTS 语音,如 zh-CN-XiaoyiNeural |
speechRate |
语速,范围 -100 到 100 |
speechVolume |
音量,范围 0.0 到 1.0 |
theme |
cyan、cyan-dark、blue、blue-dark、green、green-dark、amber、amber-dark、rose、rose-dark、violet、violet-dark、indigo、indigo-dark、magenta、magenta-dark、orange、orange-dark、emerald、emerald-dark |
GitHub Actions 的 Build OpenRemoteShouter workflow 会构建并上传:
OpenRemoteShouter-portable-net8.0OpenRemoteShouter-win-x64OpenRemoteShouter-win-x86OpenRemoteShouter-win-arm64OpenRemoteShouter-linux-x64OpenRemoteShouter-linux-arm64OpenRemoteShouter-linux-armOpenRemoteShouter-linux-musl-x64OpenRemoteShouter-linux-musl-arm64OpenRemoteShouter-osx-x64OpenRemoteShouter-osx-arm64OpenRemoteShouter-linux-loongarch64-oldworld-abi1.0OpenRemoteShouter-all-platforms(CI 内部汇总包)
GitHub Release 会将每个平台包作为独立附件列出,文件名对应目标平台;同时提供 SHA256SUMS.txt,Release 正文中也会列出相同的 SHA256 校验值。CI 仍会保留 OpenRemoteShouter-all-platforms 汇总包用于流水线内部校验,但它不会作为公开 Release 附件发布。
OpenRemoteShouter-linux-loongarch64-oldworld-abi1.0.tar.gz 仅用于 LoongArch64 Old World ABI 1.0 系统。
需要安装 .NET 8 SDK。
dotnet restore
dotnet build RemoteShouter.sln -c Release
dotnet publish RemoteShouter.csproj -c Release -r win-x64 --self-contained true替换 -r 后的 Runtime Identifier 可以构建其他平台,例如 linux-x64、linux-arm64、osx-arm64。
- EdgeTTS 需要联网访问微软语音服务。
- 全屏置顶效果受 Linux 桌面环境和窗口管理器影响。
- Linux 下语音播放依赖系统播放器。
- 除 Windows 和 LoongArch64 Old World ABI 1.0 外,其他平台构建尚未实机测试。
- macOS 首次运行可能需要在系统安全设置中允许该程序运行。
- Windows 可能需要让防火墙放行,检查网络类型设置为“专用网络”




