live-channel-v1.md
7.61 KB
AI 短剧频道 v1 —「文字点播」直播间(已完成)
状态:已上线运行(server.js + live.html,pm2 进程 minimax-live)。
本文档记录当前已实现的需求范围,作为后续「换装跳舞直播间」(见
docs/todo/dressup-dance-room.md)改造的基线参照。
1. 产品概述
一个 7x24 播放的虚拟直播间。所有观众看到同一个「虚拟播出时刻表」 (server 端统一计算的播放进度,非各自独立播放),可以:
- 直接观看正在播放的 AI 生成短视频(文字弹幕点播 + 随机填充)
- 在聊天区发一句话 → 命中素材库则很快排入播放;不命中则提交给 H3 后台生成新片段,生成完成后排入播放
- 给候选片段投票,得票最高的优先播出
- 浏览「最新 / 最早 / 最热」三种非直播的素材库列表,任意点播
2. 已实现的核心能力
2.1 虚拟播出时刻表(直播的核心机制)
server.js维护内存中的schedule([{clip, startAt, endAt, requestedBy}]), 每 2 秒 tick 一次(ensureSchedule),始终保证时刻表填充到「未来至少FILLER_DURATION_MS(30s)」。- 选片优先级:投票最高的「已生成待播」(
ready)> 投票最高的「素材库命中」 (matched)> 素材库随机填充(避开上一条、避开 20 分钟内播过的,两者都 没有时退化为纯随机,保证时刻表永不断流)。 - 所有观众通过轮询
GET /api/live/state(4s 一次)拿到同一份{current, upNext, queue},前端用「服务端 endAt 减本地时间」精确定时 切下一条,轮询只作为纠偏/兜底,不是切片的唯一触发点。 - 状态持久化到
live-state.json,进程重启后从中恢复,不会冷启动断播。
2.2 文字点播驱动生成
- 观众聊天发送文本 → 先做违禁词审核(
moderateText,子串黑名单,非语义 审核)→ 通过后submitPromptToQueue:- 命中素材库(中/英文 prompt 精确或子串匹配)→ 直接进入待播队列
(
status: matched)。 - 未命中 → 调用 H3 Console
POST /v1/videos(文生视频,480x832 竖屏/ 120帧/20步——第一期默认横屏 832x480,后改为竖屏移动端优先,见 commit1dc7084)异步生成,status: generating,生成完成后自动 写入library.json并推入待播队列(status: ready)。存量片段 保留生成时的原比例,播放器object-fit: contain兼容混合比例。
- 命中素材库(中/英文 prompt 精确或子串匹配)→ 直接进入待播队列
(
- 生成是完全后台化的(H3 自建集群单次约 200s),绝不阻塞直播时刻表或 HTTP 响应。
POST /api/prompt是同一条提交路径的非聊天版本(供测试/直接调用)。
2.3 排队投票
POST /api/queue/vote/:id:按uid(cookie)对某条排队中的 matched/generating/ready 条目投票/取消投票,票数决定谁先播(2.1)。
2.4 素材库浏览模式
- 三个 tab:最新 / 最早 / 最热(
GET /api/library?sort=),点击任意条目 立即播放,播完自动顺延下一条(ended事件),与直播模式的时刻表机制 完全独立。
2.5 观众身份
- 首次进聊天框(focus 触发,不需要先点发送)弹昵称输入框,生成
uid(crypto.randomUUID)+nickname,写入 cookie(365 天)。 - 顶部常驻「昵称 ✎」可随时改名,
uid不变(投票/点播历史不丢失)。 - 无正式账号体系——身份完全基于浏览器 cookie,换设备/清 cookie 即视为
新观众。这是 v2 用户注册需求要解决的缺口,见
docs/todo。
2.6 在线人数
- 每次
/api/live/state轮询带cid(随机 clientId,非 cookie,纯前端 内存变量)打点到viewers: Map<cid, lastSeenAt>,12s 内有心跳视为在线, 服务端返回watching计数。
2.7 内容审核 / 限流
- 审核:仅关键词黑名单(
BANNED_WORDS),非语义级别;生成内容本身的 安全检查依赖 H3 Console 自身的生成时安全策略(被拒会以「生成失败」 形式体现在队列里)。 - 限流:按 IP,5 分钟内最多 3 次聊天/点播提交(
RATE_LIMIT_MAX/WINDOW_MS)。 无账号维度限流。
2.8 后台管理(admin.html)
- 表格形式管理
library.json:搜索(名称/prompt/id)、按来源筛选 (h3console / manual)、任意列排序、行内编辑、删除。 - 「新增」表单可手动挂载一条外部视频地址(
source: manual)的素材, 不经过 H3 生成。 - 编辑/新增会置
edited: true,让后续自动同步(2.9)不覆盖人工修改。 - 删除一条
h3console来源的素材,会级联调用 H3 Console 的DELETE /v1/videos/:id(移入 H3 自己的回收站),避免下次同步又冒出来。 - 无鉴权——
admin.html和所有/api/admin/*接口对能访问到该端口的 任何人开放,依赖网络边界(内网/反代)而非应用层鉴权。
2.9 与 H3 Console 的集成
ingest.js的syncLibrary():启动时 + 每 5 分钟,从 H3 Console 拉取 全量 job 列表重建library.json(规则提取短 prompt,过滤基础设施 烟雾测试 job,保留likes,跳过edited: true的条目)。这让直接在 H3 Console 网页端产出的内容,5 分钟内自动出现在直播间素材库。- 视频本体不落本地盘:
GET /lib/video/:id服务端代理转发 H3 Console 的/v1/videos/:id/file(H3_CONSOLE_TOKEN不下发到浏览器);若素材有videoUrl(manual 来源或管理后台设置过)则 302 跳转到该地址。 - 详细 API 契约见
H3-CONSOLE.md(H3 Console 是独立于本项目的内部服务, 4 卡 GPU 单节点,无按次计费)。
3. 数据模型(现状)
library.json(数组,逐条追加,无数据库):
{
"id": "19c6b745a68e", // h3console: H3 job id;manual: manual-<ts><rand>
"source": "h3console", // "h3console" | "manual"
"edited": false, // true = 后台改过/手动新增,同步时跳过重建
"prompt": "...", // 展示用短 prompt(中文)
"promptEn": "...", // 可选,英文短 prompt
"fullPrompt": "...", // 完整生成 prompt(H3 结构化 prompt 或用户原话)
"videoUrl": "...", // 可选,外部视频地址(manual 或后台改过播放源)
"width": 480, "height": 832, // 当前默认竖屏;早期/存量片段可能是 832x480 横屏
"duration": 5, // 秒
"partition": "text", // text | ref2va | fl2va | manual
"likes": 0,
"lastPlayedAt": 1788250666831, // 可选,用于播出冷却
"createdAt": 1788250666831
}
live-state.json:{ schedule, promptQueue, chatMessages },结构见
server.js 顶部注释,逐 tick 全量覆写。
4. 已知限制(未做的事,供 v2 参考)
- 无正式用户账号(仅 cookie 身份)、无积分/消费体系。
- 素材类型单一:只有「生成好的视频片段」,没有可复用的「人物」「服装」 「参考动作/音乐视频」这类结构化中间资产——每条素材都是一次性的最终 产物,无法组合复用。
- 生成路径只有「纯文字 → H3 文生视频」一条,没有「参考图/参考视频驱动」
的生成路径(H3 Console 本身支持
ref2va/fl2va,但本项目尚未从/api/prompt、/api/chat之外的路径调用过)。 - 无人工审核队列,内容一旦生成完成即自动排入公开播放,无「先审后播」 开关。
- 无任何鉴权,管理后台和写接口都是「网络可达即可操作」。