Files
lxc-streamutils/docs/components/danmaku-overlay.md
T
2026-08-13 12:05:47 -07:00

5.9 KiB
Raw Blame History

danmaku_overlay 弹幕姬

弹幕姬把一个租户直播源的互动事件投影为透明 OBS 消息墙。它是被动展示组件:不记账、不回复弹幕,也不把 WebSocket 当作持久化业务通道。

订阅事件

组件根据设置动态订阅:

  • 弹幕、进房、礼物与礼物连击、醒目留言、舰长、点赞、分享。
  • 关闭类别后,后端不为该组件投影对应事件,前端也会进行一次兼容性过滤。
  • 未归一化的 live.unknown 默认不进入弹幕姬。

设置

字段 范围/单位 行为
themeId 主题 ID 选择已安装的完整视觉主题
fontFamily 字体 ID song、fang-song、kai、liyu-shoushu
fontBrightness 70–180% 只调整文字亮度
viewerColor #RRGGBB 可选的用户昵称颜色覆盖
danmakuColor #RRGGBB 可选的弹幕正文颜色覆盖
fontScale 50–300% 展开与收缩字号的统一比例
decorationLineWeight 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 只改善交互,不能取代服务端校验。字体 ID 只映射到前端预先注册并由服务同域提供的 WOFF2 字体,不接受任意 CSS,也不依赖 OBS 设备安装的字体;song、fang-song、kai 与 liyu-shoushu 分别使用 Noto Serif SC、ZCOOL XiaoWei、LXGW WenKai 与漓雨手书。颜色覆盖同样只接受六位十六进制颜色;留空时使用主题色,切换主题后会自动采用新主题的配色。

主题

主题同时封装配色、花纹素材、装饰变体、粒子组合与动画名称。当前内置主题为 jade-scroll(“青玉花卷”)与 moonlit-water(“静夜曲水”)。后者不绘制卡片底色、外框或消息分隔线,只保留青黛、米金衬线文字、少量花星微光以及组件上下共享的透明古风细边;控制台仍以选择框呈现,新增主题后无需改变设置交互或卡片队列。

增加主题时需要同步完成三处注册:

  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,也不会跨组件广播。