Skip to content

Latest commit

 

History

22 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CueWeave · 流光提词器

CueWeave 是一个支持多设备实时同步的网页提词器。可以用电脑显示提词画面,用手机或平板编辑文稿、控制播放和调整进度。

功能概览

  • Node.js + WebSocket 局域网实时同步,按房间增量持久化,无需外部数据库即可运行。
  • 扫描二维码或打开邀请网址自动加入,无需手动输入房间号。
  • 支持自由协作、权限协作和导播三种房间模式。
  • 邀请链接直接区分查看、编辑、导播和纯显示权限,扫码后的能力与邀请文案一致。
  • 文稿、排版、播放状态、速度和定位线行锚点实时同步。
  • 桌面、手机和平板使用统一分行,定位线始终对应同一行文字。
  • 自动滚动、手动滚动和跨设备跟随均采用平滑动画,并可翻转为文字从上方出现、向下滚动。
  • 每台设备可选择跟随房间镜像,或使用仅作用于本机的镜像设置。
  • 房间快照持久化,支持断线重连、房主宽限期恢复和自动移交。
  • 文稿使用独立版本号防止多台编辑设备静默互相覆盖,冲突稿自动进入本机备份。
  • 播放或全屏时会尝试保持屏幕常亮,并在同步中断时直接在提词画面提示。
  • 支持“开始直播”锁定文稿和画面,避免现场误改导致所有显示端重排。

启动

需要 Node.js 18 或更高版本。

npm install
npm start

浏览器访问 http://localhost:17321。同一局域网内的其他设备访问:

http://运行服务的电脑局域网IP:17321

macOS 可以在“系统设置 → 网络”中查看局域网 IP。端口冲突时可以更换端口:

PORT=17322 npm start

直接双击 index.html 仍然可以作为纯本地提词器使用,但无法使用多设备同步。

多设备同步

  1. 打开首页后先选择“新建房间”、“加入房间”或“仅自己使用”;也可直接进入最近房间。入口弹窗不会因误点遮罩或按下 Esc 关闭。
  2. 填写设备名称、设备界面偏好和房间模式。
  3. 进入后网址会变为 /room/房间码;让其他设备直接扫描二维码或打开邀请网址。
  4. 对方会自动加入,无需填写房间码或再次确认;六位房间码仅作为备用方式。
  5. 房主选择“查看邀请、编辑邀请、导播邀请或显示邀请”后再分享二维码;邀请中包含不可猜测的权限令牌,扫码设备直接获得对应权限。
  6. 开播前确认在线设备和权限,点击“开始直播并锁定文稿”;直播期间仍可播放、调速和定位,但不能修改文稿或画面。
  7. 结束直播后播放会暂停,文稿和画面重新开放编辑。房主仍可在设备列表中调整角色和界面用途。

当前浏览器会保存最近 20 个房间的设备恢复凭证,回到首页后可选择恢复原身份。从最近列表移除记录不会删除服务器房间。如果浏览器数据被清理,仍可通过原链接或房间码重新加入,但无账号模式下无法自动证明原房主身份。

房主可以从设备列表移除不再使用的离线设备。普通成员主动退出房间时,其恢复凭证会同时从服务器成员列表移除;长期离线成员默认保留 30 天,房主身份不会被自动清理。

当房主通过 localhost127.0.0.1 打开页面时,Node 服务会读取服务器自身的局域网 IPv4并用于二维码,不会误用浏览器所在设备的地址。通过域名或公网地址访问时,邀请链接会保留当前域名。

房间模式

  • 自由协作(默认):除显示端外,普通加入的设备默认都可以编辑文稿和画面、控制播放和滚动;房主仍可将单个成员改为编辑者、操作者或查看者。
  • 权限协作:房主为设备分配编辑者、操作者或查看者角色。
  • 导播模式:严格按照角色拆分编辑和播放控制权限。

设备界面用途

  • 控制端:显示完整提词、设置和房间管理界面。
  • 编辑端:优先展示文稿编辑能力;实际权限来自邀请或房主调整。
  • 导播端:优先展示播放控制能力;实际权限来自邀请或房主调整。
  • 显示端:只显示提词画面,隐藏房间设置、编辑和播放控件;仍可通过右上角半透明面板切换本机镜像。

手机控制端采用窄屏布局,设置栏可以独立横向滑动,不会撑宽或裁切整个页面;回到开头和专注模式收纳在播放栏右侧的更多菜单中;手机和平板横屏时会按可视高度切换紧凑布局,确保提词区和播放栏完整显示;手机显示端会铺满可视区域并适配浏览器动态工具栏。

角色权限

  • 房主:拥有全部权限,可以管理房间、设备和角色。
  • 协作者:在自由协作房间中可以编辑文稿和画面、控制播放和滚动。
  • 编辑者:可以编辑文稿和画面设置。
  • 操作者:可以播放、暂停、调速和调整进度。
  • 查看者:只能接收并显示同步内容。

前端会隐藏或禁用无权操作的控件,服务端还会再次校验每条修改消息,不能通过浏览器控制台绕过权限。

房主离线与房间生命周期

  • 房主断线后保留身份 60 秒,刷新或网络恢复后可以自动重连。
  • 超过 60 秒仍未回来时,优先把房主移交给在线编辑者,其次是操作者和普通查看者;显示端不会成为房主。
  • 原房主在移交后重新上线,会以编辑者身份回来,不会自动抢回控制权。
  • 所有设备离线后,房间和文稿默认永久保留,以便日后通过原房间链接恢复。
  • 房主可以主动关闭并立即销毁房间。
  • 每个房间分别保存在 data/rooms-v4/房间码.json,服务重启后仍可恢复;播放状态在重启后自动暂停。
  • 普通文稿、画面和播放进度变化先标记为待保存,默认最多每 5 秒只写入发生变化的房间;创建/销毁房间、直播状态、暂停或跳转、权限变更、成员移除以及服务关闭会立即保存。
  • 每个房间成功保存前会保留自己的 .bak 备份;启动时会清理中断写入留下的临时文件,单个房间主快照损坏时自动尝试其备份。
  • 如果需要定期清理,可通过 EMPTY_ROOM_TTL_MS 设置空房间保留毫秒数。

同步内容

  • 提词文稿
  • 字号、行距、字距和阅读宽度
  • 背景色、文字色、定位线、房间镜像及滚动翻转设置
  • 播放、暂停、速度和回到开头
  • 归一化滚动进度
  • 房间模式、角色、设备用途和在线状态

跨屏统一排版

提词画面采用基于容器宽度的相对单位(cqw),字号和字距会随提词区域等比缩放。文稿还会经过确定性分行,同一份字号、字距和阅读宽度设置在电脑、手机和平板上会生成完全相同的每行内容,而不是由各系统自行换行。

滚动同步使用“定位线当前穿过的文稿行坐标”作为锚点,而不是只发送整篇文章的滚动百分比。因此不同高度、不同宽高比的设备会让同一行文字经过各自相同比例位置的定位线;自动滚动速度也按提词区域宽度等比换算,保持一致的行进节奏。

每台设备可独立选择是否“跟随房间镜像”。跟随时,拥有画面编辑权限的设备修改镜像会同步给全房间;关闭跟随后,左右和上下镜像只保存在当前浏览器,不广播,也不受房间镜像变化影响。纯显示端可触碰右上角的半透明本机镜像面板进行切换。

播放时各设备都以设置的可见速度连续滚动,控制设备每 400ms 左右发送一次进度锚点。显示端只在有限范围内小幅加减速来追赶误差,不会因手机和电脑的文稿高度比例而降到近乎静止,也不会在播放期间周期性硬改位置;主动跳转或暂停时才精确定位。

自动滚动使用独立的高精度浮点位置累加,再写入浏览器滚动容器,低速不会因为高刷新率屏幕或浏览器对 scrollTop 的像素取整而失效。

开启“滚动翻转”后,文稿仍按原有顺序阅读,但文字改为从画面上方出现并向下移动;回到开头、定位线锚点和多设备进度同步也会同时切换方向。

自动滚动过程中仍可使用鼠标滚轮、触控板、触摸手势或滚动条手动定位。手势期间自动滚动会暂时让出位置控制,并以约 20 帧/秒持续同步进度;其他设备通过逐帧追随动画自然移动到新位置。松手后各端平滑收敛,并从新的位置继续自动滚动。

环境变量

变量 默认值 说明
HOST 0.0.0.0 HTTP/WebSocket 监听地址
PORT 17321 服务端口
OWNER_GRACE_MS 60000 房主断线后的身份保留时间
EMPTY_ROOM_TTL_MS 0 全员离线后的房间保留毫秒数;0 表示永久保留
OFFLINE_MEMBER_TTL_MS 2592000000 非房主离线设备保留时间;0 表示永久保留
PERSIST_INTERVAL_MS 5000 普通状态变化合并落盘的最大间隔,最低 1000ms
MAX_ROOMS 1000 服务端最多保留的房间数
MAX_MEMBERS_PER_ROOM 50 单个房间最多保留的设备数
ATTEMPT_WINDOW_MS 60000 按来源地址统计创建/加入尝试的时间窗口
MAX_ATTEMPTS_PER_IP 120 单个时间窗口内允许的创建/加入次数
MAX_SOCKET_BUFFER_BYTES 1048576 单个慢连接允许积压的发送字节数;临时进度会丢弃,可靠消息会要求重连
TRUST_PROXY false 仅在可信反向代理会清洗请求头时启用 X-Forwarded-For
ALLOWED_ORIGINS 当前访问域名 额外允许建立 WebSocket 的 Origin,多个值用逗号分隔
ROOM_DATA_DIR data/rooms-v4 v4 房间增量快照目录

文稿备份与版本冲突

  • 全文编辑器支持导入、导出以及最近 10 份本机稿件备份;大稿件备份存入 IndexedDB,不再挤占 localStorage
  • 停止输入 30 秒后保存一份去重备份;清空、重置、导入和恢复前也会先备份当前稿件。
  • 每次文稿修改必须携带当前 scriptRevision。版本过期或缺失时,服务端拒绝覆盖并返回最新快照;被拒绝的文稿自动保存为“同步冲突”本机备份。
  • v4 同步协议、邀请令牌和按房间快照不兼容旧版本。旧的 data/rooms.json 不会读取;浏览器使用全新的 v4 本地存储键,不会恢复旧房间身份。

公网部署

公网环境应在 Node.js 服务前配置 Nginx、Caddy 或同类反向代理:

  • 启用 HTTPS,浏览器将自动使用 wss://
  • 正确转发 WebSocket 的 UpgradeConnection 请求头。
  • 限制 data/rooms-v4/ 的文件访问权限并定期备份。
  • 不要把 Node.js 服务端口直接暴露到公网。
  • 静态页面默认返回 CSP、Referrer-Policy、禁止 MIME 嗅探和同源嵌入策略;WebSocket 默认只接受与访问页面同域的 Origin。

当前版本使用房间码作为加入凭证,适合可信团队和局域网使用。如果用于公开互联网或保存敏感文稿,建议继续增加账户登录、房间密码、邀请审批和操作审计。

项目结构

文件 说明
server.js HTTP、WebSocket、房间权限、直播锁定、生命周期和增量持久化服务
sync-client.js 浏览器端房间连接、重连、邀请和权限界面
app.js 提词器状态、统一排版、滚动与本机镜像逻辑
index.html / styles.css 页面结构和响应式界面
test/ WebSocket、权限、生命周期及同步集成测试
data/rooms-v4/ 默认房间快照目录,运行时按房间自动维护

本地功能

  • 提词稿实时预览与浏览器本地自动保存
  • 全文编辑和双击文字原位修改
  • 自动滚动、播放/暂停、速度微调和回到开头
  • 鼠标滚轮、触控板及滚动条手动定位
  • 字号、行距、字距、阅读宽度和定位线调整
  • 背景色、文字色、镜像、滚动翻转、专注模式和全屏
  • 手机和平板进入全屏或专注模式后,可通过提词画面右上角的悬浮按钮直接退出
  • 快捷键:Space 播放/暂停,/ 调速,R 回到开头,F 专注模式,Enter 全屏

检查

npm run check
npm test

测试会启动隔离的临时 Node.js 服务并模拟多台 WebSocket 设备,覆盖三种房间模式、四种设备用途、权限变更、状态与播放锚点同步、房主断线重连与移交、主动关房、空房默认保留与可选过期、服务重启、异常消息、超大消息及同一设备多开页面接管。

已执行的真实浏览器回归还包括桌面/手机布局、二维码邀请自动加入、低速滚动、自动滚动期间手动接管、连续平滑跟随、跨尺寸统一分行、定位线行锚点、设备独立镜像和断线自动恢复。

About

支持多设备实时同步、角色权限与远程控制的网页提词器。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages