# poker-timer **Repository Path**: IvanYue/poker-timer ## Basic Information - **Project Name**: poker-timer - **Description**: No description available - **Primary Language**: HTML - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-20 - **Last Updated**: 2026-10-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # poker-timer · 扑克比赛计时多端系统 局域网多房间扑克比赛计时器。一个**零依赖 Node.js 后端** + 三个**纯原生 HTML/JS 前端**(总控 / 子控 / 大屏),支持多房间隔离、实时同步(SSE)、盲注/级别/筹码/报名管理,以及**大屏本地语音播报**(内置离线神经语音,含 8 种中文音色)。 ## 技术栈 - 后端:Node.js 原生 `http` 模块,**零 npm 依赖**,纯 API + SSE + 静态托管。 - 前端:原生 HTML/CSS/JS,无框架、无构建步骤,浏览器直接打开即可调试。 - 语音:两套**端侧离线神经 TTS**(Piper VITS + Kokoro-82M),模型已下载到本地 `models/`。 ## 目录结构 ``` poker-timer/ ├── server.js # 后端:API + SSE + 静态托管 + 模型本地化路由(零依赖) ├── master.html # 总控端(Windows 网页,管理房间/编辑/发播报指令) ├── sub.html # 子控端(PWA,计时控制:暂停/继续/重置) ├── display.html # 大屏端(只读,渲染 + 语音播报) ├── manifest.webmanifest # 子控 PWA 清单 ├── sw.js # 子控 PWA Service Worker(离线壳) ├── icons/ # PWA 图标(192/512 PNG) ├── models/ # 本地 TTS 模型(Kokoro-82M,约 88MB,含 8 中文音色) ├── lib/ # 语音引擎库(可选,用于完全离线) │ ├── kokoro.min.js # Kokoro TTS 引擎(需手动下载或打包生成) │ ├── vits-web.min.js # VITS Web 引擎(需手动下载或打包生成) │ └── README-BUILD.md # 离线化说明 ├── rooms.json # 房间数据(运行时自动生成,已 gitignore) ├── README.md # 本文档 └── design.md # 架构 / API / 协议 / 数据模型(详见) ``` ## 快速开始 ```bash # 1. 启动后端(首次运行会自动生成 rooms.json 并播种默认房间 default) node server.js # 可选环境变量: # PORT=4000 监听端口(默认 4000) # ADMIN_CODE=admin 管理码(默认 admin) ``` 启动后访问(同一台电脑或局域网内任意设备浏览器): | 端 | 地址 | 说明 | |---|---|---| | 总控 | `http://<服务器IP>:4000/master.html` | 输管理码 `admin` 进入,管理房间 | | 子控 | `http://<服务器IP>:4000/sub.html` | 输房间 ID + 子控码进入 | | 大屏 | `http://<服务器IP>:4000/display.html` | 输房间 ID 进入(语音播报端) | > `<服务器IP>` 在 server.js 启动日志里会打印(本机用 `localhost`)。总控登录后可在「总控码 / 子控码」处查看并复制对应码。 ## 三端分工 | 端 | 文件 | 职责 | 发声 | |---|---|---|---| | 总控 | master.html | 登录、创建/删除/重命名房间、编辑盲注/标题/筹码/报名/音色、发「开始比赛」「播报公告」指令、**试听音色** | ✅(仅试听) | | 子控 | sub.html | 用子控码登录,控制当前级别倒计时(暂停/继续/重置) | ❌ | | 大屏 | display.html | 只读渲染大屏画面,接收 `announce` 事件并**本地语音播报完整内容** | ✅(完整播报) | - 总控「开始比赛」会同时:发播报指令给大屏 + 写入赛局开始时间 + 启动级别倒计时。 - 主控可试听音色(短语音),大屏进行完整播报(包括级别升级、比赛开始等)。 ## 语音系统 ### 引擎和音色 - **Kokoro-82M**(推荐):8 种中文音色(4 女 4 男),音色 ID 格式 `kokoro:zf_xiaoxiao` - **Piper VITS**:华研女声 2 档(中等/极简质量),音色 ID 格式 `piper:zh_CN-huayan-medium` - 默认音色:`kokoro:zf_xiaoxiao`(晓晓女声) ### 本地化方案 **当前方案:智能回退(推荐)** 代码已配置为**优先从本地 `lib/` 加载引擎库,失败则回退到 CDN**: - 如果 `lib/kokoro.min.js` 和 `lib/vits-web.min.js` 存在 → 使用本地引擎(完全离线) - 如果本地文件不存在 → 从 `cdn.jsdelivr.net` 加载(需联网,首次后浏览器会缓存) **模型文件已本地化**:Kokoro 模型在 `models/` 目录,`server.js` 的 `/hf/*` 路由会优先读取本地文件,前端已内置 `huggingface.co → /hf` 的 fetch 拦截。 ### 完全离线化(APK/生产环境) 如需将引擎库也打包到本地(用于 Android APK 或无网环境): **方法 A:使用 Vite 打包(推荐)** ```bash # 1. 安装依赖 npm install vite kokoro-js @diffusionstudio/vits-web # 2. 打包(会将所有依赖打包到 dist/ 目录) npx vite build # 3. dist/ 目录中的文件即为完全离线版本 ``` 打包后的代码会自动将引擎库内联,无需 CDN。 **方法 B:手动下载(不推荐)** 由于这两个库是纯 ESM 模块,无法直接下载单个文件。如果坚持手动操作: 1. 安装 npm 包:`npm install kokoro-js @diffusionstudio/vits-web` 2. 从 `node_modules/` 中提取编译后的文件到 `lib/` 目录 3. 注意需要保持模块的依赖关系 **推荐使用方法 A 进行打包,更简单可靠。** ## 部署 - **子控 PWA**:Chrome/Edge 打开 sub.html → 菜单「安装应用/添加到主屏」。 - **主控**:Windows 直接用浏览器打开;要 exe 可用 Nativefier/Electron 或 `chrome --app=...` 封装。 - **大屏 Web**:浏览器打开 display.html,全屏投屏到电视/投影仪。 - **大屏 APK**:使用 Capacitor 打包成 Android APK,安装在小米电视等设备上(见下方)。 ### 打包成 Android APK(适用于小米电视等) ```bash # 1. 安装 Capacitor 和依赖 npm install @capacitor/core @capacitor/cli @capacitor/android npm install vite kokoro-js @diffusionstudio/vits-web # 2. 初始化项目 npx cap init # 3. 添加 Android 平台 npx cap add android # 4. 打包 Web 资源(会将引擎库打包进去) npx vite build # 5. 同步到 Android 项目 npx cap sync # 6. 在 Android Studio 中打开并构建 APK npx cap open android ``` 打包后的 APK 可以安装在小米电视、Android TV 等设备上,**完全离线运行,无需网络**。 ## 常见问题 - **改了前端不生效**:前端是静态文件,刷新浏览器即可(无需重启后端)。只有 `server.js` 改动才需重启。 - **试听/播报没声音**: - 首次需联网下载引擎库(或提前打包到 `lib/`) - 模型文件已在 `models/` 目录,确认 `server.js` 已启动 - 打开浏览器控制台查看是否有报错 - 确认浏览器支持 Web Audio API(Chrome/Edge/Safari 最新版) - **房间数据重置**:删除 `rooms.json` 后重启,会重新播种默认房间。 - **APK 安装失败**:小米电视需要在「设置」中开启「允许安装未知来源应用」。 - **语音加载慢**:首次加载需要下载引擎库和模型(约 100-150MB),建议使用打包后的离线版本。