# Sport-HUD运动会直播悬浮窗 **Repository Path**: codekpy/Sport-HUD ## Basic Information - **Project Name**: Sport-HUD运动会直播悬浮窗 - **Description**: Sport-HUD运动会直播悬浮窗 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-30 - **Last Updated**: 2026-10-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 运动会实时直播 HUD 给 OBS 用的运动会成绩实时图文(HUD)。一个 Go 二进制搞定后端与全部页面, 控制端在另一台设备上操作,画面实时同步到 OBS。 ``` ┌─────────────┐ 指令 ┌───────────────┐ 广播 ┌──────────────────┐ │ 控制端 │ ────────► │ 后端(Go) │ ────────► │ 渲染端(OBS) │ │ 导播设备 │ WS │ 唯一权威状态 │ WS │ 透明背景图层 │ └─────────────┘ └───────────────┘ └──────────────────┘ 控制端 / 渲染端 / WS / 静态资源全部由一个进程提供 ``` ## 特性 - **一个进程,零依赖**:前端资源编译进二进制,拷到直播机双击即可运行 - **透明底渲染端**:只有组件可见,其余区域 alpha 为 0,直接叠在摄像头/画面上 - **实时同步**:控制端发指令 → 服务端为唯一权威 → 广播到所有渲染端 - **状态不丢**:自动持久化,服务重启 / OBS 刷新 / 电脑重启都能恢复 - **转播级图形**:仿奥运转播构图——校徽+校名 bug、事件 chip、参赛名单板、RESULT 风格成绩表(名次琥珀块 + PB/SB/NR 徽章) - **固定场景模板**:开幕式 / 跑步 / 跳高 / 铅球四个场景,各带一套组件与位置模板;切换场景时选择对应赛事 - **草稿发布**:内容与版式先存本地草稿、预览实时可见,点「发布上屏」一次性推送到 OBS;场景切换 / 成绩弹窗 / 时钟为实时操作 - **最终成绩弹窗**:控制端一键展示/关闭,磨砂居中弹窗(真实 backdrop-filter),按名次展示完整成绩 - **组件可开关 + 固定锦点(锚点)**:每个组件可在 2–3 个固定位置间切换,支持显隐、缩放与每项目可见行数 - **校徽双通道**:图片上传(内容哈希暂存 `/media/`)或 URL - **控制端实时预览**:右下角内嵌一块与 OBS 完全同源的实时画面,可放大全屏 / 收起为小按钮;草稿改动即时可见,无需切到 OBS 窗口 - **运行时换主题色**:5 套内置配色,改一处 token 即可全局生效 - **数据源可插拔**:本期手工录入,接口与写入端点已预留,后续对接比赛数据系统**无需改渲染端** ## 快速开始 ```powershell # 1. 构建(打包渲染端 + 编译后端) powershell -ExecutionPolicy Bypass -File scripts\build.ps1 # 2. 启动 powershell -ExecutionPolicy Bypass -File scripts\run.ps1 ``` 启动后终端会打印两个地址: - **控制端** `http://<局域网IP>:8080/control` — 导播在另一台设备上打开 - **渲染端** `http://127.0.0.1:8080/render` — 填进 OBS 的浏览器源 详细步骤见 **[docs/OBS-SETUP.md](docs/OBS-SETUP.md)**。 > 环境要求:Go 1.22+(构建后端)、Node 20+ 与 pnpm(构建渲染端)。 > 只有运行二进制时才不需要任何运行时。 ## 开发 ```powershell # 后端读磁盘前端资源(改控制端刷新即可)+ Vite 热更新(改渲染端自动刷新) powershell -ExecutionPolicy Bypass -File scripts\dev.ps1 ``` | 命令 | 说明 | |---|---| | `scripts\build.ps1` | 构建渲染端并编译带内嵌资源的后端,输出到 `bin\obs-hud.exe` | | `scripts\build.ps1 -SkipFrontend` | 只重编后端(前端产物已是最新时用) | | `scripts\dev.ps1` | 开发模式:后端 `-webdir web` + Vite 热更新 | | `scripts\run.ps1` | 运行已构建的二进制 | ### 测试与检查 ```powershell go vet ./... && go test ./... # 后端单测(状态引擎 / 时钟 / 名次 / 持久化 / WS 协议) cd render-app; pnpm run typecheck # 渲染端类型检查 ``` ## 目录结构 ``` cmd/server/ 启动、路由、参数 internal/ state/ 权威状态:指令应用、名次计算、时钟、持久化 hub/ WebSocket 连接管理、广播、心跳、协议实现 datasource/ 数据源适配层(Provider 接口 + /api/ingest 预留端点) web/ embed.go 把前端资源编译进二进制 control/ 控制端(原生 HTML/CSS/JS,零构建) render/ 渲染端构建产物(由 pnpm build 生成,已 gitignore) index.html 运维首页(显示状态与接入步骤) render-app/ 渲染端源码(Vite + Vue 3 + TypeScript) src/styles/tokens.css **唯一的配色与排版真相**,换主题只改这里 src/components/ 标题栏 / 多项目成绩 / 比赛事件 / 时钟 / 滚动赛事快报 scripts/ 构建、开发、运行脚本 docs/PROTOCOL.md **通信协议(冻结契约)**,三端实现均以此为准 docs/OBS-SETUP.md OBS 接入与现场操作手册 data/ 运行时状态(gitignore) ``` ## 换主题色 所有颜色都在 [render-app/src/styles/tokens.css](render-app/src/styles/tokens.css) 里, 每个主题一个块,只改三个值: ```css [data-theme="azure"] { --accent: oklch(70% 0.16 245); /* 主强调色 */ --accent-ink: oklch(18% 0.04 245); /* 落在强调色实底上的文字 */ --accent-soft: oklch(70% 0.16 245 / 0.16); } ``` 新增主题:复制一个块、改 id,控制端的主题列表会自动出现该项。 **组件代码一行都不用动。** 当前内置:`azure` 电光蓝 · `amber` 活力橙 · `magenta` 霓虹品红 · `lime` 运动绿 · `mono` 中性银。 ## 接入比赛数据系统 本期所有数据由控制端手工录入。后续对接时**渲染端无需改动**,两条路径任选: 1. **服务端拉取** —— 实现 `internal/datasource.Provider`(`http.go` 里已有桩与说明), 把外部数据转换成协议指令,走同一条状态通道。 2. **外部推送** —— 配置 `ingestToken` 后启用 `POST /api/ingest`: ```http POST /api/ingest Authorization: Bearer Content-Type: application/json { "action": "results.upsertRow", "payload": { "row": { "name": "张伟", "value": "11.32", "place": 1 } } } ``` 出于安全考虑,该端点**只允许数据类动作**(项目 / 积分 / 成绩 / 事件栏), `visibility` `/` `theme` `/` `clock` 等导播类动作一律拒绝,避免外部系统的 bug 直接改乱直播画面。 细节见 [docs/PROTOCOL.md](docs/PROTOCOL.md) §9。 ## 配置 可选,放在 `data/config.json`(不存在则全部走默认值): ```json { "addr": ":8080", "ingestToken": "", "provider": "manual", "logLevel": "info" } ``` 命令行参数优先于配置文件: | 参数 | 默认 | 说明 | |---|---|---| | `-addr` | `:8080` | 监听地址 | | `-data` | `data` | 数据目录(`state.json` / `config.json`) | | `-webdir` | 空 | 从磁盘读前端资源,开发用 | | `-token` | 空 | 启用 `/api/ingest` 的令牌 | | `-debug` | false | 输出调试日志 | ## 许可 内部项目。