- TypeScript 68.1%
- Go 27.3%
- CSS 3.5%
- Python 0.8%
- JavaScript 0.2%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| cmd/e2e | ||
| demo | ||
| deploy | ||
| docs | ||
| frontend | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| chat_objects.go | ||
| chat_temporary.go | ||
| codec_compatibility.go | ||
| control_flow_test.go | ||
| database.go | ||
| device_scans.go | ||
| device_scans_test.go | ||
| e2ee.go | ||
| e2ee_test.go | ||
| go.mod | ||
| go.sum | ||
| HANDOFF.md | ||
| http.go | ||
| ice_diagnostics.go | ||
| logging.go | ||
| main.go | ||
| maintenance.go | ||
| media.go | ||
| media_actions.go | ||
| media_actions_test.go | ||
| meeting_policy.go | ||
| meeting_policy_test.go | ||
| messaging.go | ||
| messaging_test.go | ||
| permissions.go | ||
| permissions_test.go | ||
| README.md | ||
| reception.go | ||
| reception_test.go | ||
| rooms.go | ||
| server_diagnostics.go | ||
| server_diagnostics_test.go | ||
| server_test.go | ||
| start.sh | ||
| V2-PLAN.md | ||
| v2.go | ||
| v2_test.go | ||
| websocket.go | ||
Hola 2.1 私人会议
Hola 是面向个人使用的 Web 视频会议,采用 Go、React/TypeScript、SQLite 和 LiveKit。服务器只转发媒体,不进行转码。
- 入口:meet.cloverdo.cn
- 仓库:Cloverdo/Hola,开发分支
dev - 本次更新:2026-11-03;实际发布版本、验证结果与备份路径见 HANDOFF.md
- 部署方式:Linux 宿主机 + systemd,暂不使用 Docker;暂不开发 Android APP
聊天模块
消息和会议共用账号与导航。普通单聊、群聊、好友关系和历史保存在 SQLite,普通附件经后端流式转发到私有 S3,单文件最多 200 MiB。配置项见 .env.example,S3 地址必须可从运行 Go 服务的主机访问。
管理员可邀请成员创建 1 小时的临时 E2EE 房。首版每房最多 8 人,内容预算 200 MiB,其中为文字保留 2 MiB。所有临时房状态、密文和封装恢复材料仅驻内存。新设备需核对安全码,刷新可由获准设备协助,或在浏览器本地输入恢复码。到期、结束或进程重启清理房间。
新功能的隔离浏览器回归使用 playwright.messaging.config.ts。真实对象存储回归可在配置 S3 环境变量后运行 HOLA_TEST_RUSTFS=1 go test -run TestMessagingFriendsGroupPermissionsAndAttachments,测试创建并清理独立的测试对象。
2.1.2 E2EE 发起权限
仅平台账号管理员可创建 E2EE 会议,普通用户可通过设备检查和安全码批准后加入。前后端同步限制;主持人、联席身份不会额外获得发起权限。移除会议举手按钮、成员标记及消息处理。
2.1.1 统一开关
所有原勾选框统一为胶囊开关,包括创建会议的 E2EE、私密会议、设备安全码核对和管理员身份设置;支持禁用、键盘操作与亮暗主题。沿用原有权限和确认规则。验证见 QA-2.1.1.md。
2.1.0 E2EE
管理员创建会议时可选 E2EE,默认 H.265,可手动改为 H.264;不支持 AV1。设备检查会静默预检浏览器、Worker 和 Web Crypto,不额外申请摄像头或麦克风权限。只有通过预检且支持所选视频方案的设备能创建或加入 E2EE 会议,不提供邀请链接。
首次加入需要双方通过可信渠道核对 E2EE 安全码,再由主持人或联席主持人的主设备批准。摄像头、麦克风、共享画面与共享声音使用 E2EE,服务器仅转发;名单、文字聊天及控制消息仍由服务器处理。支持状态可以从会中顶栏 E2EE 面板查看。
每分钟、设备成员变化、主持控制权转移或手动点击“立即更新 E2EE”时,生成新的随机媒体材料。更新未完成时暂停媒体,不回退普通传输。设备身份保存在本站 IndexedDB 中,为不可导出的 Web Crypto 私钥,有效期144小时;清除站点数据、换浏览器或过期后需要重新核对。刷新页面可恢复仍有效的同一设备身份。
实现与使用边界见 E2EE.md,验证记录见 QA-2.1.0.md。
2.0.2 会议操作与布局
主持人离会时可选择仅离开当前设备或结束整个会议;会议管理结束操作增加确认。每个视频及预览均有视频信息、旋转、全屏操作。全屏顶栏依次为设备设置、视频信息、画面旋转、切换摄像头、退出全屏;摄像头选择使用单行布局,无备用摄像头时保留禁用按钮。用户管理保留自己账号的灰色停用按钮。首页会议与个人会议卡片等高对齐,三个快捷入口改为较矮的横向按钮。
2.0.1 界面修复
修复自测报告A1–A12并完成B1–B4:控件状态、长标题与窄屏、原会议入口、旋转完整适配、聊天跟随及新消息提示、顶栏提示避让、横屏主视角、弹窗层级、字段分组、重复日程日期和非法日期校验。手机月历使用预约数量,直播人数与设备数区分显示,时长格式统一。
全屏设备设置按需展开,快捷切换摄像头保留;视频信息与设备设置互斥展开。手机横屏采用主画面加侧边滚动预览。
浏览器界面回归:npm run test:ui,使用下方同名HOLA_V2环境变量;测试文件为 frontend/tests/ui-regressions.spec.ts。测试需使用隔离账号/环境,会创建临时会议与预约。
2.0 的变化
- 采用已确认 Demo 的 Hola 界面,支持亮色/暗色、收起侧边栏与手机导航。
- 个人空间包含会议大厅、日历日程、本人参与的历史会议;管理员的用户管理、会议管理独立分组。
- 设备、能力、诊断收进设置;会中成员、聊天、视频统计按需打开,再次点击收起。
- 下拉选择、确认、弹窗使用应用组件;弹窗四角保留圆角,内容可滚动但不显示滚动条。摄像头授权、系统共享来源和文件选择仍由浏览器/系统管理。
- 日历预约支持每日/每周重复、编辑、取消、复制预约信息及发起会议。预约不是提前开启的媒体房间,参会链接在实际会议中生成。
- 历史只展示本人发起或参与的会议,支持搜索、分页、个人备注、收藏和再次发起。备注、收藏和日程按账号隔离。
- 会议中生成邀请链接;已有账号登录后准备入会,无需再输入房间码和会议密码。链接绑定本次会议,结束或超时后失效,不授予主持权限。
- 会中聊天最多保留100条,每条最多1000字;只在当前进程内保存,服务重启后清除。
- 管理员可查看所有进行中的会议,包括私密会议,并一键结束;不自动获得会议主持或设备详情权限。
- 所有会议单次最长24小时,从创建开始计时,重新加入或重启服务不重置;空房间仍在30分钟后结束。
控制与媒体链路
flowchart LR
A[登录并上报浏览器能力] --> B[Go 校验账号和会议规则]
B --> C[WebSocket 下发角色和带版本的媒体策略]
C --> D[确认规则后申请 SFU 凭证]
D --> E[按需采集并经 LiveKit 转发]
E --> F[反馈实际编码与收发状态]
规则、权限、能力和执行反馈走业务接口与 WebSocket。业务状态及待同步媒体操作在同一 SQLite 事务保存,媒体调用在锁外执行;失败可重试,重启后继续处理。权限集中在 permissions.go 与 meeting_policy.go。平台账号管理员、会议主持人、联席主持人和普通成员分别授权。
同一账号可从多台设备加入并选择主设备。主持人/联席的设备管理与高画质资格随主设备转移;普通成员设置主设备不会增加权限。完整能力和兼容性汇总仅向有权限的主持/联席主设备下发,撤销角色后同步收回。
视频与设备规则
| 项目 | 当前方案 |
|---|---|
| 编码 | H.264、H.265、AV1;不支持 VP9,无自动换码或备用编码流 |
| 默认 | 1080p、30帧、H.264;可保存个人创建会议预设,加入已有会议服从主持人方案 |
| 摄像头 | 720p、1080p、2K(2560×1440),目标30/60帧 |
| 2K资格 | 仅主持人、联席主持人的主设备 |
| 其他设备 | 最高1080p60,不再因超过5台设备自动限制720p |
| 网络调节 | 仅降低发送帧率,最低15帧;保留分辨率,恢复后尝试回到目标帧率 |
| 屏幕共享 | 独立配置720p/1080p/2K/4K、30/60帧与三种编码,最高4K60 |
| 实际性能 | 受摄像头、浏览器、编解码实现和网络影响,目标不等于保证持续达到的性能 |
首次登录只读取浏览器声明的编解码能力和可枚举设备,不自动打开摄像头、不再运行完整档位排列扫描。能力按账号与浏览器实例缓存 144小时,可从云端恢复,也可手动更新。浏览器标识是本站生成的随机UUID,不是硬件序列号。能力未知时允许音频入会,视频保持关闭。
实际打开摄像头时校验所选采集档位与发布编码;H.265/AV1 的浏览器声明不保证跨设备实际解码。收到数据却解码失败会提示主持/联席手动调整,系统不会自动切换会议编码。CPU型号不能代替浏览器真实媒体链路验证。
PC支持网格/主视角,手机为主画面加可滚动预览;个人选看与主持的一次主画面通知分开。只有一台设备时显示灰色加号,达到两台即隐藏。摄像头竖屏内容仍置于横向预览;全屏另行适配。音频播放独立于视频布局,隐藏的视频可按兴趣暂停订阅。
构建与测试
Go版本要求见 go.mod,前端使用支持当前 Vite 的 Node。直接依赖已固定版本,使用提交的 package-lock.json 安装。
cd frontend
npm ci
npm run check
npm test
npm run build
cd ..
go test ./...
go build -buildvcs=false -ldflags "-X main.version=YOUR_COMMIT" -o bin/hola .
浏览器回归需要独立 Go + LiveKit 实例,环境变量 HOLA_V2_URL、HOLA_V2_USER、HOLA_V2_PASSWORD,Chrome路径可用 HOLA_CHROME_PATH 指定:
cd frontend
npx playwright test --config playwright.v2.config.ts
npx playwright test --config playwright.e2ee.config.ts
测试会创建专用日程、测试账号和测试会议,请在隔离环境运行。虚拟摄像头/共享源验证收发与解码链路,不能代替安卓真机性能与持续帧率验收。
部署与回滚
私密配置放在服务器 .env,参照 .env.example。反向代理指向9009;媒体配置与UDP端口需保持一致。start.sh 和 hola.service 管理进程,应用发布仅重启 Go,不重启 LiveKit。
2.0 数据库迁移为新增表和附加状态,保留现有账号、个人码及会议记录。发布前必须做一致SQLite备份、旧二进制、前端、源码、配置和服务元数据备份,并验证校验和。发布脚本 deploy/deploy-v2.py 验证产物、要求无活动会议、原子替换前端,并在健康检查失败时恢复代码。
备份目录包含 rollback-release.py。执行以下命令恢复旧代码和前端,保留当前SQLite业务数据:
python3 /opt/Hola/backups/EXACT_BACKUP/rollback-release.py --rollback /opt/Hola/backups/EXACT_BACKUP
不要直接覆盖线上数据库;恢复完整旧快照会丢失备份之后的数据,需要单独评估。账号密码、SSH信息、Forgejo令牌不进入Git。
诊断与边界
设置中的故障排查可导出本机Debug和诊断。会中视频信息分别展示摄像头发送、共享发送与各路接收的分辨率、FPS、实际编码、码率及延迟。
服务器日志在 /opt/Hola/logs/:meeting-diagnostics.jsonl、browser-diagnostics.jsonl、server-diagnostics.jsonl。日志过滤密码、令牌及原始SDP,权限0600,每类保留当前文件及3份轮转文件,每份约20MB。
- H.265 Windows–Android互通、真实1080p60与2K60性能仍需真机实测;不能用能力声明或虚拟源结果承诺。
- 安卓Chrome网页缺少手机屏幕采集接口,不能发起系统屏幕共享;可以观看他人的共享。
- 后台/锁屏采集依赖浏览器和系统策略,提供有限恢复与明确失败反馈。
- 200Mbps服务器带宽不代表任意数量的高画质视频可稳定转发;信令容量测试不等于媒体容量验收。
- nps不在本次修改范围。
- E2EE 仅覆盖媒体内容,不能阻止已参会设备录制或被控制的终端访问内容。