From 16895dcdd87fc18167169f54f00f823c96b3ab06 Mon Sep 17 00:00:00 2001 From: noelorin Date: Thu, 20 Aug 2026 15:03:44 +0800 Subject: [PATCH] docs: document chat/danmaku and broadcaster external push API; add design spec - README: explain the room chat/danmaku flow and the host-only POST /api/room/{room}/broadcast endpoint for OBS/bot/moderator use. - Add design.md describing the Awwwards-grade visual/UX bar. --- README.md | 103 ++++++++++++++++++++++++++++++++++++++---------------- design.md | 13 +++++++ 2 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 design.md diff --git a/README.md b/README.md index 7a1a69f..490126d 100644 --- a/README.md +++ b/README.md @@ -6,46 +6,66 @@ - 一路推流 → SFU 扇出 → 多路拉流。 - 同一路发布可同时落到 **Cloudflare Realtime** 与 **SRS** 两条分发链路(分流)。 - 浏览器经服务端反向代理直连 SFU,凭证不出服务端。 -- **默认 DB 使用 Turso 嵌入式 (libSQL file)**:房间分发拓扑持久化到本地文件。 +- 默认 DB 使用 Turso 嵌入式 (libSQL file):房间分发拓扑持久化到本地文件。 +- 前端为 **SolidJS + TanStack Router/Query + Ark UI + Tailwind v4** 单页应用,构建产物嵌入 Go 二进制。 ## 目录结构 ``` -app/live-sfu-demo/ - api/live_sfu.proto # protobuf 控制面契约 - gen/ # buf generate 产出(Go) +live-sfu-demo/ + api/live_sfu.proto # protobuf 控制面契约 + gen/ # buf generate 产出(Go) internal/ - config/ # 运行参数(对齐 GOSpeak 的 env 布局) - db/ # Turso 嵌入式 (libSQL file) 持久化 - sfu/cloudflare/ # Cloudflare Realtime REST 客户端 + Provider - sfu/srs/ # SRS Provider - server/ # gRPC 服务 + JSON 网关 + SRS/CF 媒体反代 + 房间扇出状态 - static/ # 浏览器 UI(发布 / 观看 / 分发面板) + config/ # 运行参数 + db/ # Turso 嵌入式 (libSQL file) 持久化 + sfu/cloudflare/ # Cloudflare Realtime REST 客户端 + Provider + sfu/srs/ # SRS Provider + server/ # gRPC 服务 + JSON 网关 + SRS/CF 媒体反代 + 房间扇出状态 + static/ # 前端构建产物(由 web/ 构建生成,Go embed) + auth/ # Casbin RBAC + JWT + bcrypt 用户存储 cmd/server/main.go - deploy/ # docker-compose.yml + srs.conf + deploy/ # docker-compose.yml + srs.conf + web/ # 前端工程(Solid + TanStack + Ark UI + Tailwind v4) + src/ # 页面 / 组件 / 库 + vite.config.ts # 构建输出到 ../internal/server/static ``` ## 运行(SRS 链路,开箱即跑) ```bash -# 1) 起本地 SRS(WHIP/WHEP/HLS 三协议后端,见 docs/streaming-pipeline.md) -cd app/live-sfu-demo/deploy && SRS_CANDIDATE=127.0.0.1 docker compose up -d srs +# 1) 起本地 SRS(WHIP/WHEP/HLS 三协议后端) +cd deploy && SRS_CANDIDATE=127.0.0.1 docker compose up -d srs # 2) 起 Demo 控制面(默认 Turso 嵌入式,无需额外配置) -cd app/live-sfu-demo +cd live-sfu-demo cp .env.example .env go run ./cmd/server -# 3) 打开浏览器 -# 发布: http://localhost:8088/publish?room=demo -# 观看: http://localhost:8088/watch?room=demo +# 3) 打开浏览器(发布/订阅需先登录,见下方鉴权说明) +# 首页: http://localhost:8088/ +# 发布: http://localhost:8088/publish?room=demo +# 观看: http://localhost:8088/watch?room=demo ``` -两个标签页用同一房间名即可配对。发布页勾选的分发后端会在「分发状态」中实时显示。 +两个标签页用同一房间名即可配对。发布页勾选的分发后端会在「分发状态」中实时显示; +SRS 链路同时产出 HLS/FLV,分发状态面板可直接获取 `/live/.m3u8` / `.flv` 链接, +经 Go 网关 (`/live/*`) 反代,无需浏览器直连 8080。 + +## 鉴权(Casbin RBAC + JWT) + +控制面已启用登录与 RBAC: + +- 发布 / 订阅 / 房间管理需要登录;`guest` 仅可读取配置与 SRS 切片流(HLS/FLV)。 +- 默认账号(bcrypt,落盘 `data/users.json`): + - `admin / Admin123!`(admin) + - `publisher / Publisher123!`(publisher) + - `viewer / Viewer123!`(viewer) +- 登录后服务端下发 HttpOnly Cookie,前端同源请求自动携带;在 `/login` 登录。 ## 默认 DB:Turso 嵌入式 -房间的“分发目标”拓扑(`stream_targets`)默认持久化到 **Turso 嵌入式**(`github.com/tursodatabase/go-libsql` 的 SQLite 兼容 file 模式),而非纯内存。 +房间“分发目标”拓扑(`stream_targets`)默认持久化到 **Turso 嵌入式** +(`github.com/tursodatabase/go-libsql` 的 SQLite 兼容 file 模式),而非纯内存。 - **DSN**:`TURSO_DATABASE_URL=file:./data/live-sfu.db?cache=shared&_journal_mode=WAL`(默认) - 兼容 `DATABASE_URL` 覆盖 @@ -57,11 +77,8 @@ go run ./cmd/server # 默认即嵌入文件 TURSO_DATABASE_URL=file:./data/live-sfu.db?cache=shared&_journal_mode=WAL -# 内存(测试) -TURSO_DATABASE_URL=file::memory:?cache=shared - # 验证持久化:发布后重启,/api/rooms 仍在 -curl http://localhost:8088/api/rooms | jq +curl -b cookie.txt http://localhost:8088/api/rooms | jq sqlite3 data/live-sfu.db "select room, backend, stream from stream_targets;" ``` @@ -88,21 +105,47 @@ buf generate api ``` 契约(`LiveSFU` 服务):`GetConfig` / `ListRooms` / `Publish` / `Subscribe` / `StopStream` / -`WatchRoom`(服务端流式推送房间分发拓扑)。gRPC 监听 `GRPC_PORT`(默认 9090),浏览器走同端口 -的 JSON 网关(`protojson`)。 +`WatchRoom`(服务端流式推送房间分发拓扑)以及 `Login` / `Register` / `GetMe` / `ListUsers` / `UpdateUserRole`。 +gRPC 监听 `GRPC_PORT`(默认 9090),浏览器走同端口的 JSON 网关(`protojson`)。 -## 文档 +## 前端开发(web/) -* 推流链路详解(PC → WHIP → SRS → HLS/WHEP/FLV):[`docs/streaming-pipeline.md`](docs/streaming-pipeline.md) +```bash +cd web +pnpm install +pnpm dev # http://localhost:5173 热更新 +pnpm build # 构建进 ../internal/server/static(被 Go embed) +``` + +技术栈:SolidJS(`vite-plugin-solid`)、TanStack Router + Query、Ark UI(无样式原语)、 +Tailwind v4(CSS-first `@theme` 做 design token 体系化驱动)。design token 集中在 +`web/src/index.css` 的 `@theme`,组件语义类在 `web/src/components/ui.tsx` 中以 token 派生。 ## 分流拓扑 ``` publisher ──WHIP/tracks.new──▶ Cloudflare Realtime SFU ──▶ viewer(s) └────WHIP────────────▶ SRS SFU ─┬─▶ WHEP viewer(s) (低延时 0.2-0.5s) - ├─▶ HLS viewer(s) (PC→WHIP→SRS→HLS 延时 5-10s,全端兼容) + ├─▶ HLS viewer(s) (全端兼容,/live/*.m3u8) └─▶ FLV viewer(s) - 一路 WHIP 推流,SRS 自动 remux 三协议同出;房间分发目标由 WatchRoom 实时广播,观众任选后端拉流 + 一路 WHIP 推流,SRS 自动 remux 三协议同出;房间分发目标由 WatchRoom 实时广播 ``` -> 详见 [`docs/streaming-pipeline.md`](docs/streaming-pipeline.md) — 默认已开启 HLS,`Go` 网关反代 `/live/*.m3u8`,前端 iOS 原生 / hls.js 双兼容。 \ No newline at end of file +> SRS 推流链路详解见 [`docs/streaming-pipeline.md`](docs/streaming-pipeline.md)。 + +## 主播外部推送 API(弹幕广播) + +除观众可发送的 `POST /api/room/{room}/chat` 外,额外提供**仅主播可用**的独立推送端点,供 OBS 脚本 / 机器人 / 管理工具以主播身份推送弹幕: + +``` +POST /api/room/{room}/broadcast +Authorization: Bearer +Content-Type: application/json + +{ "message": "欢迎来到直播间", "color": "#4ea8ff" } +``` + +- 权限:需 `room:publish`(仅 `publisher` / `admin`),未登录返回 `401`,越权返回 `403`。 +- 推送的弹幕自动标记 `host: true`,经同一 `chatHub` 广播,主播端与观众端实时可见;前端在消息列表与弹幕叠加层以「主播」标识区分。 +- 同样受滑动窗口限流(房间 + 发送者 + IP,3s 内 5 条)保护。 +- 外部工具用 `Authorization: Bearer ` 调用;浏览器端同源请求自动携带登录 Cookie。 diff --git a/design.md b/design.md new file mode 100644 index 0000000..4dae4f0 --- /dev/null +++ b/design.md @@ -0,0 +1,13 @@ +# Design Spec — 设计规范 + +## 设计标准 + +对标 Awwwards 顶级网站水准,达到 Awwwards、FWA、CSS Design Awards 每日最佳网站同等设计品质。 + +## 创意自由度 + +将浏览器视作交互式艺术画布,跳出传统布局框架,追求先锋视觉风格、实验性排版、流畅物理动效、极具冲击力的文字版式。 + +## 沉浸式体验 + +融合代码、高级渲染逻辑,打造统一完整的精品页面,做出突破常规 UI 认知、令人惊艳的数字交互体验。