This commit is contained in:
Yvan
2026-09-22 20:20:23 +08:00
parent bf33e87d72
commit ceaea78b0f
42 changed files with 2845 additions and 154 deletions
+34 -5
View File
@@ -4,7 +4,7 @@
## WebSocket
连接现有 WebSocket 地址(默认 `/ws`)。观看直播允许匿名握手;登录用户可携带 GVA JWT,以使用聊天和开播能力:
连接现有 WebSocket 地址(后端默认 `/ws`,生产反向代理地址为 `/api/ws`)。观看直播允许匿名握手;PC 登录后的 HttpOnly Cookie 会随同源握手自动发送,分享链接中不携带凭证。非浏览器客户端也可携带 GVA JWT:
```text
wss://host/ws?token=<x-token>
@@ -16,7 +16,7 @@ wss://host/ws?token=<x-token>
{"type":"Join","payload":{"role":"publisher","streamId":"room-1"}}
```
角色支持 `publisher`、`subscriber`、`observer`。`subscriber` 可匿名加入,`publisher` 必须登录且只能发布自己拥有的启用直播间。主播和观众完成 Join 后,浏览器发送 SDP offer:
角色支持 `publisher`、`subscriber`、`observer`。`subscriber` 可匿名加入正在直播的房间;离线录播直接使用 HTTP 视频地址,不创建 WebRTC 观众连接。`publisher` 必须登录且只能发布自己绑定的启用直播间,分类也必须启用;允许从未开播状态开始推流。主播和观众完成 Join 后,浏览器发送 SDP offer:
```json
{"type":"Offer","payload":{"type":"offer","sdp":"v=0..."}}
@@ -55,7 +55,7 @@ wss://host/ws?token=<x-token>
GET /live/streams
GET /live/streams/:streamId
GET /live/categories
GET /live/rooms?page=1&pageSize=20&categoryId=1&status=live&orderBy=viewer_count_desc
GET /live/rooms?page=1&pageSize=20&categoryId=1&orderBy=viewer_count_desc
GET /live/rooms/:id
POST /live/rooms/:id/like
GET /live/rooms/:id/messages?limit=100
@@ -64,7 +64,11 @@ GET /live/recharge/providers
GET /live/recharge/plans
```
`/live/rooms` 默认只返回当前直播中的启用房间,并按在线人数倒序排列;支持 `categoryId`、`page`、`pageSize` 和 `orderBy` 筛选/排序。房间响应同时返回 `viewerCountText`(如 `5.1k`、`1.0w`)以及直播中的 `startedAt`。
`/live/rooms` 默认返回所有公开启用的房间,包括直播中、配置录播的离线房间、尚未开播的房间。停用房间、停用或已删除分类下的房间不公开。接口按在线人数倒序排列,再分页;支持 `categoryId`、`page`、`pageSize`、`orderBy`,显式传入 `status=live` 或 `status=offline` 时才限制直播状态。
`/live/categories` 的返回记录就是 PC 分类来源,客户端只额外增加“全部”,按分类 ID 筛选,不依赖固定分类名称。列表直接展示接口的 `viewerCountText`(如 `5.1k`、`1.0w`)。
`GET /live/rooms/:id` 同样允许访问公开的离线房间,并返回 `replayUrl`;未开播不再返回 `LIVE_ROOM_NOT_LIVE`。客户端在 `status=live` 时使用直播流或 WebRTC,离线时使用 `replayUrl`,未配置录播则显示封面和未开播状态。停用房间返回 `LIVE_ROOM_DISABLED`,停用分类返回 `LIVE_CATEGORY_DISABLED`。
聊天历史 HTTP 接口保留用于客户端契约兼容,但验证房间后始终返回空列表,不会向新进入用户泄露此前聊天。
@@ -94,7 +98,7 @@ GET /live/recharge/orders/:orderNo
GET /live/recharge/orders/:orderNo/status
```
点赞不要求登录,点赞数只在当前进程的直播运行态中累加;关注关系按直播用户和房间保存,登录后可查询、关注或取消关注。
点赞不要求登录,但仅允许正在直播的公开房间;服务端点赞数在当前进程的直播运行态中累加。PC 保留本次访问的点赞状态,不生成随机点赞。关注关系按直播用户和房间保存,登录后可查询、关注或取消关注。
创建充值订单直接接入 KRA 通用支付订单,请求使用支付模块的渠道标识:
@@ -111,10 +115,35 @@ GET /live/recharge/orders/:orderNo/status
礼物数量允许 `1..9999`,礼物接口返回的 `tiers` 仅作为快捷数量。服务端会拒绝向未开播房间送礼;扣款、礼物流水和钱包余额在同一事务内完成,余额不会小于 0。余额不足时返回 `required`、`balance` 和 `missing`,供客户端打开充值流程;成功后通过 `GiftMessage` 广播给房间内在线用户。
PC 只展示接口返回的礼物,不补造礼物 ID、价格或随机聊天。赠送按钮在请求期间防止重复提交。充值只有确认 `creditedAt` 并刷新余额后才视为到账;余额足够时继续原先选择的礼物一次,仍不足则显示差额并允许继续充值。关闭充值弹窗、离开房间、切换账号或关播会取消尚未执行的赠送意图,迟到的响应不会重新打开弹窗或自动扣款。已提交支付的真实到账结果仍以服务端订单和钱包为准。
全站设置继续保存在 `live_settings`。字典用于稳定的枚举和下拉选项,不适合承载站点名称、公告、功能开关、兑换比例等需要类型校验和运行时读取的配置。
直播状态和在线连接是进程内状态,行为与旧项目一致;服务重启后房间自动清空。
## PC 与后台
- PC 观众页:`/#/live/:id`。
- PC 主播页:`/#/studio/:id`,使用房间绑定的主播账号登录。提供设备预览、摄像头和麦克风选择、音视频开关、开始与停止直播。
- 后台保存房间后立即展示可复制链接,房间列表也可复制主播或观众链接。默认 PC 在域名根路径,后台位于 `/admin/`;独立域名或开发端口使用后台构建变量 `VITE_LIVE_CLIENT_URL`。
- 链接不含 token。后台不再保留观众送礼页面;后台直播诊断和管理详情使用管理接口,不受房间是否正在直播的限制。
- 摄像头需要 HTTPS 或 localhost;播放和推流失败时显示错误并释放失效会话,后续可重新连接。
- API 返回的相对媒体路径默认经 `/api` 加载,已带 `/api` 的路径不会重复拼接;绝对 CDN 地址保持不变。独立文件服务可设置 PC 构建变量 `VITE_FILE_BASE`。
`frontend/` 是独立 Git 仓库,主仓库中的 `web/` 是管理后台。发布本次修复时需要分别更新 PC、后台与 Go 服务,不能只发布其中一个。
## 本地验收
`tmp/live_acceptance/` 包含可复跑的隔离接口验收程序,固定访问 `127.0.0.1:18080`,仅操作 `.tmp-live-acceptance/acceptance.db`。测试配置、账号、模拟支付密钥和报告都保存在被忽略的 `.tmp-live-acceptance/` 下,不写入生产配置,也不删除已有业务数据库。
在隔离服务和本地支付模拟服务运行后执行:
```text
go run ./tmp/live_acceptance verify
```
验收覆盖后台管理、注册登录、权限、双用户实时聊天、60 秒以上连接保活、送礼事务、余额不足、充值订单归属、签名回调与重复回调,并直接核对 SQLite 钱包、礼物流水、充值记录和不持久化的聊天表。支付模拟仅用于本地验证,不代表实际商户渠道或公网跨网络 WebRTC 已验收。
## 网络配置
默认使用 Pion 主机候选。生产环境可以配置: