82 lines
4.4 KiB
Markdown
82 lines
4.4 KiB
Markdown
# `danmaku_overlay` 弹幕姬
|
||
|
||
弹幕姬把一个租户直播源的互动事件投影为透明 OBS 消息墙。它是被动展示组件:不记账、不回复弹幕,也不把 WebSocket 当作持久化业务通道。
|
||
|
||
## 订阅事件
|
||
|
||
组件根据设置动态订阅:
|
||
|
||
- 弹幕、进房、礼物与礼物连击、醒目留言、舰长、点赞、分享。
|
||
- 关闭类别后,后端不为该组件投影对应事件,前端也会进行一次兼容性过滤。
|
||
- 未归一化的 `live.unknown` 默认不进入弹幕姬。
|
||
|
||
## 设置
|
||
|
||
| 字段 | 范围/单位 | 行为 |
|
||
| ------------------------ | ----------- | -------------------------- |
|
||
| `themeId` | 主题 ID | 选择已安装的完整视觉主题 |
|
||
| `fontScale` | 50–300% | 展开与收缩字号的统一比例 |
|
||
| `maxVisible` | 1–12 | 同时保留的消息卡数量 |
|
||
| `collapseAfterSeconds` | 2–120 秒 | 最新卡从展开态切换到紧凑态 |
|
||
| `unfoldDurationMs` | 200–5000 ms | 横向卷轴展开动画时间 |
|
||
| `motionIntensity` | 0–100% | 卡片、流光与焦点动画强度 |
|
||
| `particleCount` | 0–12 | 每卡星花粒子数量 |
|
||
| `particleSpeed` | 25–300% | 粒子动画速度 |
|
||
| `lowPerformanceMode` | boolean | 关闭高成本动态效果 |
|
||
| `highValueThreshold` | 千分之一元 | 高价值礼物起点 |
|
||
| `featuredValueThreshold` | 千分之一元 | 焦点礼物起点 |
|
||
| `show*` | boolean | 控制各事件类别订阅 |
|
||
|
||
后端的 `OverlaySettings::sanitize` 是最终边界。控制台 range input 只改善交互,不能取代服务端校验。
|
||
|
||
## 主题
|
||
|
||
主题同时封装配色、花纹素材、装饰变体、粒子组合与动画名称。当前内置主题为
|
||
`jade-scroll`(“青玉花卷”);控制台仍以选择框呈现,新增主题后无需改变设置交互或卡片队列。
|
||
|
||
增加主题时需要同步完成三处注册:
|
||
|
||
1. 在后端 `OverlayThemeId` 中增加稳定 ID,使未知主题无法进入数据库。
|
||
2. 在 `apps/overlay/src/themes/` 增加主题定义,并注册到 `overlayThemes`。
|
||
3. 提供主题使用的 CSS 动画和素材;不要在 `Card` 中加入按主题 ID 分支。
|
||
|
||
旧组件没有 `themeId` 时会自动使用
|
||
`jade-scroll`。WebSocket 收到未知 ID 时前端也会安全降级到该主题,以支持前后端滚动部署。
|
||
|
||
## 卡片生命周期
|
||
|
||
1. 新事件插入队首,以卷轴动画横向展开。
|
||
2. 用户名与内容在展开态分行显示,长内容完整换行。
|
||
3. 新事件到达或超时后,旧卡变成紧凑态;内容不会隐藏。
|
||
4. 紧凑态缩小字号并尽量压缩布局,但仍允许换行避免截断。
|
||
5. 超过 `maxVisible` 的最旧卡才会离开队列。
|
||
|
||
花纹由事件类型和事件 ID 的稳定 hash 选择。相邻卡会避开完全相同的款式;礼物连击更新沿用原卡片 key 和装饰,避免视觉跳动。
|
||
|
||
## 礼物展示
|
||
|
||
- `live.gift` 创建礼物卡;`live.gift.combo` 使用 `comboId` 更新同一张卡。
|
||
- 元数据优先使用礼物目录中的静态图、GIF、币种和价格。
|
||
- GIF 加载失败时降级为静态图片;静态图失败时隐藏图片但保留名称、数量和用户。
|
||
- 普通、高价值和焦点礼物按 `totalPrice` 与两个阈值分级。
|
||
- `priceCny` 只用于人类可读展示;整数 `totalPrice` 用于精确分级。
|
||
|
||
## 弹幕表情
|
||
|
||
文字和表情按 `segments` 顺序混排。表情 URL 来自消息本身或用户级表情目录补全;图片使用
|
||
`no-referrer`,失败后显示原始表情文字。整条大表情可通过 `standalone` 使用更合适的尺寸。
|
||
|
||
## OBS 自适应
|
||
|
||
- 根背景完全透明,不存在 1920×1080 固定画布。
|
||
- `ResizeObserver` 根据浏览器源实际宽高选择 `narrow`、`short` 或 `standard`。
|
||
- 字号和间距使用 CSS custom properties 与 `clamp()`,OBS 自由缩放时不拉伸素材比例。
|
||
- 建议从 `360×600`、`440×760`、`600×1080` 或 `720×320` 开始测试。
|
||
- 低高度会减少视觉密度,但不会把仍在队列中的文字裁成省略号。
|
||
|
||
## 测试页面
|
||
|
||
控制台的事件测试直接构造 canonical
|
||
`LiveEvent`,使用当前账户、source 和 component 走同一套订阅、handler、projection 与 EventHub。测试事件标记为
|
||
`simulated=true`,不会发送到 Bilibili,也不会跨组件广播。
|