feat(monitor): 抖音 Web 接口客户端 —— 绕开爬虫子进程,直接发 HTTP
移植自 mac-agent-os 的 mediacrawler_adapter:不起子进程、不开页面,用浏览器里那份
登录态直接调抖音 Web 接口。产物键名照抄 store/douyin,所以 ingest 那条链路一个字不用改。
**目前能用的(真环境实测,非推断)**:
profile/other : 200, 7075 字节 —— 博主主页指标(粉丝/获赞/作品数/昵称)
aweme/detail : 200, 45425 字节 —— 单条作品详情(含点赞/评论/收藏/分享)
**目前不能用的:作品列表 `aweme/post`。** 两个互相独立的原因:
1. 这个接口被抖音单独升级成了真校验:不带 x-tt-argus 回 403「Uifid Not Found」,
带上 dummy 值回 200 + **空 body**。也就是说「头在不在」骗得过,「真校验」过不了。
同一套头打 profile/other 和 aweme/detail 都是通的 —— 抖音是挑着接口加保护的,
挑中的恰好是「批量拉作品列表」这个最敏感的动作。
2. 改走页面截获也不行:CDP 浏览器打开博主主页会落到「验证码中间页」(当天大量探测的
代价,过几小时要重测)。
所以现在的边界是:**已知作品的指标刷新能做,自动发现新作品做不了**。
**排查中控住变量后得到的两条事实**(都写进注释了):
· `Accept` / `Accept-Language` / `Referer` 才是主页接口能返回真数据的原因 —— 只有
UA+client hints+Cookie 时是 200 但仅 121 字节的空壳,补上这三个头变 7074 字节。
(我先前猜的 sec-ch-ua 不是关键。)
· 因此 UA 与 client hints 必须**成套地取自同一个浏览器**,所以 BrowserIdentity 一次
从 CDP 取齐 cookie + UA + hints,而不是各自写死。
「200 + 空 body 必须当场报错」也是刻意写死的:放过去它会在下游变成「这个博主没作品」,
把一次失败伪装成一条正常结果 —— 爬虫那条路正是这么栽的,还被翻译成「账号被封」。
测试 +11:cookie 解析、请求头成套性(含 uifid 缺失/回退)、产物键名与 store 对齐、
以及 _get 的三条失败路径(空 body / 403 带网关原话 / 正常返回)。
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
# 声音 / 口型 完整方案(v1 草案)
|
||||
|
||||
> 建立:2026-10-03 · 状态:**待用户最终确认后实施**
|
||||
> 关联:`composer/dubbing.py`(配音引擎·已上线)、`composer/lipsync.py`(待改造为可灵版)
|
||||
|
||||
---
|
||||
|
||||
## 一、目标
|
||||
|
||||
让成片的**声音完整、口型对得上、节奏跟得上**:
|
||||
|
||||
1. 主角出镜说台词的镜头 → **口型同步**
|
||||
2. 旁白 / 空镜 → 正常配音(不做口型)
|
||||
3. 同一角色**音色全片一致**(不管画面怎么变)
|
||||
4. 台词时长决定镜头时长(**画面跟着声音走**)
|
||||
|
||||
---
|
||||
|
||||
## 二、用户已确认的决策
|
||||
|
||||
| # | 决策 | 说明 |
|
||||
|---|---|---|
|
||||
| 1 | **只对有台词的镜头做口型** | 成本最低;其余镜头不做 |
|
||||
| 2 | **音色必须一致** | 一个角色 = 一个固定 `voice_id`;音色库管理 |
|
||||
| 3 | **音频先行** | 先 TTS 得到真实音频时长 → 按它定镜头时长 → 再生成画面 |
|
||||
| 4 | **旁白标记 = 混合(c)** | 默认自动判定(无出场人物=旁白),分镜卡片可手动改 |
|
||||
| 5 | 一句话拆两镜 | 按**语义停顿**切分(**先自动分,需要时手动调**),每段独立 TTS + 对口型 |
|
||||
| 6 | 对口型失败兜底 | 用原片段(不影响出片) |
|
||||
| 7 | 成本测试 | **改用 20 秒测试片**:1 个空镜(素材库免费素材)+ 2 个 5 秒角色说话镜头(做口型)——"该省省,该花花" |
|
||||
| 8 | **双人同框对策 = 参数** | 正反打/过肩镜头做成本可控制的**参数**(默认关,未来有能力再启用,不影响创作) |
|
||||
|
||||
---
|
||||
|
||||
## 二·五、待补充的**基础能力**(用户要求:补在基础层,其他流程可复用)
|
||||
|
||||
> 原则:**补在基础能力层**(`capabilities/` / `composer/`),而非某个流程专属实现 —— 这样分镜、口播、混剪等流程都能复用。
|
||||
|
||||
| # | 能力 | 用途 | 现状 |
|
||||
|---|---|---|---|
|
||||
| B1 | **首尾帧衔接** | 镜头间无缝续接 / 镜头内首尾帧控制 | 底层已具备(可灵 `image_tail`),**上层未接通** |
|
||||
| B2 | **多参考图** | 多角色同框各保人脸 | ❌ 可灵不支持;待专业方案(ComfyUI 多参考 / IP-Adapter) |
|
||||
| B3 | **微表情 + 口型核对** | 生成后校验表情/口型是否符合预期(质量门) | ❌ 无(可结合视觉模型做检测) |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 三、技术方案
|
||||
|
||||
### 3.1 声音分四轨
|
||||
|
||||
```
|
||||
一条片子的声音 = 旁白轨 + 角色人声轨 + 环境音轨 + BGM轨
|
||||
```
|
||||
|
||||
### 3.2 镜头按声音需求分三类
|
||||
|
||||
| 类型 | 特征 | 画面 | 声音 |
|
||||
|---|---|---|---|
|
||||
| **A 角色说话** | 有台词 + 有出场人物 | 图生视频(绑角色,保人脸) | 角色音色 TTS + **对口型** |
|
||||
| **B 旁白解说** | 有台词、无出场人物(或手动标旁白) | 空镜 / 场景 | 旁白音色 TTS,不做口型 |
|
||||
| **C 无台词** | 空镜 / 氛围 | 场景 | 环境音铺底(或静音) |
|
||||
|
||||
### 3.3 工作流(音频先行)
|
||||
|
||||
```
|
||||
① 分镜定稿(每镜:台词 + 出场人物 + 旁白标记)
|
||||
↓
|
||||
② 【音频先行】逐镜 TTS
|
||||
· A 类 → 该角色音色(voice_id 固定)
|
||||
· B 类 → 旁白音色
|
||||
· C 类 → 无
|
||||
→ 得到每段**真实音频时长**
|
||||
↓
|
||||
③ 【画面跟随】按音频时长定镜头时长 → 生成画面
|
||||
· 绑角色 → 图生视频(保人脸一致性)← 2026-10-03 已修复
|
||||
· 未绑 → 文生视频
|
||||
↓
|
||||
④ 【对口型】仅 A 类镜头:
|
||||
镜头视频 + 台词音频 → 可灵 lip-sync → 替换片段(失败则用原片段)
|
||||
↓
|
||||
⑤ 【混流】人声轨 + 环境音 + BGM + 字幕
|
||||
```
|
||||
|
||||
### 3.4 音色一致性机制
|
||||
|
||||
- **一个角色 = 一个固定 voice_id**(演员表 `CastMember.voice_id` 绑定)
|
||||
- 未指定 → 按角色代号 hash 从路人池**稳定分配**(同代号永远同音色)
|
||||
- CosyVoice 同一 voice_id 合成结果音色确定(仅语气/语速随文本微变)
|
||||
- **旁白与角色音色可以不同**(解说员 vs 画面人物,观众接受且更自然)
|
||||
|
||||
### 3.5 可灵 lip-sync 接口(已实测探明,2026-10-03)
|
||||
|
||||
```
|
||||
POST /v1/videos/lip-sync
|
||||
{
|
||||
"input": {
|
||||
"mode": "audio2video", // 或 text2video(需 voice_language)
|
||||
"video_url": "..." | "video_id": "...", // 二选一(video_id 可用我们生成的镜头)
|
||||
"audio_type": "url",
|
||||
"audio_url": "..."
|
||||
}
|
||||
}
|
||||
GET /v1/videos/lip-sync ← 任务列表查询
|
||||
```
|
||||
|
||||
✅ **用现有 kling key 即可,不需要 fal.ai**(现有 `lipsync.py` 是 fal.ai 版 → 改造为可灵版)
|
||||
⚠️ 单价未知(文档站为 SPA 抓不到)→ 按用户决策:先跑 1 个 5 秒镜头实测
|
||||
|
||||
---
|
||||
|
||||
## 四、实施步骤(建议顺序)
|
||||
|
||||
| 阶段 | 内容 | 依赖 |
|
||||
|---|---|---|
|
||||
| **P1** | 音频先行:出片流程加「先 TTS → 按音频时长定镜头时长」(音频存盘供混流复用,**不重复 TTS**) | 无 |
|
||||
| **P2** | 演员表音色绑定 + 旁白标记(前端 UI + schema) | 无 |
|
||||
| **P3** | `lipsync.py` 改造为可灵版 + 接入出片流程(仅 A 类镜头,失败用原片段) | P1 |
|
||||
| **P4** | **20 秒测试片**:1 空镜(免费素材)+ 2 个 5 秒角色说话 → 实测 lip-sync 单价 → 用户决定是否全量 | P3 |
|
||||
| **P5** | 首尾帧衔接(接通 `image_tail`)→ 补进**基础能力层**(B1) | 独立 |
|
||||
| **P6** | 双人同框 → 正反打**参数**(默认关,用户可控;未来 B2 到位后可启用) | 独立 |
|
||||
| **B 系列** | 基础能力补充:B1 首尾帧 / B2 多参考 / B3 微表情口型核对(补在基础层,全流程复用) | 见二·五 |
|
||||
|
||||
---
|
||||
|
||||
## 五、成本估算(粗略,待实测)
|
||||
|
||||
| 项 | 单价 | 说明 |
|
||||
|---|---|---|
|
||||
| TTS(CosyVoice) | 极低(按字数) | 几十字台词 ≈ 几分钱 |
|
||||
| 可灵 lip-sync | **待实测** | 参考 fal.ai 版注释 ¥0.1/秒 |
|
||||
| 粗估 | 每部短片 2~3 个台词镜头 × 5 秒 ≈ **¥1~2/部** | 月产 20 分钟 ≈ 十数量级 |
|
||||
|
||||
---
|
||||
|
||||
## 六、已知局限(诚实标注)
|
||||
|
||||
1. **多角色同框**:图生视频只能喂一张参考图 → 只保主角(替代:正反打 / 合成参考图 / 等专业能力)
|
||||
2. **跨镜头口型连贯**:一句话拆两镜时,语气可能有轻微断裂(缓解:切分点落在语义停顿)
|
||||
3. **已生成素材**:本方案只对新生成生效(旧镜头需重新出片)
|
||||
|
||||
---
|
||||
|
||||
## 七、待确认
|
||||
|
||||
- [ ] 用户确认"按默认"(第 2/3/4 点)→ 即可开工 P1
|
||||
- [ ] 优先级:**A 声音链先做**(建议),B 一致性增强随后
|
||||
@@ -0,0 +1,130 @@
|
||||
# Dashboard 五层架构合规审计报告 v1.0
|
||||
|
||||
> 日期: 2026-06-19
|
||||
> 审计范围: 所有 33 个前端视图 + 4 个内联模块
|
||||
|
||||
---
|
||||
|
||||
## 一、五层架构标准
|
||||
|
||||
```
|
||||
Layer 5: 前端视图 (Vite views/*.js) → 调 API
|
||||
Layer 4: API 路由 (routes/*.py) → 调 CommandBus
|
||||
Layer 3: 命令总线 (CommandBus) → 调 MachineSession
|
||||
Layer 2: 执行引擎 (mc run / mc task) → 调 原子操作
|
||||
Layer 1: 浏览器 (Camoufox) → 执行操作
|
||||
```
|
||||
|
||||
**通过标准**: 前端 API 调用 → 后端路由 → CommandBus.dispatch() → 子进程执行
|
||||
|
||||
---
|
||||
|
||||
## 二、账户操作视图 (必须走 CommandBus)
|
||||
|
||||
### ✅ 已合规 (7个)
|
||||
|
||||
| 视图 | 操作 | API 调用 | 后端路径 |
|
||||
|:-----|:------|:---------|:---------|
|
||||
| **养号执行** | 启动养号 | `POST /api/ops/run` | → CommandBus → `mc run` |
|
||||
| **联邦指挥台** | 执行操作 | `POST /api/ops/run` | → CommandBus → `mc run` |
|
||||
| **信息采集** | 批量采集 | `POST /api/ops/run {type:'collect'}` | → CommandBus `CMD_REGISTRY` → `mc run --blueprints=auto` |
|
||||
| **信息采集** | 单账号采集 | `POST /api/ops/run {type:'collect'}` | → CommandBus `CMD_REGISTRY` → `mc run --blueprints=auto` |
|
||||
| **定向评论** | 执行评论 | `POST /api/ops/run {type:'comment'}` | → CommandBus `CMD_REGISTRY` → `mc task comment` |
|
||||
| **收藏点赞** | 执行点赞 | `POST /api/ops/run {type:'like'}` | → CommandBus `CMD_REGISTRY` → `mc run --blueprints=douyin_daily` |
|
||||
| **登录** (账号管理/各视图🔑) | 打开浏览器 | `POST /api/ops/run {type:'login'}` | → CommandBus `CMD_REGISTRY` → `mc smart-login` |
|
||||
| **CMD_REGISTRY 注册表** | 统一 cmd_type → 命令模板 | 在 command_bus.py 定义 | 新增操作只需加一行,不需改 dispatch |
|
||||
|
||||
### ℹ️ 系统运维操作 (不走 CommandBus 是合理的)
|
||||
|
||||
| 视图 | 操作 | API | 原因 |
|
||||
|:-----|:------|:----|:------|
|
||||
| **远程Shell** | 在远端执行命令 | `POST /api/federation/exec` | 系统管理工具, 非账号操作 |
|
||||
| **对账检查** | ORACLE 宪法对账 | `POST /api/fleet/reconcile` | 系统健康检查 |
|
||||
| **一键同步** | Git 同步所有机器 | `POST /api/fleet/sync` | 系统运维 |
|
||||
|
||||
### 📊 只读数据视图 (无操作, 无需 CommandBus)
|
||||
|
||||
| 视图 | API | 说明 |
|
||||
|:-----|:----|:------|
|
||||
| machines | `/api/machines` | 机器状态, 只读 |
|
||||
| matrix-accounts | `/api/matrix/accounts` | 账号列表, 只读 |
|
||||
| matrix-blueprints | `/api/matrix/blueprints`, `/api/matrix/atom-ops` | 蓝图列表+原子操作, 只读 |
|
||||
| matrix-atom-ops | `/api/matrix/atom-ops` | 原子操作列表, 只读 |
|
||||
| matrix-corpus | `/api/matrix/corpus` | 语料库, 只读 |
|
||||
| matrix-summary | `/api/matrix/cross-machines`, `/api/matrix/system-info` | 多机总览, 只读 |
|
||||
| matrix-sms-proxy | `/api/matrix/sms/*` | SMS 代理配置, 只读 |
|
||||
| matrix-schedule | `/api/matrix/schedules` | 定时任务, 只读 |
|
||||
| capabilities | `/api/capabilities` | 能力目录, 只读 |
|
||||
| costs | `/api/summary`, `/api/costs/breakdown` | 费用统计, 只读 |
|
||||
| productions | `/api/matrix/sms/accounts` | 生产列表, 只读 |
|
||||
| assets | `/api/assets` | 资产库, 只读 |
|
||||
|
||||
### ❌ 14行占位符 (无功能)
|
||||
|
||||
| 视图 | 状态 |
|
||||
|:-----|:------|
|
||||
| ave-render, ave-script, ave-materials, ave-templates | 占位符 |
|
||||
| crawl-history, crawl-sources | 占位符 |
|
||||
| serve-dashboard, serve-mcp, serve-schedule | 占位符 |
|
||||
| matrix-login | 跳转到采集 |
|
||||
| matrix-publish | "开发中..." |
|
||||
| workflow | 占位符 |
|
||||
|
||||
---
|
||||
|
||||
## 三、远程执行路径 (federation API)
|
||||
|
||||
`recording.js` 中 `_routeOperation()` 对远程机器分发走 federation API:
|
||||
|
||||
| 操作 | Federation 端点 | 现状 |
|
||||
|:-----|:----------------|:------|
|
||||
| login(远程) | `POST /api/federation/login` | ⚠️ 直接 SSH 执行 |
|
||||
| logout(远程) | `POST /api/federation/logout` | ⚠️ 直接 SSH 执行 |
|
||||
| comment(远程) | `POST /api/federation/comment` | ⚠️ 直接 SSH 执行 |
|
||||
| nurture(远程) | `POST /api/federation/nurture` | ⚠️ 直接 SSH 执行 |
|
||||
| collect(远程) | `POST /api/federation/collect` | ⚠️ 直接 SSH 执行 |
|
||||
|
||||
**这些 federation 端点应该也改为走 CommandBus**, 否则远程操作不经过命令总线的 preflight/冷却/并发控制。
|
||||
|
||||
---
|
||||
|
||||
## 四、ORACLE 合规检查规则
|
||||
|
||||
### 4.1 账号→机器映射表
|
||||
|
||||
`ORACLE.yaml` 是账号→机器的**宪法级**映射表。CommandBus 执行前自动校验:
|
||||
|
||||
```
|
||||
请求: account=douyin_test, machine=5kechengdeAir
|
||||
→ ORACLE 查 douyin_test → 应属于 chengzigedeAir
|
||||
→ 发出警告: "douyin_test 按 ORACLE 应在 chengzigedeAir,实际发往 5kechengdeAir"
|
||||
→ 仍然允许执行(可能是临时调配)
|
||||
```
|
||||
|
||||
### 4.2 三种结果
|
||||
|
||||
| 检查结果 | 行为 | 前端显示 |
|
||||
|:---------|:-----|:---------|
|
||||
| 匹配 | 正常执行 | ✅ 绿色 |
|
||||
| 不匹配 | 执行 + 警告 | ⚠️ 橙色警告 |
|
||||
| 未登记 | 执行 + 警告 | ⚠️ 建议 git pull 后 fleet_reconcile |
|
||||
|
||||
### 4.3 规则存证
|
||||
|
||||
- `ORACLE.yaml` — 宪法文件,账号机器映射的 source of truth
|
||||
- `command_bus.py` — 运行时校验,每次 dispatch 自动检查
|
||||
- `fleet_reconcile` — 对账工具,检查实际状态是否符合 ORACLE
|
||||
|
||||
---
|
||||
|
||||
## 五、总结
|
||||
|
||||
| 类别 | 数量 | 状态 |
|
||||
|:-----|:-----|:------|
|
||||
| 账户操作视图 | **7** | ✅ **全部已合规**(走 CommandBus) |
|
||||
| 系统运维视图 | **3** | ℹ️ 合理不走 CommandBus |
|
||||
| 只读数据视图 | **12** | ℹ️ 无操作 |
|
||||
| 占位符视图 | **11** | ❌ 无功能 |
|
||||
| 远程分发端点 | **5** | ⚠️ 待改造 |
|
||||
|
||||
**当前优先级**: 远程端点(federation)改造 → 占位符填充 → 旧模块清理
|
||||
@@ -0,0 +1,144 @@
|
||||
# 基础能力治理与补强方案(提案)
|
||||
|
||||
> 2026-10-03 · 状态:待用户拍板
|
||||
> 背景:用户提问"接着补基础能力,怎么加,也涉及以后基础能力如何增加调整"
|
||||
|
||||
---
|
||||
|
||||
## 一、诊断:能力体系已"半脱节"
|
||||
|
||||
### 已有基础(做得好的)
|
||||
|
||||
| 模块 | 位置 | 作用 |
|
||||
|---|---|---|
|
||||
| 能力登记 | `05_tools/09_ave/config/capabilities.yaml` | 25 个能力,含 io / params_schema / providers |
|
||||
| 缺口声明 | `05_tools/09_ave/config/feasibility_rules.yaml` | 30 条可行性规则 + 10 个能力缺口映射 + 三色红线 |
|
||||
| 匹配器 | `05_tools/09_ave/scripts/capability_matcher.py` | 需求→能力匹配 + 目录指纹 + 升级检测 |
|
||||
| 前端 | 导演台技术预检弹窗 | 显示每个镜头的技术预检与缺口汇总 |
|
||||
|
||||
### ⚠️ 实测发现的 5 处"清单 ≠ 实际"
|
||||
|
||||
| 能力 | 清单写的 | 实际 | 影响 |
|
||||
|---|---|---|---|
|
||||
| `lipsync` 对口型 | providers: fal / volcano / d_id · partial | 已用**百炼 videoretalk** 跑通 | 清单 provider 错误,无法据此排障 |
|
||||
| `person_swap` 人物置换 | partial | **已实测跑通** | 状态偏保守 |
|
||||
| `vfx_apply` 特效 | planned | 可灵 `camera_control` **已可用** | 状态偏保守 |
|
||||
| `frame_chain` 首尾帧 | **missing** | `kling_video.py:152` **已实现 image_tail** | **把已有能力报成缺口** |
|
||||
| `voice_lock` 声线锁 | cap_id=**None** | 音色库已实现 | 未挂到能力,统计丢失 |
|
||||
|
||||
**根因**:能力登记、代码实现、缺口声明**三者无联动** ——
|
||||
加了功能忘登记、登记了没实现、实现了却仍报"缺失"。
|
||||
|
||||
---
|
||||
|
||||
## 二、机制方案:能力生命周期(4 步 + 1 台账)
|
||||
|
||||
```
|
||||
① 登记 capabilities.yaml(唯一真相源)
|
||||
新增字段:
|
||||
cost: {unit: "元/秒", price: 0.08, note: "走免费额度优先"}
|
||||
limits: ["正面近景 2~120s", "边长 640~2048"]
|
||||
self_test: "python -m capabilities.selftest lipsync"
|
||||
last_verified: "2026-10-03"
|
||||
provider.state: ready | needs_key | broken
|
||||
|
||||
② 自检 scripts/capability_doctor.py(新)
|
||||
一条命令验证"清单说的 ready 是不是真能跑"
|
||||
--list 列出全部能力与最近验证状态
|
||||
--capability X 单查(api_key 配置 / provider 可达 / limits 校验)
|
||||
--live 真跑最小样例(产生费用,需显式开启)
|
||||
--update 把验证结果写回 capabilities.yaml 的 last_verified
|
||||
|
||||
③ 接入 标准 4 步(写成 docs/CAPABILITY_GUIDE.md)
|
||||
a. capabilities.yaml 登记(id/name/category/io/schema/provider/cost/limits)
|
||||
b. 实现 provider(scripts/capabilities/<name>.py 或既有模块)
|
||||
c. 写自检样例(让 doctor --live 能跑)
|
||||
d. feasibility_rules.yaml 声明"什么技术需求触发它"
|
||||
—— 与导演系统的"接新导演 3 步"对称
|
||||
|
||||
④ 台账 runtime/ave/capability_gaps.json(新)
|
||||
缺口不再散落在规则里,而是有状态:
|
||||
{id, name, first_seen, occurrences, affected_shots[], status,
|
||||
blocking, resolved_at, resolved_by}
|
||||
status: open → planned → in_progress → resolved
|
||||
+ 能力升级 → 指纹变化 → 已出片方案自动提示"可重新生成更好版本"
|
||||
```
|
||||
|
||||
**设计取舍**:先做 ①②(对账 + 体检),台账 ④ 可后置。
|
||||
理由是 ①② 立刻消除"清单不可信"这个根本问题;④ 是统计增项。
|
||||
|
||||
---
|
||||
|
||||
## 三、本轮补什么(按性价比排序)
|
||||
|
||||
### 🥇 P0 能力对账 + 体检脚本(零成本 · 约 1 天)
|
||||
|
||||
- 修正上述 5 处脱节(尤其 `frame_chain` 从 missing → ready)
|
||||
- 补 `cost` / `limits` 字段(为报价与预算打基础)
|
||||
- 写 `capability_doctor.py`(`--list` 与单查;`--live` 可选)
|
||||
- **产出**:一份可信的能力清单 + 一键体检
|
||||
|
||||
### 🥈 P1 首尾帧衔接 `frame_chain`(能力已有,只差接线)
|
||||
|
||||
- **前提**:可灵 `image_tail` 参数**代码已实现**(`capabilities/kling_video.py:143-152`)
|
||||
- **做**:分镜 `tech_requirements.chain_from_prev` → 生成时自动把上一镜尾帧作为本镜尾帧/首帧
|
||||
- 抽尾帧:ffmpeg 取上一镜最后一帧 → 存 `chain/{shot_id}_tail.jpg`
|
||||
- 生成时:`tail_image_path=上镜尾帧`
|
||||
- **效果**:长镜头分段生成无缝衔接;跨镜人物/光线不漂移
|
||||
- **成本**:0(只多一个参数;抽帧是本地 ffmpeg)
|
||||
|
||||
### 🥉 P2 多角色同框一致性(已发现的真实问题)
|
||||
|
||||
现状:图生视频只喂**一张**参考图 → 双人同框时只有主角保脸,配角随机。
|
||||
|
||||
| 方案 | 做法 | 成本 | 我的评价 |
|
||||
|---|---|---|---|
|
||||
| **a. 首帧合成** | 生成前把多角色合成到一张首帧图 → 图生视频 | 一次图生图 | 效果最好,稍复杂 |
|
||||
| **b. 导演层规避** | 提示词要求避免"多角色同框近景",改用正反打/过肩 | **0** | **零成本先上**,且更符合真实拍摄 |
|
||||
| c. 多参考图 | 查即梦/万相是否支持多图输入 | ? | 需先验证 |
|
||||
|
||||
**建议**:先 b(零成本、马上见效)→ 再评估 a。
|
||||
|
||||
### P3 表情微管理 `expression_consistency`
|
||||
|
||||
- 轻量:分镜 `expression_detail`(已有)+ 跨镜一致性提示词强化
|
||||
- 中量:角色资产加"表情参考图"槽位 → 图生视频时带上
|
||||
|
||||
### P4 口型质检辅助(用户提过的"微表情口型核对")
|
||||
|
||||
- 出片后自动抽关键帧 → 拼对比图 → 人工快速核对
|
||||
- 进阶:接人脸检测,粗判嘴部开合与音频包络是否吻合
|
||||
|
||||
---
|
||||
|
||||
## 四、推荐执行顺序
|
||||
|
||||
```
|
||||
P0 对账 + 体检脚本 ← 地基,零成本,先做
|
||||
↓
|
||||
P1 首尾帧接线 ← 能力已有,投入产出比最高
|
||||
↓
|
||||
P2b 多角色规避(提示词)→ P2a 首帧合成
|
||||
↓
|
||||
P3 表情 / P4 口型质检
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、待用户拍板
|
||||
|
||||
1. **P0 治理机制**是否认可?(登记 + 自检 + 台账三件套;可精简为"对账 + doctor")
|
||||
2. **P1 首尾帧**是否本轮做?
|
||||
3. **P2 多角色**:先用提示词规避够不够,还是直接上首帧合成?
|
||||
|
||||
---
|
||||
|
||||
## 附:执行时需动的文件(预告)
|
||||
|
||||
- `05_tools/09_ave/config/capabilities.yaml`(对账 + 补字段)
|
||||
- `05_tools/09_ave/config/feasibility_rules.yaml`(缺口状态修正)
|
||||
- `05_tools/09_ave/scripts/capability_doctor.py`(新建)
|
||||
- `05_tools/09_ave/scripts/capability_matcher.py`(缺口台账读写)
|
||||
- `05_tools/09_ave/scripts/composer/pipeline.py`(首尾帧接线)
|
||||
- `05_tools/09_ave/scripts/directors/*.py`(多角色规避提示词)
|
||||
- `05_tools/10_dashboard/routes/ave.py` + 前端(缺口台账展示,可选)
|
||||
@@ -0,0 +1,55 @@
|
||||
# 命令传导治理——改动清单与范围
|
||||
|
||||
> 日期: 2026-06-25 | 目标版本: 4.2.1
|
||||
> 改动后由用户全面审计
|
||||
|
||||
---
|
||||
|
||||
## 改动范围总览
|
||||
|
||||
### 前端视图(4个文件)
|
||||
|
||||
| 文件 | 当前问题 | 改为 | 工作量 |
|
||||
|:-----|:---------|:-----|:-------|
|
||||
| `views/matrix-like.js` | 用旧路由 `/matrix/task/run` + 双重循环逐个发 | `POST /api/ops/run {type:'like', accounts:全部}` | 中 |
|
||||
| `views/matrix-sms-proxy.js` | 用已删除的路由 `/matrix/collect-homepage` | `POST /api/ops/run {type:'collect', accounts}` | 小 |
|
||||
| `views/matrix-accounts.js` | 单账号采集/登录逐个发 | 一次性提交 + 显示结果 | 中 |
|
||||
| `views/matrix-comment.js` | — | 审计确认是否需要改 | 小 |
|
||||
|
||||
### 后端路由(1个文件)
|
||||
|
||||
| 路由 | 处理方式 |
|
||||
|:-----|:---------|
|
||||
| `routes/matrix.py:/task/run` (POST) | 删除(已改由 `/api/ops/run` 替代) |
|
||||
| `routes/matrix.py:/nurture/start` (POST) | 删除(已改由 `/api/ops/run` 替代) |
|
||||
| `routes/matrix.py:/collect-homepage/*` (POST) | ✅ 已删除 |
|
||||
|
||||
### 旧模块(modules/ 中的残留引用)
|
||||
|
||||
| 模块 | 引用 | 处理 |
|
||||
|:-----|:------|:------|
|
||||
| `modules/collect.js:92` | `/api/matrix/task/run` | 改为 `/api/ops/run` |
|
||||
| `modules/recording.js:137,149` | `/matrix/collect-homepage/phone` + `/status` | 删除或改为新路由 |
|
||||
| `modules/nurture.js:109,122,153,165` | `/matrix/collect-homepage` + `/status` | 删除或改为新路由 |
|
||||
|
||||
### CMD_REGISTRY
|
||||
|
||||
| 条目 | 当前 | 改为 |
|
||||
|:-----|:-----|:-----|
|
||||
| `nurture.runner` | 定义了但 dispatch 未使用 | dispatch 使用 runner 字段 |
|
||||
| `comment` 模板 | 含 `{direction}` 可能缺失 | 去掉 direction 或设默认值 |
|
||||
|
||||
---
|
||||
|
||||
## 实施顺序
|
||||
|
||||
```
|
||||
Step 1: 改 matrix-like.js(旧路由,最高优先级)
|
||||
Step 2: 改 matrix-sms-proxy.js(旧路由已删除,会404)
|
||||
Step 3: 改 matrix-accounts.js(逐个发送问题)
|
||||
Step 4: 改 modules/*.js 旧引用
|
||||
Step 5: 删除后端旧路由 + 清理 CMD_REGISTRY
|
||||
Step 6: 构建前端 + 重启 Dashboard
|
||||
Step 7: git push + 同步远程
|
||||
Step 8: 提供改动清单供用户审计
|
||||
```
|
||||
@@ -0,0 +1,191 @@
|
||||
# AgentOS 联邦系统 — 代码合并与清理方案 v1.0
|
||||
|
||||
> 目标:消除重复/歧义/新旧版本并存问题,留下一套统一清晰的代码
|
||||
|
||||
---
|
||||
|
||||
## 一、CLI 合并:`mc` + `matrix` → `mc` 统一
|
||||
|
||||
### 1.1 现状
|
||||
|
||||
| 功能 | `mc` (当前主入口) | `matrix` (旧入口) |
|
||||
|:-----|:-----------------|:-----------------|
|
||||
| 账号列表 | ✅ `mc account list` | ✅ `matrix account list`(读不同yaml) |
|
||||
| 账号状态 | ✅ `mc account status` | ✅ `matrix account status`(不同判断方式) |
|
||||
| 账号登录 | ✅ `mc account login` | ✅ `matrix account login`(代码相同) |
|
||||
| **账号创建** | ❌ **没有** | ✅ `matrix account create` → `create_identity.py` |
|
||||
| 账号导出 | ✅ `mc account export` | ❌ |
|
||||
| 账号导入 | ✅ `mc account import` | ❌ |
|
||||
| 蓝图列表 | ✅ `mc blueprint list` | ✅ `matrix config blueprint list` |
|
||||
| **养号执行** | ✅ `mc run` (**BatchEngine**) | ✅ `matrix nurture run` (**nurture_multi**) |
|
||||
| 定时任务 | ✅ `mc task` | ❌ |
|
||||
| 语料库 | ✅ `mc corpus` | ❌ |
|
||||
| 代理 | ✅ `mc proxy` (预留) | ❌ |
|
||||
| SMS | ✅ `mc sms` (预留) | ❌ |
|
||||
| 全局状态 | ✅ `mc status` | ✅ `matrix status` |
|
||||
| **config展示** | ❌ | ✅ `matrix config show` |
|
||||
|
||||
### 1.2 关键问题
|
||||
|
||||
**问题1:`matrix account create` 是 mc 没有的**
|
||||
`mc` 缺少创建身份功能。需要把 `create_identity.py` 的调用移植过来。
|
||||
|
||||
**问题2:`mc account list` 和 `matrix account list` 读不同的 yaml**
|
||||
- `mc account list` → 读 `config/accounts.yaml`(mc配置)
|
||||
- `matrix account list` → 也读 `config/accounts.yaml`(其实是同一个文件)
|
||||
- 这里其实不冲突,只是 `matrix` 把所有 enabled 账号都列出来
|
||||
|
||||
**问题3:养号执行有两套路径**
|
||||
- `mc run` → `BatchEngine` → CDPConnector → DouyinOps/XhsOps → JSON 蓝图
|
||||
- `matrix nurture run` → `nurture_multi` / `nurture_xhs_loop` → `runner.py` → `nurture_blueprint.py` (Python步列表)
|
||||
|
||||
这两套是**完全不同的执行逻辑**!`mc run` 走 JSON 蓝图,`matrix nurture` 走 Python 步列表。
|
||||
|
||||
### 1.3 合并方案
|
||||
|
||||
**目标:只保留 `mc`,`matrix.py` 移入 `archive/`。**
|
||||
|
||||
| 要加的功能 | 加到 `mc` 哪里 | 代码来源 |
|
||||
|:----------|:-------------|:---------|
|
||||
| `mc account create <name>` | `mc/cli.py:cmd_account` → 新增 action="create" | 从 `matrix.py:cmd_account_create` 搬 |
|
||||
| `mc config show` | `mc/cli.py` → 新增子命令 | 从 `matrix.py:cmd_config_show` 搬 |
|
||||
|
||||
**养号执行路径统一**:
|
||||
- **保留 `mc run`**(走 BatchEngine + JSON 蓝图)
|
||||
- **删除 `matrix nurture run`**
|
||||
- `runner.py` 中的 `nurture_multi` / `nurture_xhs_loop` 保留备查,但不再通过 CLI 直接调用
|
||||
|
||||
---
|
||||
|
||||
## 二、Ops 合并:抖音 → 统一 DouyinOps
|
||||
|
||||
### 2.1 现状:抖音有三套操作代码
|
||||
|
||||
| 实现 | 文件 | 形式 | 状态 |
|
||||
|:-----|:------|:------|:------|
|
||||
| **A: DouyinOps 完整类** | `douyin_ops.py` (210行) | 完整类,20个操作 | ✅ **当前使用** (engine.py 调这个) |
|
||||
| **B: ops/douyin/ 拆分布** | `ops/douyin/browse.py` + `interact.py` (70行) | 独立函数,5个操作 | ❌ 轻量版、不完整、未使用 |
|
||||
| **C: runner.py 内联执行** | `runner.py:_execute_op()` | 内联函数,10个操作 | ❌ 旧养号路径在用 |
|
||||
|
||||
**ops/douyin/browse.py + interact.py = 冗余代码**。只有 5 个操作(goto_home, goto_video, scroll_feed, like, collect, comment, next_video),而且和 DouyinOps 功能完全重叠。
|
||||
|
||||
### 2.2 小红书情况
|
||||
|
||||
| 实现 | 文件 | 状态 |
|
||||
|:-----|:------|:------|
|
||||
| **XhsOps** | `ops/xhs_ops.py` | ✅ 当前使用 (engine.py 调这个) |
|
||||
| **runner.py 内联** | `runner.py` 中 `nurture_xhs_loop` | ❌ 旧养号路径在用 |
|
||||
|
||||
小红书只有一套 XhsOps,没有冗余问题。
|
||||
|
||||
### 2.3 Ops 合并方案
|
||||
|
||||
| 操作 | 当前方案 |
|
||||
|:-----|:---------|
|
||||
| `douyin_ops.py` DouyinOps | ✅ **保留为主入口** |
|
||||
| `ops/douyin/browse.py` | **归档**到 `archive/` |
|
||||
| `ops/douyin/interact.py` | **归档**到 `archive/` |
|
||||
| `ops/douyin/` 目录 | **删除**(已被 DouyinOps 完整覆盖) |
|
||||
| `runner.py` 中的 `_execute_op()` | 保持不动(旧养号路径还在用,等迁移完再删) |
|
||||
|
||||
---
|
||||
|
||||
## 三、工具 vs 蓝图:厘清职责
|
||||
|
||||
### 3.1 当前散落的独立工具
|
||||
|
||||
| 文件 | 功能 | 应该归类 |
|
||||
|:-----|:------|:---------|
|
||||
| `collect_homepage_info.py` | 采集用户主页信息(昵称/粉丝/关注) | **走蓝图** (现有 `douyin_read_profile` + `xiaohongshu_read_profile`) |
|
||||
| `collect_batch_runner.py` | 批量采集多个账号 | **走蓝图** + `mc run` 批量执行 |
|
||||
| `publish_video.py` | 视频发布(Camoufox浏览器上传,可选调外部sau CLI) | **Camoufox模式→走蓝图**(加4个发布操作到Ops);sau模式保持独立工具 |
|
||||
| `login_identity.py` | 身份登录 | **走 mc account login** |
|
||||
| `create_identity.py` | 创建新身份 | **走 mc account create** |
|
||||
| `guardd.py` | 系统守护进程 | **不是蓝图**,保持独立 |
|
||||
|
||||
### 3.2 蓝图 vs 工具的定义
|
||||
|
||||
| | 蓝图 (Blueprint) | 工具 (Tool) |
|
||||
|:--|:----------------|:------------|
|
||||
| **做什么** | 操作账号(登录/点赞/评论/采集/发布) | 维护系统(创建身份/管理代理/启动daemon) |
|
||||
| **执行方式** | 被 `mc run` 调用,走浏览器 + 原子操作 | 直接 CLI 调用,不涉及浏览器 |
|
||||
| **定义位置** | `blueprints/*.json` | `scripts/*.py` 或 `mc/*.py` |
|
||||
| **例子** | `douyin_daily`, `douyin_comment`, `xhs_daily` | `create_identity.py`, `guardd.py`, `cdp_connector.py` |
|
||||
|
||||
**结论**:`collect_homepage_info.py` 的功能应该通过 `mc run --blueprint=douyin_read_profile` 来实现。它有独立的 `douyin_read_profile` 蓝图(9步)和 `xiaohongshu_read_profile` 蓝图(8步),只是原来没有通过 `mc run` 统一入口调用。应该改成:
|
||||
|
||||
```bash
|
||||
# 原来: python collect_homepage_info.py --single phone_xxx
|
||||
# 改为: mc run --accounts=douyin_test --blueprints=douyin_read_profile --rounds=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、完整合并行动清单
|
||||
|
||||
### Phase 1: CLI 合并(30分钟)
|
||||
|
||||
| # | 任务 | 改动文件 | 说明 |
|
||||
|:-:|:-----|:---------|:------|
|
||||
| 1 | `mc account create` | `mc/cli.py` | 新增 action="create", 调 create_identity.py |
|
||||
| 2 | `mc config show` | `mc/cli.py` | 新增子命令,搬 matrix.py 的 cmd_config_show |
|
||||
| 3 | `matrix.py` 移入 archive | 删除原文件 | 标记废弃 |
|
||||
|
||||
### Phase 2: Ops 清理(15分钟)
|
||||
|
||||
| # | 任务 | 说明 |
|
||||
|:-:|:-----|:------|
|
||||
| 1 | `ops/douyin/` 目录归档 | browse.py + interact.py 功能完全被 douyin_ops.py 覆盖 |
|
||||
| 2 | 确认 engine.py 只引用 douyin_ops.py | 当前已经是这样,不改 |
|
||||
|
||||
### Phase 3: 工具→蓝图迁移(辅助标注)
|
||||
|
||||
| # | 任务 | 说明 | 操作 |
|
||||
|:-:|:-----|:------|:-----|
|
||||
| 1 | `collect_homepage_info.py` 迁移 | 提取函数(extract_douyin/extract_xiaohongshu)被collect_batch_runner复用 | 保留不动,新增 blueprints 内数据输出能力后自然废弃 |
|
||||
| 2 | `collect_batch_runner.py` 迁移 | 有独特的分批管理/输出格式逻辑,暂不能直接取代 | 保留,待BlueprintEngine支持结构化输出后再迁移 |
|
||||
| 3 | **LoginStateMachine** | ✅ 这才是真正要写的核心模块 | 立即开始写 |
|
||||
|
||||
> **实际优先级调整**:工具→蓝图迁移是清理任务,可延后。
|
||||
> 当下最有价值的是写 `login_state_machine.py`,嵌入到现有的 BatchEngine 执行流中。
|
||||
|
||||
### Phase 4: 废弃代码归档
|
||||
|
||||
| 文件 | 处理 |
|
||||
|:-----|:------|
|
||||
| `matrix.py` (整个) | → `archive/` |
|
||||
| `ops/douyin/browse.py` | → `archive/` |
|
||||
| `ops/douyin/interact.py` | → `archive/` |
|
||||
| `atom_ops.py` | → `archive/` |
|
||||
| `yanghao_runner.py` | → `archive/` |
|
||||
| `orchestrator.py` | → `archive/` |
|
||||
| `step_by_step_v2.py` | → `archive/` |
|
||||
| `step_by_step_v3.py` | → `archive/` |
|
||||
| `xhs_session_test.py` | 删除(测试文件) |
|
||||
| `watch_session.py` | 删除(测试文件) |
|
||||
|
||||
---
|
||||
|
||||
## 五、合并后架构
|
||||
|
||||
```
|
||||
mc CLI (统一入口)
|
||||
├── mc account list|create|login|status|export|import
|
||||
├── mc run --accounts --blueprints --rounds ← 唯一执行入口
|
||||
├── mc blueprint list|show
|
||||
├── mc task comment
|
||||
├── mc corpus list|add|select
|
||||
├── mc proxy list|test|set
|
||||
├── mc sms config|test
|
||||
├── mc status all|accounts|browsers
|
||||
└── mc config show ← 新增
|
||||
|
||||
执行路径 (唯一):
|
||||
mc run → BatchEngine → CDPConnector → Camoufox → DouyinOps / XhsOps → JSON蓝图步
|
||||
|
||||
独立工具 (不通过蓝图, 直接CLI调用):
|
||||
cdp_connector.py 浏览器连接管理
|
||||
create_identity.py 创建身份
|
||||
guardd.py 系统守护进程
|
||||
vision_bridge.py oMLX视觉分析
|
||||
```
|
||||
@@ -0,0 +1,220 @@
|
||||
# AgentOS 命令传导统一治理方案 v1.0
|
||||
|
||||
> 日期: 2026-06-25
|
||||
> 版本: 4.2.1 规划
|
||||
> 状态: 规划中 → 逐步落地中
|
||||
> 主线: 消除调用链路打架,CommandBus 成为唯一执行入口
|
||||
|
||||
---
|
||||
|
||||
## 一、背景与问题
|
||||
|
||||
### 1.1 当前问题清单
|
||||
|
||||
看板经过多次改造迁移,积累了大量不一致的调用路径。扫描发现:
|
||||
|
||||
| # | 问题 | 涉及文件 | 严重程度 |
|
||||
|:-:|:-----|:---------|:---------|
|
||||
| ① | 采集有 **6 条入口路径**,5 条有问题 | `routes/matrix.py`、`services/command_bus.py`、`platforms/`、`mc/cli.py` | P0 |
|
||||
| ② | CommandBus 的 cmd_type 映射散落在 dispatch() 中,不一致 | `services/command_bus.py:698-719` | P0 |
|
||||
| ③ | `platforms/` 插件层引用已归档脚本 | `platforms/douyin/plugin.py`、`platforms/xiaohongshu/plugin.py` | P1 |
|
||||
| ④ | 前端视图参数格式不统一(account_ids vs accounts) | `matrix-collect.js`、`matrix-accounts.js` | P1 |
|
||||
| ⑤ | `routes/matrix.py` 中有路由绕过 CommandBus | `/collect-homepage/phone`、`/nurture/start` | P1 |
|
||||
| ⑥ | `mc collect --all` 无参数时提示退出不执行 | `mc/cli.py:641-652` | P2 |
|
||||
| ⑦ | `agents/plugins/matrix.py` 引用存档脚本 | `agentos/plugins/matrix.py:191` | P2 |
|
||||
|
||||
### 1.2 根因
|
||||
|
||||
```
|
||||
看板改造迁移过程中:
|
||||
旧路径(routes/matrix.py + 直接subprocess)← 未删除
|
||||
新路径(routes/ops.py + CommandBus) ← 新增
|
||||
platforms/ 插件层(引用存档脚本) ← 未同步更新
|
||||
前端视图(分两批迁移,参数格式未统一) ← 未统一
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、治理目标
|
||||
|
||||
### 2.1 核心原则
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ L5 前端视图(薄层) │
|
||||
│ 统一发 {type, accounts, params} │
|
||||
│ 统一走 POST /api/ops/run │
|
||||
├──────────────────────────────────────────────┤
|
||||
│ L4 API 路由(薄层转发) │
|
||||
│ routes/ops.py 是唯一的执行入口 │
|
||||
│ routes/matrix.py 中的执行类路由全部删除 │
|
||||
├──────────────────────────────────────────────┤
|
||||
│ L3 CommandBus(注册表驱动) │
|
||||
│ CMD_REGISTRY 统一映射 cmd_type → 命令 │
|
||||
│ 新增操作只需加一行注册表 │
|
||||
├──────────────────────────────────────────────┤
|
||||
│ L2-L0 mc 引擎 + 原子操作(唯一执行层) │
|
||||
│ 所有命令最终走到同一套引擎 │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 治理后
|
||||
|
||||
| 维度 | 治理前 | 治理后 |
|
||||
|:-----|:-------|:-------|
|
||||
| 采集入口 | 6 个(5 个坏) | 2 个(前端 `/api/ops/run` + CLI `mc collect`)|
|
||||
| 命令映射 | 散落在 dispatch() 中硬编码 | 注册表 `CMD_REGISTRY` |
|
||||
| 前端调用格式 | `account_ids` / `accounts` 混用 | 统一 `{type, accounts, params}` |
|
||||
| 新增操作类型 | 改 CommandBus 代码 | 加一行注册表 |
|
||||
| 平台层 | 两层(PlatformOps + Platform) | 一层(mc 引擎 + 原子操作)|
|
||||
| archive 引用 | 多处 | 零 |
|
||||
|
||||
---
|
||||
|
||||
## 三、实施步骤
|
||||
|
||||
### Phase 0: 方案文档(当前)
|
||||
|
||||
- [x] 创建 `PLANS/COMMAND_UNIFICATION_PLAN.md`(本文档)
|
||||
- [x] 更新 `01_core/VERSION` → 4.2.1
|
||||
- [x] 更新 `CHANGELOG.md`
|
||||
|
||||
### Phase 1: CommandBus 加操作注册表(P0) ✅
|
||||
|
||||
- [x] 在 `services/command_bus.py` 新建 `CMD_REGISTRY` 注册表
|
||||
- [x] 注册表包含:nurture / collect / login / logout / comment / like
|
||||
- [x] collect 默认 `--blueprints` 根据账号平台自动选择
|
||||
- [ ] 验证:所有入口命令格式一致(等启动 Dashboard 后验证)
|
||||
|
||||
**修改文件**:`services/command_bus.py` ✅
|
||||
|
||||
### Phase 2: 前端统一调用路径(P1) ✅
|
||||
|
||||
- [x] `matrix-collect.js` 改走 `POST /api/ops/run {type:'collect', accounts, params}`
|
||||
- [x] 删除 `routes/matrix.py` 中:
|
||||
- `/collect-homepage`
|
||||
- `/collect-homepage/phone`
|
||||
- `/collect-homepage/cancel`
|
||||
- `/collect-homepage/status`
|
||||
- [ ] 验证:信息采集页批量采集功能正常(等启动 Dashboard 后验证)
|
||||
|
||||
**修改文件**:`frontend/src/views/matrix-collect.js` ✅、`routes/matrix.py` ✅
|
||||
|
||||
### Phase 3: CLI mc collect 修复(P2) ✅
|
||||
|
||||
- [x] `mc/cli.py:cmd_collect()` 支持 `--all` 参数
|
||||
- [x] 按手机号采集改为先查账号ID再执行(修复直接传phone的bug)
|
||||
- [x] 新增 `--status` 显示采集状态
|
||||
- [x] 删除废弃提示
|
||||
- [ ] 验证:CLI `mc collect --all` 正常(等实际执行时验证)
|
||||
|
||||
**修改文件**:`mc/cli.py` ✅
|
||||
|
||||
### Phase 4: 标记 platforms/ 为 deprecated(P1) ✅
|
||||
|
||||
- [x] `platforms/douyin/plugin.py` 的 `collect()` 方法不再引用 archive 脚本
|
||||
- [x] `platforms/xiaohongshu/plugin.py` 同上
|
||||
- [x] 添加 deprecated 注释说明替代方案
|
||||
- [ ] 注册到 99_system/INDEX.md(待定,取决于 platforms/ 是否记录在 INDEX)
|
||||
|
||||
**修改文件**:`platforms/*/plugin.py` ✅
|
||||
|
||||
### Phase 5: 更新 AUDIT_5LAYER_REPORT.md(P2) ✅
|
||||
|
||||
- [x] 更新信息采集的审计状态(从 `/matrix/collect-homepage` 改为 `/api/ops/run`)
|
||||
- [x] 添加 CommandBus 注册表审计项
|
||||
|
||||
**修改文件**:`PLANS/AUDIT_5LAYER_REPORT.md` ✅
|
||||
|
||||
---
|
||||
|
||||
## 四、关键设计决策
|
||||
|
||||
### 4.1 CMD_REGISTRY 注册表设计
|
||||
|
||||
```python
|
||||
CMD_REGISTRY = {
|
||||
"nurture": {
|
||||
"runner": "nurture_runner.sh", # shell 包装器
|
||||
"defaults": {"blueprint": "douyin_daily", "rounds": 10},
|
||||
"auto_blueprint": False,
|
||||
},
|
||||
"collect": {
|
||||
"template": "mc run --accounts={ids} --blueprints={blueprint} --rounds={rounds}",
|
||||
"defaults": {"rounds": 1},
|
||||
"auto_blueprint": True,
|
||||
"blueprint_map": {
|
||||
"douyin": "douyin_read_profile",
|
||||
"xiaohongshu": "xiaohongshu_read_profile",
|
||||
},
|
||||
},
|
||||
"login": {
|
||||
"template": "mc smart-login {ids}",
|
||||
"single_account": True,
|
||||
},
|
||||
"logout": {
|
||||
"template": "mc run --accounts={ids} --blueprints=douyin_daily --rounds=1",
|
||||
},
|
||||
"comment": {
|
||||
"template": "mc task comment --account={ids} --url={url}",
|
||||
"required_params": ["url"],
|
||||
},
|
||||
"like": {
|
||||
"template": "mc run --accounts={ids} --blueprints=douyin_daily --rounds=1",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 前端统一调用格式
|
||||
|
||||
```javascript
|
||||
// ✅ 所有操作统一格式
|
||||
await apiRequest('/api/ops/run', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
type: 'collect', // nurture / collect / login / logout / comment / like
|
||||
accounts: ['douyin_01'], // 账号ID列表
|
||||
params: { // 操作参数(可选,不传则用注册表默认值)
|
||||
rounds: 1,
|
||||
// blueprint 由服务端根据账号平台自动推断
|
||||
},
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
### 4.3 与现有架构的关系
|
||||
|
||||
```
|
||||
现有架构:
|
||||
routes/matrix.py → 多个执行入口(需要干掉)
|
||||
routes/ops.py → 统一执行入口(需要保留并做强)
|
||||
CommandBus → 转发层(加注册表)
|
||||
mc CLI → 直接调执行引擎
|
||||
|
||||
治理后:
|
||||
所有执行操作 → routes/ops.py → CommandBus(注册表) → mc 引擎
|
||||
routes/matrix.py 只保留读操作(GET)
|
||||
CLI 直接调 mc 引擎(与 CommandBus 共享执行层)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、版本更新
|
||||
|
||||
| 组件 | 当前版本 | 目标版本 | 变更 |
|
||||
|:-----|:---------|:---------|:-----|
|
||||
| AgentOS 框架 | 4.2.0 | **4.2.1** | 命令传导统一治理 |
|
||||
| guardd | 2.3.0 | 2.3.0 | 无变更 |
|
||||
| ORACLE schema | 1.0 | 1.0 | 无变更 |
|
||||
|
||||
---
|
||||
|
||||
## 六、验证清单
|
||||
|
||||
每阶段完成后验证:
|
||||
|
||||
- [ ] Phase 1: CommandBus 注册表生效,collect 命令带 `--blueprints`
|
||||
- [ ] Phase 2: 信息采集页批量采集功能正常,`/api/matrix/collect-homepage` 路由已删除
|
||||
- [ ] Phase 3: CLI `mc collect --all` 执行所有账号采集
|
||||
- [ ] Phase 4: platforms/plugin 不再引用 archive 脚本
|
||||
- [ ] Phase 5: 审计报告已更新
|
||||
@@ -0,0 +1,295 @@
|
||||
# AgentOS 前端看板调整方案
|
||||
|
||||
> 版本: 1.0 | 日期: 2026-07-04
|
||||
> 后端改动: Phase 1 三队列 + Phase 2 语料重组 + Phase 3 智能评论
|
||||
|
||||
---
|
||||
|
||||
## 一、调整总览
|
||||
|
||||
| 视图 | 文件 | 行数 | 当前状态 | 需要调整 |
|
||||
|:-----|:------|:-----|:---------|:---------|
|
||||
| **指挥台** | `ops-command.js` | 413 | ✅ P0/P1/P2 过滤 + 初始化按钮 | 小修 |
|
||||
| **定向评论** | `matrix-comment.js` | 99 | ❌ 只支持旧 comment 类型 | **大改** |
|
||||
| **语料库** | `matrix-corpus.js` | 573 | ❌ 无行业/accessible 显示 | **大改** |
|
||||
| **账号中心** | `accounts-center.js` | 797 | ❌ 无 smart_comment + industry 显示 | **中改** |
|
||||
| **互动操作** | `matrix-interact.js` | 500 | ⚠️ 有 corpus 浏览但无行业池 | 小修 |
|
||||
| **执行管道** | `execution-pipeline.js` | 300 | ❌ 未被任何视图引用 | 可废弃 |
|
||||
| **命令历史** | `matrix-commands.js` | 221 | ⚠️ 需确认状态展示一致 | 小修 |
|
||||
|
||||
---
|
||||
|
||||
## 二、每项调整详述
|
||||
|
||||
### 2.1 指挥台(ops-command.js)— 小修
|
||||
|
||||
**当前已有功能** ✅
|
||||
- P0/P1/P2 过滤器 ✅
|
||||
- 机器下拉选择 ✅
|
||||
- 初始化/重置全部按钮 ✅
|
||||
- 活动任务网格 + 队列详情 ✅
|
||||
|
||||
**需要补充**:
|
||||
| 补充项 | 原因 | 工作量 |
|
||||
|:-------|:------|:-------|
|
||||
| 在队列详情中区分 smart_comment 任务来源 | 当前 P0 任务只显示优先级,不区分是评论还是智能评论 | ~10行 |
|
||||
| 添加视频分析状态显示(如果是 smart_comment) | VideoAnalyzer 的 `asyncio.run()` 可能执行较久,用户需要知道分析进度 | ~30行 |
|
||||
| 队列详情增加 industry 过滤 | 让用户只看 health 或 general 账号的任务 | ~15行 |
|
||||
|
||||
---
|
||||
|
||||
### 2.2 定向评论(matrix-comment.js)— ❌ 需要大改
|
||||
|
||||
**当前问题**:
|
||||
1. 只支持 `type:'comment'`,不支持 `smart_comment`
|
||||
2. 没有视频分析预览 — 填了链接直接执行,用户不知道会发什么评论
|
||||
3. 语料选择只有硬编码的下拉("通用/科技/生活/美食/娱乐"),不反映后端实际的行业池
|
||||
4. 每个视频×每个账号发一次 `/ops/run`,效率低(N 个账号×M 个链接 = N×M 次 API 调用)
|
||||
|
||||
**需要改为**:
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────┐
|
||||
│ 💬 智能评论(新版) │
|
||||
│ │
|
||||
│ [账号选择器] │
|
||||
│ │
|
||||
│ 视频链接: [textarea 每行一个] │
|
||||
│ │
|
||||
│ 方向: [称赞/提问/共鸣/感慨] 语料: [自动/行业/万能] │
|
||||
│ │
|
||||
│ [▶️ 分析视频] [▶️ 直接执行] │
|
||||
│ │
|
||||
│ ── 分析结果预览 ── │
|
||||
│ url1 → [health] "医生讲得很清楚..." [✏️ 修改] │
|
||||
│ url2 → [general] "博主说得很对..." [✏️ 修改] │
|
||||
│ url3 → [health] "这个方子很实用..." [✏️ 修改] │
|
||||
│ │
|
||||
│ 全部 3 个视频分析完成,预计分发 20 个账号 │
|
||||
│ [✅ 确认并分发] │
|
||||
└───────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**具体改动**:
|
||||
| 改动 | 说明 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| 新增分析按钮 + 预览区 | 先调 `smart_comment` 只分析不分发,返回预览 | ~80行 |
|
||||
| 预评论可编辑 | 用户可在预览区修改每条评论后确认 | ~30行 |
|
||||
| 行业标签显示 | 每个视频分析后显示 `[health]` 或 `[general]` 标签 | ~10行 |
|
||||
| 语料下拉从后端动态加载 | 从 `/matrix/corpus` 接口读取实际分类列表 | ~15行 |
|
||||
| 批量提交 | 分析完的一次性 `POST /ops/run` 全部账号×全部URL | ~20行 |
|
||||
| **合计** | | **~155行** |
|
||||
|
||||
---
|
||||
|
||||
### 2.3 语料库(matrix-corpus.js)— ❌ 需要大改
|
||||
|
||||
**当前现状**:
|
||||
- 573 行,三标签(1D 分类 / 2D 场景 / 3D 多轮)
|
||||
- 分类显示:分类名 + 权重 + 启用状态 + 评论列表
|
||||
- 添加/批量导入/删除
|
||||
- **缺少**:`accessible` 行业标签显示和管理
|
||||
|
||||
**需要改为**:
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────┐
|
||||
│ 📚 语料库 │
|
||||
│ 8 个分类 · 2 个行业池 · 156 条评论 │
|
||||
│ │
|
||||
│ ┌─ 行业过滤 ──────────────────────────────────────────┐
|
||||
│ │ [全部] [万能池] [大健康池] [科技池] [美食池] │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ 大健康称赞 ──── accessible: [health] ───────────┐ │
|
||||
│ │ weight: 30 | enabled: true │ │
|
||||
│ │ "医生讲得很清楚,通俗易懂" [编辑] [删除] │ │
|
||||
│ │ "这个方子很实用,收藏了" [编辑] [删除] │ │
|
||||
│ │ [+ 添加评论] │ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
```
|
||||
|
||||
**具体改动**:
|
||||
| 改动 | 说明 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| 行业池过滤标签 | 在分类列表上方加 accessible 过滤按钮 | ~20行 |
|
||||
| accessible 标记显示 | 每个分类显示 `accessible: ["health"]` 或 `accessible: ["*"]` | ~15行 |
|
||||
| 行业池管理入口 | 添加/编辑分类时可选"允许哪些行业访问" | ~30行 |
|
||||
| 行业池 vs 万能池分离显示 | 万能池标签(称赞/提问/共鸣)显示在独立区域 | ~20行 |
|
||||
| 删除功能修复 | 当前删除按钮可能不工作(查下 delete 端点) | ~10行 |
|
||||
| **合计** | | **~95行** |
|
||||
|
||||
---
|
||||
|
||||
### 2.4 账号中心(accounts-center.js)— 中改
|
||||
|
||||
**当前现状**:
|
||||
- 797 行,账号列表 + 批量操作 + 状态汇总
|
||||
- 批量操作:采集/登录/评论/养号
|
||||
- 评论按钮跳转到 `matrix-comment.js`
|
||||
- **缺少**:industry 字段显示、smart_comment 批量操作
|
||||
|
||||
**需要改为**:
|
||||
|
||||
| 改动 | 说明 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| 账号列表增加 industry 列 | 显示 health/general 标签 | ~15行 |
|
||||
| 按 industry 过滤 | 下拉选择 health/general/全部 | ~15行 |
|
||||
| 批量操作新增"智能评论" | 弹出链接输入+方向+分析预览对话框 | ~60行 |
|
||||
| **合计** | | **~90行** |
|
||||
|
||||
---
|
||||
|
||||
### 2.5 互动操作(matrix-interact.js)— 小修
|
||||
|
||||
**当前现状**:
|
||||
- 500 行,有三个 tab(评论/点赞/关注)
|
||||
- 评论 tab 有 corpus 浏览器 + 关键词匹配
|
||||
- 评论模式下拉:`comment` / `search_browse` / `reply`
|
||||
- **缺少**:smart_comment 模式
|
||||
|
||||
| 改动 | 说明 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| smart_comment 模式选择 | 在模式下拉加"智能评论"选项 | ~10行 |
|
||||
| 方向选择与行业匹配 | 如果选了行业池,自动过滤可选方向 | ~15行 |
|
||||
| **合计** | | **~25行** |
|
||||
|
||||
---
|
||||
|
||||
### 2.6 执行管道组件(execution-pipeline.js)— ❌ 废弃
|
||||
|
||||
**当前现状**:
|
||||
- 300 行,但 **不被任何视图引用**
|
||||
- 搜索 `execution-pipeline.js` 的引用:0 个视图 import
|
||||
- 有 double `/api` 前缀 bug(line 20 `const API = '/api'`,line 146 `api('/api/ops/...')` → `/api/api/ops/...`)
|
||||
|
||||
| 处理 | 说明 |
|
||||
|:-----|:------|
|
||||
| 标记为废弃 | 不移除文件,但在顶部加注释说明 |
|
||||
| 保留未来用 | 如有重构计划可复用,但当前不需要修 |
|
||||
|
||||
---
|
||||
|
||||
### 2.7 命令历史(matrix-commands.js)— 小修
|
||||
|
||||
**当前现状**:
|
||||
- 221 行,显示历史命令列表
|
||||
- 调 `/ops/status` 获取
|
||||
|
||||
| 改动 | 说明 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| 显示 priority 列 | 区分 P0/P1/P2 任务 | ~10行 |
|
||||
| 显示 industry 列 | 如果任务包含 industry 信息 | ~5行 |
|
||||
| **合计** | | **~15行** |
|
||||
|
||||
---
|
||||
|
||||
## 三、修改优先级
|
||||
|
||||
| 优先级 | 视图 | 工作量 | 原因 |
|
||||
|:-------|:------|:-------|:-----|
|
||||
| **P0** | `matrix-comment.js` | ~155行 | **核心功能**: 智能评论的前端入口,用户直接交互 |
|
||||
| **P1** | `matrix-corpus.js` | ~95行 | **体验提升**: 行业池管理,让用户能自定义语料 |
|
||||
| **P1** | `accounts-center.js` | ~90行 | **效率提升**: 批量智能评论入口 |
|
||||
| **P2** | `matrix-interact.js` | ~25行 | 补充优化 |
|
||||
| **P2** | `ops-command.js` | ~55行 | 已有基础功能,补细节 |
|
||||
| **P2** | `matrix-commands.js` | ~15行 | 显示优化 |
|
||||
| - | `execution-pipeline.js` | 0 | 废弃不修 |
|
||||
|
||||
**总计工作量**: ~435 行改动。
|
||||
|
||||
---
|
||||
|
||||
## 四、smart_comment 前端交互流程
|
||||
|
||||
```
|
||||
用户进入「定向评论」页面
|
||||
│
|
||||
├─ 选择账号(账户选择器)
|
||||
├─ 填写视频链接(textarea,每行一个)
|
||||
├─ 选择方向(称赞/提问/共鸣)
|
||||
└─ 选择语料(自动/行业匹配/指定分类)
|
||||
│
|
||||
▼
|
||||
点击「分析视频」
|
||||
│
|
||||
▼
|
||||
前端调 POST /api/ops/run {type:"smart_comment", accounts: [只取1个], params:{urls, direction, preview:true}}
|
||||
↓ 后端 VideoAnalyzer 分析
|
||||
↓ 返回 {url: {title, industry, comment}}
|
||||
│
|
||||
▼
|
||||
前端显示分析结果预览
|
||||
┌─────────────────────────────────────────┐
|
||||
│ url1 → [health] "医生讲得很清楚..." [✏️]│
|
||||
│ url2 → [general] "博主说得很对..." [✏️]│
|
||||
└─────────────────────────────────────────┘
|
||||
用户可逐条修改预评论
|
||||
│
|
||||
▼
|
||||
点击「确认并分发」
|
||||
│
|
||||
▼
|
||||
调 POST /api/ops/run {type:"smart_comment", accounts:[全部], params:{urls, direction, comments:{url:预评论}}}
|
||||
↓
|
||||
后端直接拆解 → 打包 → API 分发到各机 guardd
|
||||
│
|
||||
▼
|
||||
前端切换到指挥台,显示各机队列状态
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、预审/修改流程的关键设计
|
||||
|
||||
**关键设计点:用户在分发前可以看到并修改每条预评论**
|
||||
|
||||
```javascript
|
||||
// 分析结果数据结构(前端存储)
|
||||
let previewData = {
|
||||
urls: {
|
||||
"https://v.douyin.com/xxx": {
|
||||
title: "胃镜到底疼不疼",
|
||||
industry: "health",
|
||||
comment: "医生讲得很清楚,通俗易懂" // 用户可编辑
|
||||
},
|
||||
"https://v.douyin.com/yyy": {
|
||||
title: "苏州美食探店",
|
||||
industry: "general",
|
||||
comment: "博主说得很对" // 用户可编辑
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 用户编辑预评论后,确认分发
|
||||
async function confirmDistribute() {
|
||||
// 收集所有预评论(含用户修改后的)
|
||||
const comments = {};
|
||||
for (const [url, data] of Object.entries(previewData.urls)) {
|
||||
comments[url] = data.comment;
|
||||
}
|
||||
// 一次性分发
|
||||
await apiRequest('/ops/run', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
type: 'smart_comment',
|
||||
accounts: selectedAccounts,
|
||||
params: { urls: Object.keys(comments), comments, direction }
|
||||
})
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、调整汇总工作量
|
||||
|
||||
| 视图 | 当前行数 | 新增行数 | 总行数 |
|
||||
|:-----|:---------|:---------|:-------|
|
||||
| `matrix-comment.js` | 99 | +155 | 254 |
|
||||
| `matrix-corpus.js` | 573 | +95 | 668 |
|
||||
| `accounts-center.js` | 797 | +90 | 887 |
|
||||
| `ops-command.js` | 413 | +55 | 468 |
|
||||
| `matrix-interact.js` | 500 | +25 | 525 |
|
||||
| `matrix-commands.js` | 221 | +15 | 236 |
|
||||
| **Total** | **2603** | **+435** | **~3038** |
|
||||
@@ -0,0 +1,54 @@
|
||||
# 实施进度跟踪
|
||||
|
||||
> 最后更新: 2026-07-16 17:30
|
||||
|
||||
## ✅ Phase 1 — guardd 调度引擎
|
||||
|
||||
| 任务 | 提交 |
|
||||
|:-----|:------|
|
||||
| 1a guardd modules/ 目录拆分 | 015b0579 |
|
||||
| 1b TaskStore + PriorityQueue | 015b0579 |
|
||||
| 1c 孤儿浏览器清理 | 015b0579 |
|
||||
| 1d BrowserSlotManager + 心跳增强 | f36b39cd |
|
||||
| 1e 调度主循环 + Executor + guardd集成 | f36b39cd |
|
||||
|
||||
## ✅ Phase 2 — 联邦指挥台
|
||||
|
||||
| 任务 | 提交 |
|
||||
|:-----|:------|
|
||||
| 2a CommandBus 读写分离 + 任务拆解 | daaf19a2 |
|
||||
| 2b API路由 + 指挥台前端 | 44d561d |
|
||||
| 2c 跨机依赖事件推送 | fffeef6c |
|
||||
|
||||
## ✅ Phase 3 — 高级功能
|
||||
|
||||
| 任务 | 提交 |
|
||||
|:-----|:------|
|
||||
| 3a 指挥台操作(停止/排序按钮)| 7c0f00a |
|
||||
| 3b ORACLE 定时任务同步 | 015b0579 |
|
||||
| 3c 三级接力蓝图 | fffeef6c |
|
||||
| 3d 告警中心 | fffeef6c |
|
||||
| 3e 超时熔断 | fffeef6c |
|
||||
| 账号健康度面板 | 本次 |
|
||||
| 远程机器 launchd 自启 | 本次 |
|
||||
| 拖拽排序按钮 | 本次 |
|
||||
|
||||
## ✅ Phase 4 — 抖追踪 + CDP 采集引擎 (2026-07-15/16)
|
||||
|
||||
| 任务 | 提交 |
|
||||
|:-----|:------|
|
||||
| 4a mediacrawler_adapter — CDP 采集引擎 | 90b3042c |
|
||||
| 4b 抖追踪前端 UI(导入/采集/跟踪/全选) | 90b3042c |
|
||||
| 4c 跟踪专项页 + 评论展开 + 刷新全部 | 38d3ba2f |
|
||||
| 4d 复制链接(单条/已选/全部) | 38d3ba2f |
|
||||
| 4e Chrome debug launchd 自启 | 90b3042c |
|
||||
| 4f KeepAlive true,崩溃自动重启 | e7bb8767 |
|
||||
| 4g 评论工作台粘贴解析「标题+链接」配对 | 7c372bec |
|
||||
| 4h 双行排版标题+网址 | 1b26d235 |
|
||||
| 4i 浏览器标题跟随路由切换 | 7e4a789a |
|
||||
|
||||
## 待做(低优先级)
|
||||
|
||||
- 拖拽排序后端API(目前只有前端按钮)
|
||||
- 三级接力端到端人机验证
|
||||
- 指挥台UI美化
|
||||
@@ -0,0 +1,67 @@
|
||||
# Dashboard 集成审计报告
|
||||
|
||||
> 日期: 2026-06-27 | 基于当前代码状态
|
||||
|
||||
## 执行路径总览
|
||||
|
||||
```
|
||||
前端视图 → POST /api/ops/run {type, accounts, params}
|
||||
→ CommandBus.dispatch()
|
||||
→ 按机器分组
|
||||
→ _send_local() / _send_remote()
|
||||
→ guardd /scheduler/submit (新路径 ✅)
|
||||
→ guardd /task (旧路径降级)
|
||||
→ subprocess / SSH (最终降级)
|
||||
```
|
||||
|
||||
## 各视图集成状态
|
||||
|
||||
### ✅ 已走新路径(CommandBus → guardd 调度引擎)
|
||||
|
||||
| 视图 | 操作类型 | 提交方式 |
|
||||
|:-----|:---------|:---------|
|
||||
| `matrix-accounts.js` | collect, login | `fetch('/api/ops/run')` → 新路径 |
|
||||
| `matrix-collect.js` | collect | `apiRequest('/api/ops/run')` → 新路径 |
|
||||
| `matrix-nurture.js` | nurture | `apiRequest('/api/ops/run')` → 新路径 |
|
||||
| `matrix-comment.js` | comment | `apiRequest('/api/ops/run')` → 新路径 |
|
||||
| `matrix-interact.js` | interact | `apiRequest('/api/ops/run')` → 新路径 |
|
||||
| `matrix-like.js` | like | `apiRequest('/api/ops/run')` → 新路径 |
|
||||
| `ops-command.js` | 联邦指挥台 | 读 `/api/ops/queue` + `/api/ops/machines` |
|
||||
|
||||
### 🔶 需要注意的点
|
||||
|
||||
| 问题 | 说明 |
|
||||
|:-----|:------|
|
||||
| **账号管理页采集不显示在指挥台** | 已修复: `_send_local()` 优先走 scheduler,旧路径降级 |
|
||||
| **指挥台只读不写** | 目前指挥台只能"看"不能"操作"(Phase 3a 实现) |
|
||||
| **旧 `/task` 路径仍保留** | 作为降级方案,guardd 不可用时自动 fallback |
|
||||
| **nurture_runner.sh 未集成到调度器** | 养号任务仍走旧 nurture_runner.sh 路径(通过 /task 降级) |
|
||||
|
||||
### ⏳ 待实现(Phase 3)
|
||||
|
||||
| 功能 | 优先级 |
|
||||
|:-----|:-------|
|
||||
| 指挥台操作按钮(取消/暂停/重排) | P0 |
|
||||
| 告警中心(封号/登录失败高亮) | P1 |
|
||||
| 三级接力 | P2 |
|
||||
| 任务超时熔断自动恢复 | P1 |
|
||||
|
||||
## 当前数据流
|
||||
|
||||
```
|
||||
用户点击"采集"
|
||||
↓
|
||||
matrix-accounts.js → POST /api/ops/run
|
||||
↓
|
||||
CommandBus.dispatch("collect", [account_id], params)
|
||||
↓
|
||||
_send_local() → guardd /scheduler/submit
|
||||
↓
|
||||
guardd scheduler → 15s循环 → executor.execute()
|
||||
↓
|
||||
指挥台每15秒 poll /api/ops/queue → 看到任务
|
||||
```
|
||||
|
||||
## 测试方法
|
||||
|
||||
在账号管理页点"采集" → 等15秒 → 刷新指挥台 → 应该能看到任务出现在队列中
|
||||
@@ -0,0 +1,551 @@
|
||||
# 评论互动系统 — 详细规划
|
||||
|
||||
> 版本: v1.0-draft | 日期: 2026-06-25
|
||||
> 范围: 定向评论 + 收藏点赞 → 合并为"评论互动"全功能
|
||||
> 基于: AgentOS 联邦多机协同 + CommandBus 分发 + 现有蓝图引擎
|
||||
|
||||
---
|
||||
|
||||
## 一、功能全景
|
||||
|
||||
### 1.1 核心能力
|
||||
|
||||
| 能力 | 说明 |
|
||||
|:-----|:------|
|
||||
| **定向评论** | 给指定视频/博主评论,多个账号参与 |
|
||||
| **三级接力评论** | A评→B回复A→C回复B,形成互动链 |
|
||||
| **点赞互动** | 点赞视频/评论/关注评论者 |
|
||||
| **定时错开** | 跨小时/跨天的评论时间编排 |
|
||||
| **跨机协同** | 三台机器之间任务分配与排队 |
|
||||
| **语料集成** | 现有语料库(L1-L4)复用 + 上下文感知 |
|
||||
| **评论载体** | 文字 + emoji + 图片(预留) |
|
||||
|
||||
### 1.2 用户场景
|
||||
|
||||
```
|
||||
用户输入:
|
||||
博主/视频链接: https://www.douyin.com/video/xxx
|
||||
或博主主页: https://www.douyin.com/user/xxx
|
||||
互动策略: 热评互动 / 三级接力 / 点赞关注
|
||||
时间窗口: 2小时 / 跨天
|
||||
参与账号: douyin_136, xhs_7 (自动分配给7kecheng)
|
||||
douyin_01, xhs_01 (自动分配给5kechengdeAir)
|
||||
|
||||
系统输出:
|
||||
自动编排 → 按机器+时间分配任务
|
||||
→ 机器1 13:00 douyin_136 发评论A
|
||||
→ 机器2 13:05 douyin_01 回复A
|
||||
→ 机器1 13:10 xhs_7 回复B
|
||||
→ 全部完成后汇总报告
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、架构设计
|
||||
|
||||
### 2.1 系统分层
|
||||
|
||||
```
|
||||
L5 看板层 ── 评论互动视图 (matrix-interact.js)
|
||||
│ POST /api/ops/run {type:'interact', accounts, params:{...}}
|
||||
L4 路由层 ── routes/ops.py (已存在,复用)
|
||||
│ → CommandBus.dispatch('interact', ...)
|
||||
L3 分发层 ── CommandBus + CMD_REGISTRY (已存在,扩展)
|
||||
│ → 按机器分组 → 每机一条 interact 命令
|
||||
│ → 高级编排: InteractOrchestrator
|
||||
L2 编排层 ── InteractOrchestrator (新增)
|
||||
│ ├── 解析互动策略
|
||||
│ ├── 生成时间线 (谁在什么时间做什么)
|
||||
│ ├── 拆解为原子任务 (每个账号每个时间点一条)
|
||||
│ └── 写入跨机任务队列
|
||||
L1 执行层 ── 现有 mc run + 蓝图引擎 (复用)
|
||||
│ 新增互动蓝图: interact_chain, interact_like, interact_comment
|
||||
│ 复用现有: douyin_ops.py, xhs_ops.py (post_comment, like, follow)
|
||||
L0 浏览器层 ── Camoufox (已有,不变)
|
||||
```
|
||||
|
||||
### 2.2 新增模块
|
||||
|
||||
```
|
||||
05_tools/07_matrix/
|
||||
├── scripts/
|
||||
│ ├── mc/
|
||||
│ │ ├── cli.py ← 新增: interact 子命令
|
||||
│ │ ├── interact.py ← [新增] 互动引擎 (InteractOrchestrator)
|
||||
│ │ │ ├── InteractOrchestrator — 主编排器
|
||||
│ │ │ ├── InteractionPlan — 互动计划
|
||||
│ │ │ ├── TimeLine — 时间线
|
||||
│ │ │ └── ChainStrategy — 接力策略
|
||||
│ │ └── engine.py ← 扩展: 支持互动蓝图的 resolve_args
|
||||
│ ├── matrix_modules/
|
||||
│ │ └── interact/ ← [新增] 互动模块
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── chain.py — 三级接力逻辑
|
||||
│ │ ├── timeline.py — 时间线生成
|
||||
│ │ └── strategy.py — 互动策略选择
|
||||
├── blueprints/
|
||||
│ ├── interact_chain.json ← [新增] 三级接力蓝图
|
||||
│ ├── interact_comment.json ← [新增] 定向评论蓝图
|
||||
│ ├── interact_like.json ← [新增] 点赞互动蓝图
|
||||
│ └── interact_hot.json ← [新增] 热评互动蓝图
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、蓝图设计
|
||||
|
||||
### 3.1 定向评论蓝图 (interact_comment)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "interact_comment",
|
||||
"name": "互动-定向评论",
|
||||
"description": "给指定视频发评论(含语料库+表情)",
|
||||
"version": "1.0",
|
||||
"platform": "douyin",
|
||||
"steps": [
|
||||
{"step_id": 1, "op": "goto_url", "args": {"url": "@url"}},
|
||||
{"step_id": 2, "op": "wait_watch", "args": {"seconds": null}},
|
||||
{"step_id": 3, "op": "open_comments", "args": {}},
|
||||
{"step_id": 4, "op": "post_comment", "args": {"text": "@comment_text"}},
|
||||
{"step_id": 5, "op": "close_comments", "args": {}}
|
||||
],
|
||||
"args_schema": {
|
||||
"url": {"type": "string", "required": true, "desc": "视频链接"},
|
||||
"comment_text": {"type": "string", "required": true, "desc": "评论内容,支持@corpus从语料库取"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 三级接力蓝图 (interact_chain)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "interact_chain",
|
||||
"name": "互动-三级接力",
|
||||
"description": "A评→B回复A→C回复B,形成互动链",
|
||||
"version": "1.0",
|
||||
"platform": "douyin",
|
||||
"steps": [
|
||||
{"step_id": 1, "op": "goto_url", "args": {"url": "@url"}},
|
||||
{"step_id": 2, "op": "wait_watch", "args": {"seconds": null}},
|
||||
{"step_id": 3, "op": "open_comments", "args": {}},
|
||||
{"step_id": 4, "op": "post_comment", "args": {"text": "@comment_text"}},
|
||||
{"step_id": 5, "op": "close_comments", "args": {}},
|
||||
{"step_id": 6, "op": "reply_to_comment", "args": {"target": "@reply_to", "text": "@reply_text"}}
|
||||
],
|
||||
"args_schema": {
|
||||
"url": {"required": true},
|
||||
"comment_text": {"desc": "一级评论内容"},
|
||||
"reply_to": {"desc": "回复目标的评论ID或用户名"},
|
||||
"reply_text": {"desc": "回复内容"},
|
||||
"chain_position": {"enum": ["first", "reply", "second_reply"]}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
蓝图不分三级为三个独立的蓝图。**用同一个蓝图 + 不同参数**,InteractOrchestrator 根据 `chain_position` 决定每个账号执行哪一步。
|
||||
|
||||
### 3.3 点赞互动蓝图 (interact_like)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "interact_like",
|
||||
"name": "互动-点赞互动",
|
||||
"description": "点赞视频+点赞评论+关注评论者",
|
||||
"version": "1.0",
|
||||
"platform": "douyin",
|
||||
"steps": [
|
||||
{"step_id": 1, "op": "goto_url", "args": {"url": "@url"}},
|
||||
{"step_id": 2, "op": "wait_watch", "args": {"seconds": null}},
|
||||
{"step_id": 3, "op": "like", "args": {}},
|
||||
{"step_id": 4, "op": "open_comments", "args": {}},
|
||||
{"step_id": 5, "op": "like_comment", "args": {"target": "@target_comment"}},
|
||||
{"step_id": 6, "op": "follow_user", "args": {"target": "@target_user"}},
|
||||
{"step_id": 7, "op": "close_comments", "args": {}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 热评互动蓝图 (interact_hot)
|
||||
|
||||
组合评论 + 点赞 + 回复热评:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "interact_hot",
|
||||
"name": "互动-热评互动",
|
||||
"description": "在热门评论下回复,提升曝光",
|
||||
"version": "1.0",
|
||||
"platform": "douyin",
|
||||
"steps": [
|
||||
{"step_id": 1, "op": "goto_url", "args": {"url": "@url"}},
|
||||
{"step_id": 2, "op": "open_comments", "args": {}},
|
||||
{"step_id": 3, "op": "scroll_to_hot_comment", "args": {}},
|
||||
{"step_id": 4, "op": "like_comment", "args": {"target": "first_hot"}},
|
||||
{"step_id": 5, "op": "reply_to_comment", "args": {"text": "@reply_text"}},
|
||||
{"step_id": 6, "op": "close_comments", "args": {}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、任务编排引擎 (InteractOrchestrator)
|
||||
|
||||
### 4.1 核心流程
|
||||
|
||||
```
|
||||
用户输入:
|
||||
{url, strategy, accounts, time_window}
|
||||
|
||||
InteractOrchestrator.plan()
|
||||
│
|
||||
├── 1. 解析互动策略
|
||||
│ strategy="chain" → 生成三级接力计划
|
||||
│ strategy="comment" → 生成批量评论计划
|
||||
│ strategy="like" → 生成点赞互动计划
|
||||
│ strategy="hot" → 生成热评互动计划
|
||||
│
|
||||
├── 2. 生成时间线
|
||||
│ 根据 time_window + interval 计算每个账号的执行时间
|
||||
│ 例: 3账号 × 三级接力
|
||||
│ 账号A 13:00 发评论 → 间隔5分钟
|
||||
│ 账号B 13:05 回复A → 间隔5分钟
|
||||
│ 账号C 13:10 回复B → 完成
|
||||
│
|
||||
├── 3. 拆解为原子任务
|
||||
│ 每个 (账号, 时间, 蓝图, 参数) = 一条原子任务
|
||||
│ 每台机器独占一条(机器级别串行,账号级别串行)
|
||||
│
|
||||
├── 4. 写入任务队列
|
||||
│ 通过 CommandBus 分发到各台机器
|
||||
│ → 不立即执行,先写入任务数据库(带时间戳)
|
||||
│ → guardd 或守护线程按时触发
|
||||
│
|
||||
└── 5. 返回计划
|
||||
{plan: [...], status: "scheduled"}
|
||||
```
|
||||
|
||||
### 4.2 时间线生成算法
|
||||
|
||||
```
|
||||
输入: accounts=[A, B, C], strategy="chain", window={start: "13:00", end: "15:00"}
|
||||
|
||||
chain 策略:
|
||||
A 在 13:00 → 发评论 (first)
|
||||
B 在 13:00 + offset1 → 回复A (reply, reply_to=A)
|
||||
C 在 13:00 + offset1 + offset2 → 回复B (second_reply, reply_to=B)
|
||||
|
||||
其中 offset = random(300, 600) 秒 (5-10分钟)
|
||||
支持跨小时: offset 累加可以到 next hour
|
||||
|
||||
batch 策略:
|
||||
A 在 13:00 → 评论 (内容1)
|
||||
B 在 13:00 + random(300,900) → 评论 (内容2)
|
||||
C 在 13:00 + random(600,1800) → 评论 (内容3)
|
||||
|
||||
like 策略:
|
||||
A 在 13:00 → 点赞视频+关注博主
|
||||
B 在 13:00 + random(120,600) → 点赞视频+点赞热评
|
||||
```
|
||||
|
||||
### 4.3 跨机任务排队
|
||||
|
||||
```
|
||||
CommandBus.dispatch("interact", all_accounts, params)
|
||||
→ 按 machine 分组
|
||||
→ 每台机器构建一条 InteractOrchestrator 任务
|
||||
|
||||
每台机器上:
|
||||
MachineSession 串行队列
|
||||
|
||||
[interact_任务A] → 执行A → 完成后
|
||||
[等待中到13:05] → 定时器触发
|
||||
[interact_任务B] → 执行B → 完成后
|
||||
...
|
||||
```
|
||||
|
||||
**关键**:定时触发不是由 CommandBus 的 poll 守卫做,而是由 **InteractOrchestrator 在机器本地启动一个延迟协程**。
|
||||
|
||||
执行流程:
|
||||
```python
|
||||
class InteractOrchestrator:
|
||||
async def execute_plan(self, plan: InteractionPlan):
|
||||
"""按时间线顺序执行所有子任务"""
|
||||
for step in plan.timeline:
|
||||
# 等待到指定时间
|
||||
wait_seconds = (step.scheduled_at - datetime.now()).total_seconds()
|
||||
if wait_seconds > 0:
|
||||
await asyncio.sleep(wait_seconds)
|
||||
# 执行当前步骤
|
||||
result = await self._execute_step(step)
|
||||
step.result = result
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、看板集成 (Dashboard)
|
||||
|
||||
### 5.1 新视图: 评论互动 (matrix-interact.js)
|
||||
|
||||
参照现在 `matrix-collect.js` 和 `matrix-nurture.js` 的模式:
|
||||
|
||||
```javascript
|
||||
// 使用已有 account-selector 组件
|
||||
// ① 选择账号
|
||||
// ② 输入互动参数(URL/博主/策略/时间)
|
||||
// ③ 提交 → POST /api/ops/run {type:'interact', accounts, params}
|
||||
```
|
||||
|
||||
**交互流程**:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 💬 评论互动 │
|
||||
│ │
|
||||
│ 账号选择器 (复用 createAccountSelector) │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ ☑ douyin_136 🎵 7kecheng │ │
|
||||
│ │ ☑ xhs_7 📕 7kecheng │ │
|
||||
│ │ ☑ douyin_01 🎵 5kechengdeAir │ │
|
||||
│ │ ... │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ 互动参数: │
|
||||
│ 视频链接 [________________________] 📋 │
|
||||
│ 互动策略 [热评互动 ▼] [三级接力] [点赞] │
|
||||
│ 时间窗口 [13:00] ~ [15:00] │
|
||||
│ 延迟间隔 [5-10] 分钟 / 步 │
|
||||
│ 语料分类 [美食 ▼] [旅行] [通用] │
|
||||
│ │
|
||||
│ [🔍 预检] [🚀 提交互动] │
|
||||
│ │
|
||||
│ 执行计划预览: │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ 13:00 douyin_136 → 发评论 "看着就很有.." │ │
|
||||
│ │ 13:05 xhs_7 → 回复 ↑ "同意!.." │ │
|
||||
│ │ 13:12 douyin_01 → 回复 xhs_7 "... " │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.2 API 路由
|
||||
|
||||
复用现有 `POST /api/ops/run`,新增 type `interact`:
|
||||
|
||||
```json
|
||||
POST /api/ops/run
|
||||
{
|
||||
"type": "interact",
|
||||
"accounts": ["douyin_136", "xhs_7", "douyin_01"],
|
||||
"params": {
|
||||
"strategy": "chain",
|
||||
"url": "https://www.douyin.com/video/xxx",
|
||||
"time_window": {"start": "13:00", "end": "15:00"},
|
||||
"interval": {"min": 300, "max": 600},
|
||||
"corpus_category": "food",
|
||||
"chain_position": {
|
||||
"douyin_136": "first",
|
||||
"xhs_7": "reply",
|
||||
"douyin_01": "second_reply"
|
||||
},
|
||||
"dry_run": true // 预检模式:只返回计划不执行
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 CMD_REGISTRY 扩展
|
||||
|
||||
```python
|
||||
CMD_REGISTRY = {
|
||||
...,
|
||||
"interact": {
|
||||
"runner": None, # 不走 nurture_runner.sh,直接调 InteractOrchestrator
|
||||
"defaults": {"rounds": 1},
|
||||
"single_account": False,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、现有代码复用清单
|
||||
|
||||
### 6.1 可直接复用的
|
||||
|
||||
| 组件 | 用途 |
|
||||
|:-----|:------|
|
||||
| `account-selector.js` | 账号选择器(不改) |
|
||||
| `routes/ops.py` | API 路由(扩展 type=interact) |
|
||||
| `CommandBus` | 按机器分发、排队(复用) |
|
||||
| `MachineSession` | 串行队列(复用) |
|
||||
| `douyin_ops.post_comment(text)` | 评论发送(复用) |
|
||||
| `douyin_ops.like()` | 点赞(复用) |
|
||||
| `douyin_ops.follow()` | 关注(复用) |
|
||||
| `xhs_ops.xhs_comment(text)` | 小红书评论(复用) |
|
||||
| `corpus.py` | 语料库(复用) |
|
||||
| `ai_generator.py` | AI 评论生成(复用) |
|
||||
| `nurture_runner.sh` | 执行包装器(可选复用,interact 可能直接走 mc run) |
|
||||
|
||||
### 6.2 需要新增/扩展的
|
||||
|
||||
| 组件 | 说明 |
|
||||
|:-----|:------|
|
||||
| `mc/interact.py` | InteractOrchestrator 编排引擎 |
|
||||
| `mc/cli.py` | 新增 `mc interact` 子命令 |
|
||||
| `blueprints/interact_*.json` | 互动蓝图 |
|
||||
| `matrix_modules/interact/` | 互动模块(chain、timeline、strategy)|
|
||||
| `douyin_ops.reply_to_comment()` | 回复评论原子操作 **(新增)** |
|
||||
| `douyin_ops.like_comment()` | 点赞评论原子操作 **(新增)** |
|
||||
| `douyin_ops.scroll_to_hot_comment()` | 滚动到热评(新增) |
|
||||
| `frontend/src/views/matrix-interact.js` | 看板视图 |
|
||||
|
||||
### 6.3 新增原子操作
|
||||
|
||||
```python
|
||||
# douyin_ops.py
|
||||
|
||||
async def reply_to_comment(self, page, target: str, text: str) -> bool:
|
||||
"""回复指定评论。target 可以是评论序号或评论者用户名"""
|
||||
# 1. 找到目标评论的回复按钮
|
||||
# 2. 点击"回复"
|
||||
# 3. 输入框聚焦
|
||||
# 4. 填入回复内容
|
||||
# 5. 发送
|
||||
pass
|
||||
|
||||
async def like_comment(self, page, target: str = "first_hot") -> bool:
|
||||
"""点赞评论。target=first_hot / 指定序号"""
|
||||
# 1. 找到目标评论
|
||||
# 2. 找到点赞按钮(大拇指/心形)
|
||||
# 3. 点击
|
||||
pass
|
||||
|
||||
async def follow_user(self, page, target: str) -> bool:
|
||||
"""关注指定用户(从评论区)"""
|
||||
pass
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、语料库增强(三级互动语料)
|
||||
|
||||
现有语料库是单条评论。三级互动需要**配对语料**:
|
||||
|
||||
```python
|
||||
# 新增: interact_corpus.py 或扩展 corpus.py
|
||||
|
||||
# 三级互动语料对
|
||||
CHAIN_CORPUS = {
|
||||
"food": {
|
||||
"first": "看着就很有食欲,周末去试试",
|
||||
"reply": "同意!上次吃过一次确实不错",
|
||||
"second_reply": "我也去过!他家那个招牌菜绝了"
|
||||
},
|
||||
"tech": {
|
||||
"first": "这个技术分析很透彻,学到了",
|
||||
"reply": "对,特别是第三点我之前完全没想到",
|
||||
"second_reply": "是的,按照这个方法试了效果很好"
|
||||
},
|
||||
"travel": {
|
||||
"first": "这个地方太美了,已加入旅行清单",
|
||||
"reply": "去年去过,风景确实很好,值得二刷",
|
||||
"second_reply": "求攻略!准备下个月去"
|
||||
},
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
每套三级语料包含三个层次的评论,形成一个自然的对话流。
|
||||
|
||||
---
|
||||
|
||||
## 八、实施路线图
|
||||
|
||||
### Phase 1(基础能力)— 2天
|
||||
|
||||
| 任务 | 产出 |
|
||||
|:-----|:------|
|
||||
| 新增 `douyin_ops.reply_to_comment()` | 原子操作 |
|
||||
| 新增 `douyin_ops.like_comment()` | 原子操作 |
|
||||
| 编写 3 个互动蓝图 JSON | blueprints |
|
||||
| 扩展 `corpus.py` 增加三级接力语料 | 语料库 |
|
||||
| 构建 `matrix-interact.js` 基础视图 | 看板 |
|
||||
| 扩展 CMD_REGISTRY 增加 interact 类型 | 后端 |
|
||||
|
||||
### Phase 2(编排引擎)— 2天
|
||||
|
||||
| 任务 | 产出 |
|
||||
|:-----|:------|
|
||||
| 实现 `InteractOrchestrator` 核心 | mc/interact.py |
|
||||
| 时间线生成算法 | timeline.py |
|
||||
| 跨机任务队列 | interact 走 CommandBus |
|
||||
| 预检功能 (dry_run) | 返回计划预览 |
|
||||
|
||||
### Phase 3(高级功能)— 2天
|
||||
|
||||
| 任务 | 产出 |
|
||||
|:-----|:------|
|
||||
| 三级接力全流程联调 | chain 端到端 |
|
||||
| 跨小时定时触发 | asyncio sleep / guardd定时 |
|
||||
| 看板计划预览 | 前端展示时间线 |
|
||||
| 执行进度跟踪 | status API |
|
||||
|
||||
### Phase 4(增强)— 持续
|
||||
|
||||
| 任务 | 产出 |
|
||||
|:-----|:------|
|
||||
| 图片/表情包评论 | 蓝图扩展 |
|
||||
| AI 生成评论(oMLX) | 对接现有 ai_generator |
|
||||
| 互动效果分析 | 看板统计 |
|
||||
| 自动策略推荐 | 基于账号健康度 |
|
||||
|
||||
---
|
||||
|
||||
## 九、关键设计决策
|
||||
|
||||
| 决策 | 选择 | 理由 |
|
||||
|:-----|:------|:------|
|
||||
| 蓝图复用 vs 新建 | 新建互动蓝图系列 | 避免污染现有养号蓝图 |
|
||||
| 定时触发方式 | InteractOrchestrator 内部 sleep | 简单可靠,不依赖外部调度 |
|
||||
| 三级接力实现 | 同一个蓝图+chain_position 参数 | 减少蓝图数量,参数化驱动 |
|
||||
| 跨机协同 | 复用 CommandBus 队列 | 已有成熟的分发/排队机制 |
|
||||
| 看板视图 | 新建 matrix-interact.js | 功能独立,不与现有视图耦合 |
|
||||
| CMD_REGISTRY 扩展 | 新增 type=interact | 统一入口,不走硬编码分支 |
|
||||
|
||||
---
|
||||
|
||||
## 十、与现有系统的关系
|
||||
|
||||
```
|
||||
现有系统 新增系统
|
||||
──────── ────────
|
||||
养号 (nurture) 评论互动 (interact)
|
||||
├── 日常浏览 ├── 定向评论
|
||||
├── 随机点赞/评论 ├── 三级接力
|
||||
├── asyncio.gather ├── 时间线编排
|
||||
└── 蓝图 douyin_daily └── 互动蓝图系列
|
||||
|
||||
采集 (collect) 点赞 (like) → 并入 interact
|
||||
├── 读主页信息
|
||||
└── 写 profiles.json
|
||||
|
||||
登录 (login) 评论 (comment) → 并入 interact
|
||||
├── smart-login
|
||||
└── 状态检测
|
||||
```
|
||||
|
||||
**合并策略**:`like` 和 `comment` 类型的 `CMD_REGISTRY` 保留向后兼容,但前端视图统一到 `matrix-interact.js`,不再使用独立的 `matrix-comment.js` 和 `matrix-like.js`。
|
||||
|
||||
---
|
||||
|
||||
## 十一、风险与对策
|
||||
|
||||
| 风险 | 概率 | 影响 | 对策 |
|
||||
|:-----|:----:|:----:|:------|
|
||||
| 回复评论 DOM 结构变化 | 高 | 中 | CSS 选择器 + JS 多兜底 |
|
||||
| 跨小时 sleep 被中断 | 中 | 高 | 使用 guardd 持久化定时器 |
|
||||
| 同一时间多账号冲突 | 中 | 中 | MachineSession 队列保证单线程 |
|
||||
| 抖音限流/封号 | 低 | 高 | 不超过每天10条/账号 |
|
||||
| 三级接力找不到目标评论 | 中 | 中 | fallback 到独立评论 |
|
||||
@@ -0,0 +1,221 @@
|
||||
# AgentOS 命令传导与采集系统——全面优化规划 v2.0
|
||||
|
||||
> 日期: 2026-06-25 | 版本: 4.2.1
|
||||
> 基于: CONSTITUTION.md、FEDERATION_GUIDE.md、AUDIT_5LAYER_REPORT.md、COMMAND_UNIFICATION_PLAN.md
|
||||
> 覆盖: 命令传导全链路 + 信息采集全链路 + 远程执行 + 数据持久化 + 封号检测
|
||||
|
||||
---
|
||||
|
||||
## 一、当前架构全景
|
||||
|
||||
```
|
||||
L5 前端视图 (12个操作视图)
|
||||
│ 统一格式: {type, accounts, params}
|
||||
│ 统一入口: POST /api/ops/run
|
||||
▼
|
||||
L4 API 路由
|
||||
├── routes/ops.py ← ✅ 统一执行入口(已治理)
|
||||
└── routes/matrix.py ← ✅ 只保留 GET 读操作(已治理)
|
||||
▼
|
||||
L3 CommandBus
|
||||
├── CMD_REGISTRY ← ✅ 注册表(已治理)
|
||||
├── dispatch() ← ✅ 注册表驱动(已治理)
|
||||
├── MachineSession ← ✅ 每机队列(已治理)
|
||||
├── CMD_POLL_STRATEGY ← ✅ 按类型策略(已治理)
|
||||
└── poll守卫线程 ← ✅ 15s自动检测(已治理)
|
||||
▼
|
||||
L2 mc 引擎
|
||||
├── nurture_runner.sh ← ⚠️ 远程参数默认值已修
|
||||
├── BatchEngine ← ✅ 支持封号标记
|
||||
└── LoginStateMachine ← ✅ 支持banned状态
|
||||
▼
|
||||
L1 平台原子操作
|
||||
├── douyin_ops.py ← ✅ 封号检测+同步写homepage_info
|
||||
└── ops/xhs_ops.py ← ✅ 封号检测+同步写homepage_info
|
||||
▼
|
||||
L0 Camoufox 浏览器
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、剩余问题清单(按优先级)
|
||||
|
||||
### P0 —— 必须修(功能阻断)
|
||||
|
||||
| # | 问题 | 发现时间 | 涉及文件 |
|
||||
|:-:|:-----|:---------|:---------|
|
||||
| ① | **远程 nurture 空值参数导致参数错位** | 2026-06-25 | `command_bus.py:_send_remote` ✅ **已修复** |
|
||||
| ② | **前端批量账号逐个发送**(matrix-nurture) | 2026-06-25 | `matrix-nurture.js` ✅ **已修复** |
|
||||
| — | 以上两个问题已修复并推送 | — | — |
|
||||
|
||||
### P1 —— 应修(影响体验/一致性和正确性)
|
||||
|
||||
| # | 问题 | 涉及文件 | 说明 |
|
||||
|:-:|:-----|:---------|:------|
|
||||
| ③ | **`routes/matrix.py` 中 `/nurture/start` 和 `/nurture/preview` 绕过 CommandBus** | `routes/matrix.py:333-443` | 约100行 POST 代码直接调引擎,不走 CommandBus |
|
||||
| ④ | **`routes/matrix.py` 中 `/task/run` 路由绕过 CommandBus** | `routes/matrix.py:757-790` | 任务执行直接 subprocess |
|
||||
| ⑤ | **`matrix-accounts.js` 单账号采集(`_actCol`)+登录(`_actLogin`)逐个发送** | `matrix-accounts.js:121-145` | 和修复前的 `_nurtureExec` 一样的问题 |
|
||||
| ⑥ | **`matrix-comment.js` 评论执行逐个发送** | `matrix-comment.js` | 需要审计 |
|
||||
| ⑦ | **`matrix-like.js` 收藏点赞逐个发送** | `matrix-like.js` | 需要审计 |
|
||||
| ⑧ | **CMD_REGISTRY 中 comment 的模板含 `{direction}`,可能缺失** | `command_bus.py:631` | 前端可能不传 direction |
|
||||
| ⑨ | **nurture 在 CMD_REGISTRY 中定义了 `runner` 字段但 dispatch 未使用** | `command_bus.py:640` | 注册表与实际逻辑不一致 |
|
||||
|
||||
### P2 —— 可修(清理/优化/后续)
|
||||
|
||||
| # | 问题 | 涉及文件 | 说明 |
|
||||
|:-:|:-----|:---------|:------|
|
||||
| ⑩ | **`platforms/` 目录已标记 deprecated 但代码还存在** | `platforms/` | 等待最终清理 |
|
||||
| ⑪ | **`agentos/plugins/matrix.py` 引用存档脚本** | `agentos/plugins/matrix.py:189-192` | 依然引用 `collect_batch_runner.py` |
|
||||
| ⑫ | **`scripts/archive/` 中的旧脚本可移出** | `scripts/archive/` | 确认无引用后移除 |
|
||||
| ⑬ | **`routes/matrix.py` 中 `/nurture/preview`(GET读操作)可保留但需要文档说明** | `routes/matrix.py:333` | 仅预览功能 |
|
||||
| ⑭ | **联邦机器 `fleet_collector` 缓存过期后 Dashboard 读到旧数据** | `services/fleet_collector.py` | 需要自动刷新机制 |
|
||||
| ⑮ | **Dashboard 信息采集页展示多渠道数据聚合时的去重** | `routes/matrix.py` | 多台机器有同一个账号时重复显示 |
|
||||
| ⑯ | **`crawl-tasks.js`、`crawl-sources.js` 等占位符视图无功能** | `views/crawl-*.js` | 11个占位符 |
|
||||
|
||||
### P3 —— 远期(架构优化)
|
||||
|
||||
| # | 问题 | 说明 |
|
||||
|:-:|:-----|:------|
|
||||
| ⑰ | **nurture_runner.sh 和 _send_remote 参数传递方式不同** | 本地传数组、远程传 shell 字符串,应统一 |
|
||||
| ⑱ | **远程结果回传路径不一致** | nurture 结果在 `/tmp/`,collect 结果在 `runtime/results/` |
|
||||
| ⑲ | **CMD_REGISTRY 从 dict 改为 dataclass** | 类型安全+IDE 补全 |
|
||||
| ⑳ | **`routes/ops.py` 改为 class-based router** | 更好的可维护性 |
|
||||
|
||||
---
|
||||
|
||||
## 三、信息采集专项优化
|
||||
|
||||
### 3.1 当前链路(治理后)
|
||||
|
||||
```
|
||||
前端 matrix-collect.js → POST /api/ops/run {type:'collect', accounts, params}
|
||||
→ CommandBus CMD_REGISTRY["collect"]
|
||||
→ auto_blueprint: 按账号平台自动选 douyin_read_profile / xiaohongshu_read_profile
|
||||
→ 按机器分组 → MachineSession 队列 → _send_local / _send_remote
|
||||
→ 远程执行 mc run --blueprints=xxx --rounds=1
|
||||
→ BatchEngine → LoginStateMachine → 原子操作 → 数据提取
|
||||
→ _save_profiles_json() → 写 profiles.json + homepage_info.json ✅
|
||||
```
|
||||
|
||||
### 3.2 已修复的问题
|
||||
|
||||
| 问题 | 修复 |
|
||||
|:-----|:------|
|
||||
| profiles.json 和 homepage_info.json 不同步 | ✅ `_save_profiles_json()` 同步写两个文件 |
|
||||
| 封号检测在采集流程内 | ✅ 登录层也检测封号,直接标记 banned |
|
||||
| 正则取数字为'?' | ✅ 小红书 e2e 兜底已加 |
|
||||
| 数据写入了但 Dashboard 不显示 | ✅ fleet_collector 缓存清除已做 |
|
||||
|
||||
### 3.3 信息采集的剩余优化
|
||||
|
||||
| 优化项 | 说明 | 优先级 |
|
||||
|:-------|:-----|:-------|
|
||||
| 采集进度实时反馈到 Dashboard | 目前是"提交后等完成",没有进度条 | P2 |
|
||||
| 多机采集结果去重 | 同一个 identity_dir 在多台机器都有数据时重复显示 | P2 |
|
||||
| 采集历史对比(上次 vs 本次) | 方便查看粉丝增长 | P3 |
|
||||
| homepage_info.json 数据与 ORACLE 账号映射对账 | 自动发现"有账号但未采集" | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 四、统一命令模板注册表(CMD_REGISTRY)最终设计
|
||||
|
||||
```python
|
||||
CMD_REGISTRY = {
|
||||
"nurture": {
|
||||
"template": "mc run --accounts={ids} --blueprints={blueprint} --rounds={rounds}",
|
||||
"defaults": {"blueprint": "douyin_daily", "rounds": 10},
|
||||
"runner": "nurture_runner.sh", # shell 包装器(本地用)
|
||||
"auto_blueprint": False,
|
||||
},
|
||||
"collect": {
|
||||
"template": "mc run --accounts={ids} --blueprints={blueprint} --rounds={rounds}",
|
||||
"defaults": {"rounds": 1},
|
||||
"auto_blueprint": True,
|
||||
"blueprint_map": {
|
||||
"douyin": "douyin_read_profile",
|
||||
"xiaohongshu": "xiaohongshu_read_profile",
|
||||
},
|
||||
},
|
||||
"login": {
|
||||
"template": "mc smart-login {ids}",
|
||||
"single_account": True,
|
||||
},
|
||||
"logout": {
|
||||
"template": "mc run --accounts={ids} --blueprints=douyin_daily --rounds=1",
|
||||
},
|
||||
"comment": {
|
||||
"template": "mc task comment --account={ids} --url={url}",
|
||||
"required_params": ["url"],
|
||||
},
|
||||
"like": {
|
||||
"template": "mc run --accounts={ids} --blueprints=douyin_daily --rounds=1",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**核心原则**:
|
||||
- ✅ 所有操作共用同一套模板渲染引擎
|
||||
- ✅ 新增操作只需在注册表加一行
|
||||
- ✅ `auto_blueprint` 让前端不用知道具体蓝图名
|
||||
- ✅ `required_params` 在 dispatch 时自动校验
|
||||
|
||||
---
|
||||
|
||||
## 五、实施路线图
|
||||
|
||||
### Phase 6: 统一后端执行路由(P1)
|
||||
|
||||
| # | 任务 | 文件 | 工作量 |
|
||||
|:-:|:-----|:-----|:-------|
|
||||
| 6.1 | 删除 `routes/matrix.py` 中 `/nurture/start` 绕过 CommandBus 的代码 | `routes/matrix.py` | 小 |
|
||||
| 6.2 | 删除 `/task/run` 绕过 CommandBus 的代码 | `routes/matrix.py` | 小 |
|
||||
| 6.3 | 确认所有前端视图已改用 `/api/ops/run` | 逐个审计 views/ | 中 |
|
||||
| 6.4 | 修复 accounts.js 单账号采集逐个发送 | `matrix-accounts.js` | 小 |
|
||||
|
||||
### Phase 7: 前端统一调用格式审计(P1)
|
||||
|
||||
| # | 任务 | 说明 |
|
||||
|:-:|:-----|:------|
|
||||
| 7.1 | 审计所有 views/ 中的 POST 调用,确认格式统一 | 逐个检查 |
|
||||
| 7.2 | 修复不合规的调用 | 同上 |
|
||||
| 7.3 | 增加 ESLint 规则或文档约束 | 后续 |
|
||||
|
||||
### Phase 8: 远程执行结果回传统一(P2)
|
||||
|
||||
| # | 任务 | 说明 |
|
||||
|:-:|:-----|:------|
|
||||
| 8.1 | 统一远程命令的结果文件路径 | 目前 `/tmp/` 和 `runtime/results/` 混用 |
|
||||
| 8.2 | 统一 poll 策略对远程命令的检查方式 | 目前本地和远程各一套逻辑 |
|
||||
|
||||
### Phase 9: 清理遗留代码(P2)
|
||||
|
||||
| # | 任务 | 文件 |
|
||||
|:-:|:-----|:------|
|
||||
| 9.1 | 移除 `platforms/` 目录(或移到 archive) | `platforms/` |
|
||||
| 9.2 | 修复 `agentos/plugins/matrix.py` 存档引用 | `agentos/plugins/matrix.py` |
|
||||
| 9.3 | 确认 `scripts/archive/` 无外部引用后移出 | `scripts/archive/` |
|
||||
| 9.4 | 删除 `routes/matrix.py` 中已废弃的 GET/POST 路由(需逐个确认) | `routes/matrix.py` |
|
||||
|
||||
---
|
||||
|
||||
## 六、治理后最终状态
|
||||
|
||||
```
|
||||
L5 前端 ── 统一 POST /api/ops/run {type, accounts, params}
|
||||
L4 路由 ── ops.py 唯一执行入口 | matrix.py 只读查询
|
||||
L3 总线 ── CMD_REGISTRY 注册表 | 统一模板渲染 | 自动按机器分组
|
||||
L2 引擎 ── BatchRunner | LoginStateMachine | 封号检测
|
||||
L1 操作 ── douyin_ops + xhs_ops | 三段式原子操作
|
||||
L0 浏览器 ── Camoufox | 登录态管理
|
||||
数据层 ── profiles.json + homepage_info.json 同步写入
|
||||
封号层 ── 登录检测 + 采集检测 双层判断
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、验证清单
|
||||
|
||||
- [ ] Phase 6: 无 POST 路由绕过 CommandBus
|
||||
- [ ] Phase 7: 所有前端 views POST 调用格式统一
|
||||
- [ ] Phase 8: 远程结果回传一致,Dashboard 能看到远程执行结果
|
||||
- [ ] Phase 9: 无 archive 脚本的外部引用
|
||||
@@ -0,0 +1,309 @@
|
||||
# AgentOS 队列管理与程序职责框架
|
||||
|
||||
> 版本: 1.0 | 日期: 2026-07-04
|
||||
> 目标: 说清楚"什么程序管什么"、"任务怎么流转"、"三台机器各自干什么"
|
||||
|
||||
---
|
||||
|
||||
## 一、程序总图:三台机器各自运行什么
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ Master(chengzigedeAir) │
|
||||
│ │
|
||||
│ ┌─ Dashboard ───────────────────────────────────────┐ │
|
||||
│ │ FastAPI :9988 │ │
|
||||
│ │ 职责: 接收用户请求、展示状态、调度分发 │ │
|
||||
│ │ 包含: routes/*.py (API层) │ │
|
||||
│ │ services/command_bus.py (调度层) │ │
|
||||
│ │ services/video_analyzer.py (视频分析) 🆕 │ │
|
||||
│ │ frontend/ (前端页面 47个视图) │ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ guardd :9090 ──────────────────────────────────────┐ │
|
||||
│ │ 16个模块 + 15秒调度循环 │ │
|
||||
│ │ 职责: 本地任务排队→执行、心跳上报 │ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ └── 也负责自己的3台账号的养号/评论/采集 ──┘ │
|
||||
└──────────────────────┬───────────────────────────────┘
|
||||
│ Tailscale
|
||||
┌──────────────────────────────────────────┐
|
||||
│ Worker(5kechengdeAir / 7kecheng) │
|
||||
│ │
|
||||
│ ┌─ guardd :9090 ─────────────────────────┐ │
|
||||
│ │ 只跑 guardd(无 Dashboard) │ │
|
||||
│ │ 职责: 收大包→拆小包→三队列→3 slot执行 │ │
|
||||
│ └────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ 账号: 5kecheng=12个, 7kecheng=大量的 │ │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**结论**: Dashboard 只在 Master 跑,Worker 只跑 guardd。
|
||||
|
||||
---
|
||||
|
||||
## 二、每个程序的具体职责
|
||||
|
||||
### 2.1 Dashboard(Master 专用)
|
||||
|
||||
| 模块 | 文件 | 职责 |
|
||||
|:-----|:------|:------|
|
||||
| **路由层** | `routes/ops.py` | 接收用户提交 → 调 CommandBus |
|
||||
| **命令分发** | `services/command_bus.py` | 拆解任务→按机器打包→调 guardd API |
|
||||
| **视频分析** | `services/video_analyzer.py` 🆕 | 浏览器提取标题→分类→选评论 |
|
||||
| **前端** | `frontend/src/views/*` | 47 个视图,用户操作入口 |
|
||||
|
||||
### 2.2 guardd 守护进程(每台机器都有)
|
||||
|
||||
| 模块 | 文件位置 | 职责 |
|
||||
|:-----|:---------|:------|
|
||||
| **HTTP 服务器** | `guardd.py` line 227-380 | 端口 9090,接收/响应所有 API 请求 |
|
||||
| **调度引擎** | `modules/scheduler.py` | **三队列管理 + 3 slot 流水线 + 账号互斥** |
|
||||
| **任务存储** | `modules/task_store.py` | 任务数据持久化(SQLite + 内存双写) |
|
||||
| **优先级队列** | `modules/priority_queue.py` | heapq 实现,支持按时间调度和取消 |
|
||||
| **槽位管理器** | `modules/slot_manager.py` | 3 slot 分配/释放,浏览器进程监控 |
|
||||
| **执行器** | `modules/executor.py` | 子进程执行 `mc run`,解析输出,超时控制 |
|
||||
| **心跳上报** | `modules/heartbeat.py` | 每15秒收集本地状态→推送给 Dashboard |
|
||||
| **计划同步** | `modules/schedule_bridge.py` | 每60秒检查 ORACLE 定时任务并提交 |
|
||||
| **账号监控** | `modules/account_monitor.py` | 实时检查 cookies.sqlite 登录态 |
|
||||
| **清理维护** | `guardd.py` line 1420-1450 | 9 模块循环每 300 秒执行 |
|
||||
|
||||
---
|
||||
|
||||
## 三、任务流转全路径:从用户提交到账号执行
|
||||
|
||||
### 3.1 场景:用户提交 20 个账号评论 1 个视频
|
||||
|
||||
```
|
||||
你 (Dashboard 浏览器)
|
||||
│ POST /api/ops/run {type:"smart_comment", accounts:[...20个], params:{urls:["https://..."]}}
|
||||
▼
|
||||
┌─ routes/ops.py line 36 ─────────────────────────────────────────────┐
|
||||
│ api_ops_run() │
|
||||
│ 数据校验 → CommandBus.dispatch("smart_comment", accounts, params) │
|
||||
└───────────────────────────┬──────────────────────────────────────────┘
|
||||
▼
|
||||
┌─ services/command_bus.py line 908 ──────────────────────────────────┐
|
||||
│ CommandBus.dispatch() │
|
||||
│ │
|
||||
│ STEP 1: 加载 ORACLE.yaml → 按机器分组 │
|
||||
│ 7kecheng → [12个账号] │
|
||||
│ 5kechengdeAir → [8个账号] │
|
||||
│ │
|
||||
│ STEP 2: smart_comment 分支 (line 1007) │
|
||||
│ ├─ 新建 VideoAnalyzer → asyncio.run(analyze_batch(urls)) │
|
||||
│ │ └─ 无头浏览器打开视频 → 提取标题/描述 │
|
||||
│ │ └─ 关键词匹配 → 行业分类 (health/general) │
|
||||
│ │ └─ 从行业池或万能池选评论 │
|
||||
│ │ └─ 返回 {url: {title, industry, comment}} │
|
||||
│ │ │
|
||||
│ └─ 拆解: 每个账号×每个URL = 最小单元 │
|
||||
│ ├─ {douyin_133, comment, "医生讲得很清楚", P0, 7kecheng} │
|
||||
│ ├─ {douyin_134, comment, "医生讲得很清楚", P0, 7kecheng} │
|
||||
│ └─ ... × 20 │
|
||||
│ │
|
||||
│ STEP 3: 按机器打包 → MachineSession.send() │
|
||||
│ ├─ POST http://100.65.35.28:9090/scheduler/submit (12个P0任务) │
|
||||
│ └─ POST http://100.72.182.121:9090/scheduler/submit (8个P0任务) │
|
||||
└───────────────────────────┬──────────────────────────────────────────┘
|
||||
▼
|
||||
┌─ guardd HTTP :9090 (Worker机器) ──────────────────────────────────┐
|
||||
│ do_POST /scheduler/submit │
|
||||
│ → api_scheduler_submit() → _init_scheduler() → scheduler.submit() │
|
||||
│ │
|
||||
│ submit_task(): │
|
||||
│ ├─ 账号互斥检查(第1层)→ 同一账号不可同时入队 │
|
||||
│ ├─ 根据 priority 入对应队列: │
|
||||
│ │ P0=0 → queue_priority (优先队列) │
|
||||
│ │ P1=1 → queue_normal (日常队列) │
|
||||
│ │ P2=2 → queue_filler (劣后队列) │
|
||||
│ └─ 有空闲 slot → 立即分配 │
|
||||
└───────────────────────────┬──────────────────────────────────────────┘
|
||||
▼
|
||||
┌─ scheduler.run_cycle() 每15秒 ─────────────────────────────────────┐
|
||||
│ │
|
||||
│ ① _check_all_active_tasks(): │
|
||||
│ ├─ slot0: [P1养号 douyin_133] → 还在跑?→ 检查超时 │
|
||||
│ ├─ slot1: [P1养号 douyin_134] → 已完成!→ _release_slot() │
|
||||
│ │ └─ 释放 account_slots["douyin_134"] │
|
||||
│ │ └─ 检查 paused_tasks: 有P0等这个slot? → 推入 queue_priority │
|
||||
│ └─ slot2: [P2采集 douyin_135] → 还在跑 │
|
||||
│ │
|
||||
│ ② _schedule_all_slots(): │
|
||||
│ ├─ slot0: 忙 → 跳过 │
|
||||
│ ├─ slot1: 空闲 → _pop_by_priority() │
|
||||
│ │ ├─ queue_priority pop → 取出 {douyin_134, comment} ← P0 │
|
||||
│ │ └─ _assign_task() + account_slots["douyin_134"] = slot1 │
|
||||
│ └─ slot2: 忙 → 跳过 │
|
||||
│ │
|
||||
│ ③ slot_manager.check_health(): 监控浏览器进程 │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 关键:每台机器的 guardd 独立管理自己的队列
|
||||
|
||||
```
|
||||
7kecheng 的 guardd:
|
||||
queue_priority: [P0评论×4, P0评论×3] ← 智能评论待执行
|
||||
queue_normal: [P1养号×22] ← 日常养号排队
|
||||
queue_filler: [P2采集×8] ← 采集任务有空才做
|
||||
---------------
|
||||
slot0: → [P1养号 douyin_133 → P0评论 douyin_183 → 恢复P1 douyin_143]
|
||||
slot1: → [P1养号 douyin_134 → P0评论 douyin_184 → 恢复P1 douyin_144]
|
||||
slot2: → [P2采集 douyin_135 → ...]
|
||||
---------------
|
||||
account_slots: {"douyin_133":0, "douyin_134":1, "douyin_135":2}
|
||||
|
||||
5kechengdeAir 的 guardd:
|
||||
queue_priority: [P0评论×2]
|
||||
queue_normal: [P1养号×15]
|
||||
queue_filler: []
|
||||
---------------
|
||||
slot0: → [P1养号 douyin_01 → P0评论 douyin_02 → 恢复P1 douyin_03]
|
||||
slot1: → [空闲]
|
||||
slot2: → [空闲]
|
||||
---------------
|
||||
account_slots: {"douyin_01":0}
|
||||
```
|
||||
|
||||
**两台机器互不干扰** — 各自管各自的队列和 slot。
|
||||
|
||||
---
|
||||
|
||||
## 四、谁管队列
|
||||
|
||||
### 4.1 一句话回答
|
||||
|
||||
| 程序 | 管什么 |
|
||||
|:-----|:--------|
|
||||
| **CommandBus**(Master) | 把大任务拆成最小单元 → 按机器打包 → 分发到各机 guardd |
|
||||
| **guardd scheduler**(每台机器) | 收到包后 → 自己管理三队列 → 分配 3 slot 执行 → 账号互斥 |
|
||||
| **guardd heartbeat**(每台机器) | 只管 **上报状态** 给 Dashboard — **不参与队列管理** |
|
||||
|
||||
### 4.2 详细
|
||||
|
||||
```
|
||||
大任务(20个账号评论1个视频)
|
||||
│
|
||||
▼ CommandBus(Dashboard 进程)
|
||||
拆成 20 个小单元
|
||||
按机器分成 2 个包: 7kecheng=12个, 5kecheng=8个
|
||||
│
|
||||
├──→ 7kecheng guardd:
|
||||
│ 收到12个P0任务 → 入 queue_priority
|
||||
│ scheduler: 从queue取 → 分到3个slot → 执行
|
||||
│
|
||||
└──→ 5kechengdeAir guardd:
|
||||
收到8个P0任务 → 入 queue_priority
|
||||
scheduler: 从queue取 → 分到3个slot → 执行
|
||||
```
|
||||
|
||||
**heartbeat 只做状态上报,不干涉队列。**
|
||||
|
||||
---
|
||||
|
||||
## 五、三队列详细逻辑
|
||||
|
||||
### 5.1 队列类型
|
||||
|
||||
| 队列 | 变量名 | 优先级 | 谁来入队 | 何时执行 | 可被抢占 |
|
||||
|:-----|:--------|:-------|:---------|:---------|:---------|
|
||||
| P0 优先 | `queue_priority` | 最高 | smart_comment / 定向操作 | 有空闲 slot 立即执行 | ❌(它抢别人) |
|
||||
| P1 日常 | `queue_normal` | 中 | 养号定时任务 / 日常操作 | P0 都执行完才取 | ✅ 被 P0 打断 |
|
||||
| P2 劣后 | `queue_filler` | 低 | 批量采集 / 后台同步 | 只有 P0/P1 都空时才做 | ✅ 被 P0/P1 抢占 |
|
||||
|
||||
### 5.2 分配算法(`_pop_by_priority`)
|
||||
|
||||
```
|
||||
每次 slot 空闲:
|
||||
① 先看 queue_priority → 有 P0 → 取出来执行
|
||||
② queue_priority 空 → 看 queue_normal → 有 P1 → 取出来执行
|
||||
③ queue_normal 也空 → 看 queue_filler → 有 P2 → 取出来执行
|
||||
|
||||
每一步都跳过 busy 账号:
|
||||
如果任务的账号在 account_slots 表中 → 跳过不取
|
||||
```
|
||||
|
||||
### 5.3 P0 抢占(`insert_priority`)
|
||||
|
||||
```
|
||||
收到 P0 任务 → 检查账号:
|
||||
├─ 账号空闲 → 直接入 queue_priority
|
||||
└─ 账号忙碌 → 挂到该 slot 的 paused_slots 列表
|
||||
slot0: [▶️P1养号 douyin_133] → paused_slots[0] = [P0评论]
|
||||
↓ 养号完成
|
||||
_release_slot(0) → 检测到 paused_slots[0] 有 P0
|
||||
→ P0 入 queue_priority → slot0 立即分配
|
||||
↓ P0 执行完
|
||||
→ 恢复被中断的 P1 队列
|
||||
```
|
||||
|
||||
### 5.4 账号互斥表(`account_slots`)
|
||||
|
||||
```
|
||||
account_slots = {
|
||||
"douyin_133": 0, # douyin_133 在 slot0 运行
|
||||
"douyin_134": 1, # douyin_134 在 slot1 运行
|
||||
}
|
||||
|
||||
三层防护:
|
||||
第1层: submit_task() 入队时 → 检查 account_slots
|
||||
第2层: _pop_by_priority() 分配时 → 跳过 busy 账号
|
||||
第3层: slot_manager 执行前 → 浏览器级别拦截
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、与旧的 9 模块心跳循环的关系
|
||||
|
||||
### 6.1 各自独立运行
|
||||
|
||||
```
|
||||
guardd 进程:
|
||||
┌─ 主线程: HTTP 服务器 :9090
|
||||
├─ 调度线程: scheduler.run_cycle() 每15秒
|
||||
└─ 原文线程: _run_heartbeat_cycle() 每300秒
|
||||
包含 9 个模块:
|
||||
1. module_heartbeat_collect
|
||||
2. module_account_cleanup
|
||||
3. module_login_check
|
||||
4. module_results_cleanup
|
||||
5. module_browser_cleanup
|
||||
6. module_knowledge_sync ← 知识库同步
|
||||
7. module_cleanup_ops ← 命令清理
|
||||
8. module_dashboard_sync ← 看板同步
|
||||
9. module_sync_checker ← 同步检查
|
||||
```
|
||||
|
||||
**心跳只做辅助工作,不参与调度。** 调度由 `scheduler.run_cycle()` 独立完成。
|
||||
|
||||
---
|
||||
|
||||
## 七、现有技能体系与本次改造的关系
|
||||
|
||||
### 7.1 已归档技能(设计文档,无代码)
|
||||
|
||||
| 技能 | 内容 | 与本次改造的关系 |
|
||||
|:-----|:------|:----------------|
|
||||
| `web_crawler` | Scrapling + Crawl4AI 爬虫设计 | 实际代码未实现,但 Scrapling 已安装 ✅,可用来增强视频信息提取 |
|
||||
| `content_processor` | 视频/文章/音频采集设计 | 设计框架可参考,无代码 |
|
||||
| `auto_collector` | 24小时自动监控设计 | 设计框架可参考,无代码 |
|
||||
|
||||
### 7.2 可利用的已安装包
|
||||
|
||||
| 包名 | 已安装 | 可用来做什么 |
|
||||
|:-----|:-------|:------------|
|
||||
| **scrapling** 0.2.99 | ✅ | HTTP 静态页面抓取(比启动浏览器快) |
|
||||
| **crawl4ai** | ✅ | LLM 友好的页面内容提取 |
|
||||
| **cloakbrowser** | ✅ | 高反爬场景(https://www.douyin.com 动态内容) |
|
||||
| **playwright** | ✅ | 浏览器自动化(当前 VideoAnalyzer 使用) |
|
||||
|
||||
### 7.3 可做的增强(不阻塞)
|
||||
|
||||
| 增强点 | 当前做法 | 可优化为 | 优先级 |
|
||||
|:-------|:---------|:---------|:------|
|
||||
| 视频标题提取 | 启动无头 Playwright | 先用 Scrapling HTTP 请求 meta tag,失败再降级浏览器 | 可优化 |
|
||||
| 热门评论分析 | 未实现 | 爬虫获取视频页面的 top 评论,分析情感和话题 | 后续 |
|
||||
| AI 生成评论 | 模板关键词匹配 | 上下文传到本地 oMLX 模型生成个性化评论 | 后续 |
|
||||
@@ -0,0 +1,193 @@
|
||||
# 写实感指南(去 AI 感 · 自拍 Vlog)
|
||||
|
||||
> 2026-10-03 建立 · 来源:外部方法论学习(`cclank/lanshu-awesome-ai-video-kit` 21 篇方法论 + `smixs/visual-skills`)
|
||||
> 用途:调提示词、改导演规则、做拍法预设时的**对照规范**
|
||||
|
||||
---
|
||||
|
||||
## 一、三条最容易踩的坑(我们已实测踩中)
|
||||
|
||||
### 坑 1:图生视频却重描述视觉 ✗✗✗
|
||||
|
||||
**可灵官方守则**:图生视频时"**只描述运动,不重描述视觉**"——Kling 会重画图中已有内容,
|
||||
你再描述一遍 = 给它两套冲突指令 → 画面被"重画" → AI 感。
|
||||
|
||||
```
|
||||
❌ A red sports car with chrome wheels on a wet road... the car starts moving
|
||||
✅ The headlights blaze on and the engine roars to life.
|
||||
The rear tires spin, spraying water across the wet asphalt.
|
||||
```
|
||||
|
||||
**判定**:镜头有参考图(`image_path` 存在)→ 提示词应**只含动作演化**。
|
||||
|
||||
### 坑 2:矛盾约束(写了等于没写)
|
||||
|
||||
| ❌ 矛盾组合 | 原因 |
|
||||
|---|---|
|
||||
| `胶片感 / film grain` + `4K超清 / ultra sharp` | 胶片感本身是模糊+颗粒 |
|
||||
| **`电影感` + `纪实手持` 都强写** | 风格相互拉扯(**我们踩过**) |
|
||||
| `慢动作` + `高速动作` | 速度矛盾 |
|
||||
| 同时指定多个艺术家风格(>2) | 模型随机取一个 |
|
||||
| **`画面稳定` + `手持晃动`** | 稳定=三脚架语言(**我们踩过**) |
|
||||
|
||||
### 坑 3:抽象情绪词
|
||||
|
||||
```
|
||||
❌ 【情绪目标】紧张 / 好奇 / 悲伤
|
||||
✅ 手指无意识地攥紧衣角,眼神闪躲,呼吸急促
|
||||
```
|
||||
|
||||
**原则**:视频模型看不懂抽象形容词,**必须外化为身体细节**;每镜只写 1-2 个关键动作(多了稀释焦点)。
|
||||
|
||||
---
|
||||
|
||||
## 二、写实人像 5 段公式(Dan Kieft / 5M+ 播放教学)
|
||||
|
||||
```
|
||||
① Subject 谁 —— 年龄/种族/妆/服装(具体,不堆形容词)
|
||||
② Pose 姿态 —— candid shot / 坐着 / 侧看 / 微笑
|
||||
③ Camera ★ 相机 —— Fujifilm X100V · 35mm · 景深 · bokeh ← 杀手锏
|
||||
④ Skin ★ 皮肤 —— 真实纹理 · 自然瑕疵 · 不过度磨皮 · 毛孔可见
|
||||
⑤ Aesthetic 调性 —— Instagram 风 · 暖调 · 自然光 · 城市背景
|
||||
```
|
||||
|
||||
**完整示例(原文)**:
|
||||
```
|
||||
Beautiful 20-year-old East Asian woman, minimalist makeup, wearing beige streetwear
|
||||
jacket, candid moment sitting at a cafe table, looking sideways with soft smile.
|
||||
Shot on Fujifilm X100V, 35mm film, realistic lighting, natural skin texture,
|
||||
unfiltered, pores visible, soft background bokeh, Instagram aesthetic,
|
||||
professional urban street photography, warm tones.
|
||||
```
|
||||
|
||||
**要点**:
|
||||
- **相机型号是杀手锏** —— 触发模型的"真实摄影"先验(`Fujifilm X100V` / `Leica Q3` / `iPhone 前置`)
|
||||
- **`unfiltered` + `pores visible`** 是反 AI 塑料感的直接解药
|
||||
- `Same woman` / 角色名重复 → 锚定同一人物(跨场景一致性)
|
||||
|
||||
---
|
||||
|
||||
## 三、情绪外化表(10 种,可直接抄)
|
||||
|
||||
| 抽象情绪 | 外化为动作与细节 |
|
||||
|---|---|
|
||||
| 悲伤 | 低头、肩膀微微颤抖、眼眶泛红、手指无意识攥紧衣角、泪水打转却没落下 |
|
||||
| 喜悦 | 嘴角抑制不住上扬、眉眼舒展、脚步轻快、哼小曲、忍不住原地转圈 |
|
||||
| 紧张/焦虑 | 频繁看表、手指敲桌面、呼吸急促、眼神闪躲、无意识啃指甲 |
|
||||
| 愤怒 | 双拳紧握、下颌线紧绷、胸口起伏、眼神锐利、从牙缝挤话 |
|
||||
| 释然 | 长舒一口气、肩膀放松、淡淡微笑、抬头望向远方 |
|
||||
| 恐惧 | 瞳孔放大、后退半步、抓住身边物体、屏息、嘴唇发抖 |
|
||||
| 疲惫 | 揉太阳穴、靠墙、眼皮下沉、长呼气、动作迟缓 |
|
||||
| 专注 | 眉头微皱、眼神锁定一点、嘴唇抿紧、身体前倾、手稳定不动 |
|
||||
| 犹豫 | 张嘴又闭上、视线游移、手悬在半空、踱步、欲言又止 |
|
||||
| 惊喜 | 眼睛瞬间睁大、嘴巴张开成 O 形、双手捂嘴、向前一步、笑容缓缓绽放 |
|
||||
|
||||
**写法对照**:
|
||||
```
|
||||
❌ 她终于轻松下来了。
|
||||
✅ 她长长地舒了一口气,紧绷的肩膀完全放松下来,脸上浮起淡淡的微笑,抬头望向远方。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、特殊字符规范(结构化标注)
|
||||
|
||||
| 信息类型 | 符号 | 示例 |
|
||||
|---|---|---|
|
||||
| 音乐 | `( )` | `(背景播放着舒缓的爵士钢琴)` |
|
||||
| 音效 | `< >` | `<远处传来狗叫声>` |
|
||||
| 台词 | `{ }` | `她轻声说{好久不见}` |
|
||||
| 字幕 | `【 】` | `【第二章:重逢】` |
|
||||
|
||||
**语言规范**:台词语言统一,外语需标注语种 → `用日语说道{こんにちは}`
|
||||
|
||||
> ⚠️ 这是给**支持音频生成的模型**用的(Seedance 2.5 等)。我们当前是"先出画面再配音",
|
||||
> 此规范可用于**分镜脚本阶段的标注**,便于后续 TTS 分段与音效铺底。
|
||||
|
||||
---
|
||||
|
||||
## 五、约束词三件套(护栏)
|
||||
|
||||
**必加基础**:`不要水印` · `不要 Logo` · `不要字幕`
|
||||
|
||||
**画面稳定**:`人物面部稳定不变形` · `动作连贯自然不僵硬` · `无穿模无卡顿无闪烁`
|
||||
|
||||
**主体一致性(防"双胞胎")**:
|
||||
```
|
||||
视频全程禁止出现外形、着装、配饰完全一致的人物
|
||||
禁止生成同款分身、双胞胎效果
|
||||
同一画面中仅保留单个对应人物,不出现人物重复复刻
|
||||
```
|
||||
|
||||
**镜头**:`镜头平稳` / `固定机位` / `避免突然变焦`(**注意与手持风格二选一**)
|
||||
|
||||
---
|
||||
|
||||
## 六、可灵专属守则(我们用可灵,重点)
|
||||
|
||||
1. **中文理解业界最强** → **推荐纯中文提示词**(避免中英混用)
|
||||
2. **图生视频极强** → 有参考图时**只写动作**(见坑 1)
|
||||
3. **用 active verbs**:`rockets upward` / `slams into` / `erupts`(不是 `moves`/`goes`)
|
||||
4. **写时序流**:`抬起刀 → 一刀劈下 → 刀锋反光 → 竹子滑落`(箭头 = 时间节点)
|
||||
5. **用具体光源**代替笼统词:`闪烁的日光灯管` / `霓虹灯` / `烛光` / `黄金时刻`
|
||||
(❌ `dramatic lighting` / `自然光,光源有画面依据`)
|
||||
6. **加触感细节**(tactile details)
|
||||
7. **原生支持音画同步 + 角色定向发声**("角色A说X,角色B说Y")—— ⚠️ 我们尚未使用
|
||||
8. 时长:15s(智能分镜可达 2 分钟)—— 我们目前限制 5/10s,可放宽
|
||||
|
||||
---
|
||||
|
||||
## 七、自拍 Vlog 专项包(核心诉求)
|
||||
|
||||
自拍 vlog 的"真",靠这 5 层同时成立:
|
||||
|
||||
**① 设备锚点**
|
||||
```
|
||||
iPhone 15 Pro 前置摄像头,竖屏 9:16,近距离广角
|
||||
轻微桶形畸变(前置镜头的特征)
|
||||
```
|
||||
|
||||
**② 手持特征**(⚠️ 不能同时写"画面稳定")
|
||||
```
|
||||
手持自拍(手臂长度)、轻微呼吸起伏、偶尔微调构图
|
||||
```
|
||||
|
||||
**③ 生活光**(真实光源 > 形容词)
|
||||
```
|
||||
窗光从左侧打在脸上、室内顶灯偏暖、手机屏幕的光在镜片上有反光
|
||||
背景比人脸暗一档(室外过曝的窗户)
|
||||
```
|
||||
|
||||
**④ 微瑕疵**(AI 最不会自发生成的东西)
|
||||
```
|
||||
对焦偶尔漂移、曝光随移动变化、轻微噪点、头发有几缕没梳顺
|
||||
说话时自然眨眼、吞咽、鼻翼微动、视线偶尔离开镜头
|
||||
```
|
||||
|
||||
**⑤ 声音层**
|
||||
```
|
||||
房间混响、远处车流、衣服摩擦声、说话时的换气声
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、落地清单(改系统时对照)
|
||||
|
||||
| 位置 | 改什么 |
|
||||
|---|---|
|
||||
| `composer/pipeline.py: build_shot_prompt` | 图生视频分支**删视觉重描述**;加写实锚点包(相机型号/皮肤/反塑料感) |
|
||||
| 同上 | **矛盾自检**:`稳定 vs 手持`、`电影感 vs 纪实` 等成对冲突检测 |
|
||||
| `directors/*.py` | 情绪**必须外化**(内建情绪外化表);光源必须具体 |
|
||||
| 拍法预设 | 新增 📱 **自拍 Vlog**(一键带全 5 层锚点) |
|
||||
| 全局 | 每镜自动附加约束词三件套 |
|
||||
| 可选 | 试可灵原生音画同步(角色定向发声)替代"事后配音" |
|
||||
|
||||
---
|
||||
|
||||
## 附:资料存档位置
|
||||
|
||||
- 抓取的 7 篇方法论原文:`/tmp/aivideo_kb/`(临时,重启会清)
|
||||
- `04-情绪外化表.md` · `06-约束词清单.md` · `07-特殊字符规范.md`
|
||||
- `08-避坑12问.md` · `09-kling-公式.md` · `20-realistic-character-consistency.md`
|
||||
- `02-进阶公式.md` · `smixs-README.md`
|
||||
- 上游仓库:`cclank/lanshu-awesome-ai-video-kit`(411 prompts / 21 篇方法论)
|
||||
@@ -0,0 +1,241 @@
|
||||
# 改造分析报告:现状 vs 目标架构
|
||||
|
||||
> 日期: 2026-07-04 | 基于 `PLANS/TASK_ORCHESTRATION_ARCHITECTURE.md`
|
||||
> 审计范围: 全部 7 个模块,逐项检查
|
||||
|
||||
---
|
||||
|
||||
## 一、改造项总览
|
||||
|
||||
| # | 模块 | 改造类型 | 优先级 |
|
||||
|:-:|:-----|:---------|:-------|
|
||||
| 1 | `scheduler.py` | 🔧 **重写** — 现有逻辑不满足需求 | P0 |
|
||||
| 2 | `priority_queue.py` | ✅ **不动** — 现有类直接可用 | - |
|
||||
| 3 | `command_bus.py` | 🆕 **新增** smart_comment 类型 | P1 |
|
||||
| 4 | `video_analyzer.py` | 🆕 **新建** — 不存在 | P1 |
|
||||
| 5 | `corpus.py` | 🔧 **改造** — 加行业过滤 + 万能兜底 | P1 |
|
||||
| 6 | `douyin.yaml` | 🔧 **重构** — 语料分层 | P1 |
|
||||
| 7 | `profiles.json` | 🔧 **补字段** — 加 industry | P2 |
|
||||
| 8 | `ops-command.js` | 🆕 **加功能** — 三队列显示 | P3 |
|
||||
|
||||
---
|
||||
|
||||
## 二、逐项分析
|
||||
|
||||
---
|
||||
|
||||
### 改造项 1:`scheduler.py` — 🔧 重写
|
||||
|
||||
**当前代码**(`guardd/modules/scheduler.py:33-362`):
|
||||
|
||||
当前是单队列模式:
|
||||
```python
|
||||
class Scheduler:
|
||||
def __init__(self):
|
||||
self.queue = PriorityQueue() # ← 一个队列装所有优先级
|
||||
self.active_tasks: dict[int, dict] # {slot_id: task}
|
||||
self.paused_tasks: dict[int, dict]
|
||||
```
|
||||
|
||||
| 功能点 | 现状 | 目标 | 问题 |
|
||||
|:-------|:-----|:-----|:-----|
|
||||
| 队列数量 | **1 个** 混装所有优先级 | **3 个** 独立队列(P0/P1/P2) | ❌ P0不能插队,P2不能填空 |
|
||||
| `_pop_next_task()` | 遍历所有任务,按`(priority, scheduled_at)`排序后取第一个 | 先看P0→再看P1→再看P2,且跳过 busy 账号 | ❌ 无法实现优先级隔离 |
|
||||
| 账号互斥 | slot_manager.find_account() 在分配时检查 | 三层检查:入队时+分配时+执行前 | ❌ 入队层不检查,可能重复入队 |
|
||||
| 账号状态表 | 无 | `account_slots: dict[str, int]` | ❌ 没有快速查询账号状态的能力 |
|
||||
| P0 抢占 | 无 | 当前任务结束后插队 | ❌ 完全未实现 |
|
||||
| P2 劣后 | 无 | 只在空闲时执行,可被抢占 | ❌ 完全未实现 |
|
||||
| 暂停任务暂存 | `paused_tasks` 存在但不被 active 使用 | P0插入时暂停P1,完成后恢复 | ❌ 逻辑不完整 |
|
||||
|
||||
**改造原因**:当前逻辑是**功能错误的**。三个优先级的任务混在一个队列里,虽然排序时按 priority 字段,但 `_pop_next_task` 取完第一个任务后就 break 了,不会继续往后看。当高优任务 due 时间还没到时(`scheduled_at > now`),堆顶返回 None,整个调度循环就停了。这导致 P0 任务无法真正插队。
|
||||
|
||||
**改动量**:~200行,重写 `Scheduler` 类。
|
||||
|
||||
---
|
||||
|
||||
### 改造项 2:`priority_queue.py` — ✅ 不动
|
||||
|
||||
**当前代码**(`guardd/modules/priority_queue.py:1-79`):
|
||||
|
||||
```python
|
||||
class PriorityQueue:
|
||||
"""基于 heapq 实现,支持优先级排序 + 时间调度 + 取消/重排"""
|
||||
```
|
||||
|
||||
当前实现完全满足需求。三队列只需创建三个独立实例:
|
||||
```python
|
||||
self.queue_priority = PriorityQueue() # P0
|
||||
self.queue_normal = PriorityQueue() # P1
|
||||
self.queue_filler = PriorityQueue() # P2
|
||||
```
|
||||
|
||||
无需修改此类。
|
||||
|
||||
---
|
||||
|
||||
### 改造项 3:`command_bus.py` — 🆕 新增 smart_comment
|
||||
|
||||
**当前代码**(`services/command_bus.py:807-842`):
|
||||
|
||||
```python
|
||||
CMD_REGISTRY = {
|
||||
"nurture": {...},
|
||||
"collect": {...},
|
||||
"login": {...},
|
||||
"logout": {...},
|
||||
"comment": {...},
|
||||
"like": {...},
|
||||
"interact": {...},
|
||||
"record": {...},
|
||||
}
|
||||
```
|
||||
|
||||
| 功能点 | 现状 | 目标 | 问题 |
|
||||
|:-------|:-----|:-----|:-----|
|
||||
| 评论类型 | `comment` / `interact` — 直接传 `mc task comment` | + `smart_comment` — 先分析视频再评论 | ❌ 缺少视频分析环节 |
|
||||
| 分发逻辑 | 按机器分组后直接发到 guardd | 先调 VideoAnalyzer 分析所有URL,再分组分发 | ❌ 无分析环节 |
|
||||
|
||||
**改造原因**:**新功能需求**。现有 comment/interact 可以保留不变,新增 smart_comment 走新的视频分析流程。
|
||||
|
||||
**改动量**:~20行,加一条注册表 + dispatch 分支。
|
||||
|
||||
---
|
||||
|
||||
### 改造项 4:`video_analyzer.py` — 🆕 新建
|
||||
|
||||
**当前**:文件不存在。
|
||||
|
||||
**需要新建**一个完整的视频分析模块,包含:
|
||||
- 浏览器打开 URL 提取标题/描述
|
||||
- 关键词匹配行业分类
|
||||
- 根据账号 industry 选评论
|
||||
|
||||
**改造原因**:**完全是新增功能**,原来是直接传评论或者随机取语料,现在需要先分析视频内容再做匹配。
|
||||
|
||||
**改动量**:~150行新文件。
|
||||
|
||||
---
|
||||
|
||||
### 改造项 5:`corpus.py` — 🔧 改造
|
||||
|
||||
**当前代码**(`scripts/mc/corpus.py:51-57`):
|
||||
|
||||
```python
|
||||
KEYWORD_CATEGORY_MAP = [
|
||||
(["科技", "数码", "手机"], ["称赞", "提问"]),
|
||||
(["美食", "做饭", "菜"], ["称赞", "共鸣"]),
|
||||
(["旅游", "风景", "旅行"], ["称赞", "提问"]),
|
||||
(["情感", "生活", "感悟"], ["共鸣", "安慰"]),
|
||||
(["知识", "科普", "教育"], ["提问", "补充"]),
|
||||
]
|
||||
```
|
||||
|
||||
| 功能点 | 现状 | 目标 | 问题 |
|
||||
|:-------|:-----|:-----|:-----|
|
||||
| 关键词覆盖 | **5组**(科技/美食/旅游/情感/知识) | **9+组**(加上医疗/财经/育儿/汽车等) | ❌ 无医疗关键词,健康类视频无法匹配 |
|
||||
| 行业过滤 | 无 | 根据账号 industry 过滤语料 | ❌ 医疗账号可能发科技评论 |
|
||||
| 万能兜底 | `_get_random_comment()` 全域随机 | 从万能池(称赞/提问/共鸣)取 | ❌ 没有万能池概念 |
|
||||
| 分类→方向映射 | `DIRECTION_TO_CATEGORY` 5个 | 同步扩展 | ❌ 需要对齐 |
|
||||
|
||||
**改造原因**:**现有功能不完整**。关键词覆盖太窄,缺少行业过滤机制和万能兜底逻辑。
|
||||
|
||||
**改动量**:~50行,改 `KEYWORD_CATEGORY_MAP` + `get_comment_for_video()`。
|
||||
|
||||
---
|
||||
|
||||
### 改造项 6:`douyin.yaml` — 🔧 重构
|
||||
|
||||
**当前结构**(`corpus/douyin.yaml:239行`):
|
||||
|
||||
```
|
||||
categories:
|
||||
赞美: (30条,通用)
|
||||
共鸣: (15条,通用)
|
||||
提问: (15条,通用)
|
||||
感慨: (15条,通用)
|
||||
客观: (10条,通用)
|
||||
补充: (5条,通用)
|
||||
```
|
||||
|
||||
| 功能点 | 现状 | 目标 | 问题 |
|
||||
|:-------|:-----|:-----|:-----|
|
||||
| 语料分层 | **平铺**,都在同一层 | **两层**:万能池 + 行业池 | ❌ 无法区分行业 |
|
||||
| accessible 字段 | 无 | `accessible: "*"` 或 `accessible: ["health"]` | ❌ 无法限制账号使用 |
|
||||
| match_tags 字段 | 无 | 每个行业池带关键词标签 | ❌ 无法自动匹配视频 |
|
||||
|
||||
**改造原因**:**结构设计不满足新需求**。需要按行业分层,加 accessible 和 match_tags 字段。
|
||||
|
||||
**改动量**:YAML 结构调整,将现有评论分类到"万能称赞""万能提问""万能共鸣"下,新增"大健康称赞"等行业池。
|
||||
|
||||
---
|
||||
|
||||
### 改造项 7:`profiles.json` — 🔧 补字段
|
||||
|
||||
**当前**(`profiles.json:344行`):
|
||||
|
||||
```json
|
||||
{
|
||||
"douyin_133": {"nickname":"苏州胃肠体检敏敏", ...},
|
||||
"douyin_test": {"nickname":"小美养生茶", ...},
|
||||
}
|
||||
```
|
||||
|
||||
没有一个账号有 `industry` 字段。
|
||||
|
||||
**改造原因**:**缺少关键数据**。没有 industry 字段,VideoAnalyzer 无法判断账号该用哪个语料池。
|
||||
|
||||
**改动量**:每个账号加一行 `"industry": "health"` 或 `"industry": "general"`,手动配置。
|
||||
|
||||
---
|
||||
|
||||
### 改造项 8:`ops-command.js` — 🆕 加功能
|
||||
|
||||
**当前代码**:
|
||||
|
||||
前端已有 P0/P1/P2 的 HTML 筛选 checkbox(第41-43行),但后台 scheduler 返回的队列数据中优先级是混在一起的,前端无法真正按优先级分类展示。
|
||||
|
||||
**改造原因**:**新功能需求**。后台改为三队列后,前端需要分开显示三个队列的长度+内容。
|
||||
|
||||
**改动量**:~80行,加三个队列的独立展示区域。
|
||||
|
||||
---
|
||||
|
||||
## 三、改造原因分类
|
||||
|
||||
| 类别 | 数量 | 项 |
|
||||
|:-----|:-----|:----|
|
||||
| ❌ **功能错误**(现有逻辑有问题) | 1 | scheduler.py — 单队列导致P0/P2无法正常工作 |
|
||||
| ⚠️ **功能不完整**(有但不够) | 2 | corpus.py 关键词覆盖窄、douyin.yaml 无行业过滤 |
|
||||
| 🆕 **新功能需求**(完全新增) | 4 | video_analyzer.py、command_bus smart_comment、profiles.json industry、ops-command三队列 |
|
||||
| ✅ **无需修改** | 1 | priority_queue.py |
|
||||
|
||||
---
|
||||
|
||||
## 四、按 Phase 的改造详细清单
|
||||
|
||||
### Phase 1:队列改造(P0)
|
||||
|
||||
| 文件 | 当前行数 | 改动 | 原因 |
|
||||
|:-----|:---------|:------|:------|
|
||||
| `guardd/modules/scheduler.py` | 362行 | 重写:单队列→三队列 + 账号互斥表 + P0抢插 + P2填空 | ❌ 功能错误,当前单队列无法实现优先级隔离 |
|
||||
|
||||
### Phase 2:语料重组(P1)
|
||||
|
||||
| 文件 | 当前行数 | 改动 | 原因 |
|
||||
|:-----|:---------|:------|:------|
|
||||
| `corpus/douyin.yaml` | 239行 | 重构为万能池+行业池 | 🆕 新需求,需要按行业分层 |
|
||||
| `scripts/mc/corpus.py` | 701行 | 扩展关键词 + 加行业过滤 + 万能兜底 | ⚠️ 关键词覆盖窄,缺少过滤 |
|
||||
| `profiles.json` | 344行 | 各账号加 industry 字段 | 🆕 新需求,需要标记账号行业 |
|
||||
|
||||
### Phase 3:视频分析(P1)
|
||||
|
||||
| 文件 | 当前行数 | 改动 | 原因 |
|
||||
|:-----|:---------|:------|:------|
|
||||
| **新建** `services/video_analyzer.py` | 0 → ~150行 | 视频URL分析+分类+选评论 | 🆕 完全新增 |
|
||||
| `services/command_bus.py` | 1289行 | CMD_REGISTRY 加 smart_comment | 🆕 新需求 |
|
||||
|
||||
### Phase 4:指挥台展示(P2)
|
||||
|
||||
| 文件 | 当前行数 | 改动 | 原因 |
|
||||
|:-----|:---------|:------|:------|
|
||||
| `frontend/views/ops-command.js` | 413行 | 三队列独立展示 | 🆕 新需求 |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,288 @@
|
||||
# 导演工作室 · 重新设计方案
|
||||
|
||||
> 2026-10-10 · 基于**实测盘查**(非推测)
|
||||
> 目标:止住"越改越乱",把现有能力重新收进一个**边界清晰**的结构里
|
||||
|
||||
---
|
||||
|
||||
## 一、现状诊断(全部实测数据)
|
||||
|
||||
### 1.1 规模
|
||||
|
||||
| 项 | 数量 | 说明 |
|
||||
|---|---|---|
|
||||
| 前端视图 | **85 个** | 视频工厂相关 44 个 |
|
||||
| 后端路由 | **7 文件 / 145 端点 / 7206 行** | ave(33) · ave_project(30) · ave_keyframe(25) · ave_assets(33) · ave_scene(5) · ave_creatives(16) · ave_docs(3) |
|
||||
| `ave-director.js` | **112 KB** | 单文件注册 **26 个 `window._dir*` 函数** |
|
||||
| 项目对象顶层键 | **19 个** | 其中 3 个是从没写过的死键 |
|
||||
| 运行目录 | **15 个** | 含 5 个测试残留 |
|
||||
|
||||
### 1.2 五类具体问题(都对齐到了文件)
|
||||
|
||||
**① 空壳页面 4 个**(内容是"功能开发中,敬请期待")
|
||||
```
|
||||
ave-script.js 409 B 脚本生成
|
||||
ave-render.js 409 B 渲染任务
|
||||
ave-templates.js 406 B 模板
|
||||
ave-materials.js 409 B 素材库
|
||||
```
|
||||
|
||||
**② 新旧两套流程并存 —— 6 个老流程页在菜单里,但跑不通**
|
||||
```
|
||||
ave-flow-short-drama.js 744 B ← 菜单「🎭 短剧创作」
|
||||
ave-flow-dub.js 647 B ← 菜单「🎙️ 基础口播」
|
||||
ave-flow-beat.js 579 B ← 菜单「🥁 卡点视频」
|
||||
ave-flow-narrative.js 668 B ← 菜单「📖 角色叙事」
|
||||
ave-flow-digital-human.js 611 B ← 菜单「👤 数字人口播」
|
||||
ave-flow-hybrid.js 564 B ← 菜单「🎞️ 口播+混剪」
|
||||
```
|
||||
它们自己的注释写着:**"TTS / 素材 / BGM / 字幕的执行实现仍在接入中(运行时会明确跳过)"**
|
||||
→ 而工作室那条链路**是通的** → 两套并存,用户不知道点哪个
|
||||
|
||||
**③ 工作室内部职责重叠(用户已经混了)**
|
||||
```
|
||||
🌍 设定 vs 📋 创意卡 —— 都在"想清楚这个故事"
|
||||
🖼 关键帧设计 vs 🖼 关键帧 —— 用户明确问过"这两个有什么区别"
|
||||
```
|
||||
实测:用户上次说的"关键帧工作台里面是空的",我查了两轮才确认他指的是哪个页面。
|
||||
|
||||
**④ 单文件职责超载**
|
||||
`ave-director.js`(112 KB)一个文件里塞了:
|
||||
```
|
||||
<!-- ② 全局设置 --> 导演系统 / 风格 / 演员表 / 场景 / seed
|
||||
<!-- 📐 全片设定 --> 空间/角色/镜头语言(原故事板并入)
|
||||
<!-- ③ 按场次生成 --> 段落列表 + 场记板 + 生成
|
||||
<!-- ④ 分镜表 --> 镜头卡片编辑
|
||||
<!-- 出片进度 --> 渲染任务轮询
|
||||
```
|
||||
|
||||
**⑤ 数据源分散 + 死键**
|
||||
```
|
||||
projects/{pid}/project.json ← 项目对象(19 键,其中 3 键为空)
|
||||
storyboards/{pid}.json ← 分镜(不在 project.json)
|
||||
keyframes/{pid}/{sid}/ ← 关键帧图
|
||||
keyframe_videos/{pid}/{sid}/ ← 视频片段
|
||||
```
|
||||
`project.json` 里的 `keyframes` / `videos` / `assets` **三个键从没被写过**(空)。
|
||||
实测 `_enrich()` 每次读项目时**临时合并**前三个 → 说明它们本该在项目对象里。
|
||||
|
||||
---
|
||||
|
||||
## 二、根因(为什么会"越改越乱")
|
||||
|
||||
三条,都不是技术问题:
|
||||
|
||||
1. **加功能时"就地扩"** —— 没有"这一层该管什么"的边界。分镜页越塞越多(演员表、锚点、全片设定、出片设置),因为"顺手就放这了"。
|
||||
2. **新旧并存不删** —— 怕删坏,就留着旧的。结果路由/菜单/文档里同时存在两套,用户选错就在所难免。
|
||||
3. **数据"能跑就行"** —— 写在哪方便就写哪。分镜写 `storyboards/`、关键帧写 `keyframes/`,导致"上游带入"读不到(这是之前修过的真 bug)。
|
||||
|
||||
---
|
||||
|
||||
## 三、新架构
|
||||
|
||||
### 3.1 三条主线(先分清楚"这是哪一类东西")
|
||||
|
||||
```
|
||||
📦 原料 🎬 生产 📊 交付
|
||||
(可复用资产) (做一条片子) (看结果)
|
||||
角色/场景/道具 导演工作室 生产记录
|
||||
音色/BGM/音效 (唯一主流程) 费用统计
|
||||
产品/服装/素材 产物中心
|
||||
```
|
||||
|
||||
**判断规则**:
|
||||
- 能被**多条片子复用** → 进「原料」
|
||||
- 属于**某一条片子**的 → 进「生产」
|
||||
- 是**结果/统计** → 进「交付」
|
||||
|
||||
### 3.2 生产主线:工作室 9 阶段 → **7 阶段**
|
||||
|
||||
**合并的关键点**:`🖼 关键帧设计` + `🖼 关键帧` → **一个页面**(左设计右图)
|
||||
|
||||
```
|
||||
① 💡 创意 ┐
|
||||
② 🌍 设定 ├→ ③ 📋 创意卡 → ④ 📝 剧本 → ⑤ 🎬 分镜 → ⑥ 🖼 关键帧 → ⑦ 🎞 视频 → ⑧ 🎙 后期
|
||||
┘
|
||||
(素材层) (汇聚层) (执行层)
|
||||
```
|
||||
|
||||
**为什么保留 ①②(不合并)**:
|
||||
- `💡 创意` = **这个故事的种子**(候选 → 选一句)
|
||||
- `🌍 设定` = **世界的规则**(可跨故事复用,比如"肛肠科病房"这个世界的规则)
|
||||
- `📋 创意卡` = **两者合起来 → 这个故事的具体构想**
|
||||
- 职责不同,但**界面上必须写明各自管什么**(现在的毛病是没写)
|
||||
|
||||
**为什么合并 ⑥**:
|
||||
- 用户已经混了。而且"设计"(决定拆几张)和"生成"(出图)本来就是**同一步的两半** —— 设计完立刻要看图对不对。
|
||||
|
||||
### 3.3 每阶段一张「职责卡」(界面顶部固定显示)
|
||||
|
||||
这是**治乱的核心**:每个页面顶部明确写三行 —— **我从哪来 / 我产出什么 / 下一步用它做什么**。
|
||||
|
||||
| # | 阶段 | 输入(从哪来) | 产出 | 下一步用它做什么 |
|
||||
|---|---|---|---|---|
|
||||
| ① | 💡 创意 | 参数选型 | 选中的 1 句话 | 扩写成创意卡 |
|
||||
| ② | 🌍 设定 | — | 世界规则(可复用) | 创意卡 + 剧本的世界观依据 |
|
||||
| ③ | 📋 创意卡 | 创意 + 设定 | 故事卡(12 字段) | 剧本的**最高依据** |
|
||||
| ④ | 📝 剧本 | 创意卡 | 按**段落**的剧本 | 分镜按段落做 |
|
||||
| ⑤ | 🎬 分镜 | 剧本段落 + 导演/风格/演员 | 镜头(Shot) | 关键帧按镜头做 |
|
||||
| ⑥ | 🖼 关键帧 | 镜头 + 角色/场景资产 | 帧设计(A/B/C)+ 帧图 | 视频的首/尾帧 |
|
||||
| ⑦ | 🎞 视频 | 关键帧(选首尾)+ 引擎 | 视频片段(可多段) | 后期拼接 |
|
||||
| ⑧ | 🎙 后期 | 采用的片段 | 成片(拼接/字幕/混音) | 交付 |
|
||||
|
||||
### 3.4 菜单重排
|
||||
|
||||
**现状 → 目标**
|
||||
|
||||
```
|
||||
🎬 视频工厂 · 资源库(16 项) → 📦 原料(12 项)
|
||||
摘掉:素材库(空壳)
|
||||
保留:创意库 / 角色库 / 角色生成器 / 场景生成器 / 场景库 /
|
||||
真实场地 / 道具库 / 产品库 / 服装库 / 音色库 / BGM / 音效
|
||||
说明:环境音库、特效预设 暂藏在「更多」里(当前为空,用不上)
|
||||
|
||||
🎬 视频工厂 · 流程(12 项) → 🎬 生产(3 项)
|
||||
★ 导演工作室(唯一主流程)
|
||||
🔄 人物置换(独立工具,不属主流程)
|
||||
🔀 流程画布(高级功能,折叠在「高级」下)
|
||||
隐藏:6 个 ave-flow-*(老流程,跑不通)+ 新建流程(与流程画布重复)
|
||||
|
||||
🎬 视频工厂 · 能力中心(4 项) → 🧩 配置(4 项,不变)
|
||||
|
||||
🎬 视频工厂 · 运营(2+ 项) → 📊 交付(3 项)
|
||||
生产记录 / 费用统计 / 产物中心
|
||||
```
|
||||
|
||||
**净减**:`16+12+4+2 = 34 项` → `12+3+4+3 = 22 项`(-35%)
|
||||
|
||||
### 3.5 拆掉 112 KB 的巨物
|
||||
|
||||
`ave-director.js` 拆成 3 个视图(各管一件事):
|
||||
|
||||
```
|
||||
views/studio-shots-config.js ← 导演系统 / 风格 / 演员表 / 场景 / 锚点(配置)
|
||||
views/studio-shots-generate.js ← 段落列表(场记板)/ 生成 / 全片设定(动作)
|
||||
views/studio-shots-table.js ← 分镜表(结果,可编辑)
|
||||
```
|
||||
用户在一个页面里**从上到下**走,但代码是三块,各自可独立改。
|
||||
|
||||
---
|
||||
|
||||
## 四、数据模型(单一真相源)
|
||||
|
||||
### 4.1 原则
|
||||
> **一条片子的全部数据,只在一个文件里。** 媒体文件(图/视频/音频)仍各自落盘,但**路径登记在项目对象里**。
|
||||
|
||||
### 4.2 目标结构
|
||||
|
||||
**⚠️ 权衡说明(我先自我修正)**:
|
||||
我最初想把 `shots`(含关键帧和视频的全部版本记录)塞进 `project.json`。
|
||||
**但那样会让它膨胀到几百 KB** —— 20 个镜头 × 每镜 3 帧 × 每帧多版本,
|
||||
每次改一个字都要重写整个文件,性能和并发都会出问题。
|
||||
|
||||
**所以改成:单一真相源 = 单一目录,而不是单一文件。**
|
||||
|
||||
```
|
||||
projects/{pid}/ ← ★ 一个项目 = 一个目录(这就是"真相源")
|
||||
│
|
||||
├ project.json ← 轻量(< 20 KB):元数据 + 各阶段摘要
|
||||
│ { "project_id","title","stage","created_at","updated_at",
|
||||
│ "creative":{...}, // 💡 创意(选中的候选)
|
||||
│ "setting":{...}, // 🌍 设定
|
||||
│ "creative_card":{...}, // 📋 创意卡
|
||||
│ "script":{...}, // 📝 剧本(段落)
|
||||
│ "film_settings":{...}, // 📐 全片设定
|
||||
│ "post":{...}, // 🎙 后期(时间线 + 成片路径)
|
||||
│ "cast":[...], // 演员表
|
||||
│ "history":[...] } // 变更记录
|
||||
│
|
||||
├ shots.json ← 重数据:分镜 + 关键帧 + 视频(可单独读写)
|
||||
│ [ { "shot_id","paragraph_no","visual","duration","cast_slots", ...,
|
||||
│ "keyframes": { "plan":{A/B/C 提示词},
|
||||
│ "frames":[{seq,role,versions:[{v,file,adopted}]}] },
|
||||
│ "videos": [ {segment, versions:[{v,file,adopted,has_voice}]} ] } ]
|
||||
│
|
||||
└ media/ ← 媒体文件(或继续用现目录,只登记路径)
|
||||
keyframes/shot_01/v1.png
|
||||
videos/shot_01/s1_v1.mp4
|
||||
```
|
||||
|
||||
**为什么这样更好**:
|
||||
- `project.json` 保持轻量 → 改设定/剧本不会牵动分镜
|
||||
- `shots.json` 单独读写 → 生成一镜只改这个文件
|
||||
- **但对外只有"一个项目目录"** → 备份/复制/迁移 = 复制目录
|
||||
|
||||
**取消**:
|
||||
- `project.json` 里的 `keyframes` / `videos` / `assets` 三个死键 → 删除
|
||||
- `storyboards/{pid}.json` **作为独立位置** → 并入 `projects/{pid}/shots.json`
|
||||
(同级目录,不再是"另一个地方")
|
||||
- 前端不再需要 `_enrich()` 跨目录临时合并
|
||||
|
||||
### 4.3 收益
|
||||
- 「上游带入」天然正确(同一目录,不用跨目录捞)
|
||||
- 「这个项目的全部产物」一个请求拿到
|
||||
- 备份/迁移/复制项目 = 复制一个目录
|
||||
- 删项目 = 删一个目录(现在要删 4 个地方)
|
||||
|
||||
---
|
||||
|
||||
## 五、迁移路径(现有内容怎么落位)
|
||||
|
||||
**原则:不删数据,只搬家。每一步都可回滚(先备份)。**
|
||||
|
||||
| 现有 | 去向 |
|
||||
|---|---|
|
||||
| `storyboards/{pid}.json` 的 shots | 搬进 `project.json` 的 `shots[]` |
|
||||
| `keyframes/{pid}/{sid}/*.png` | 文件不动;路径登记到 `shots[i].keyframes` |
|
||||
| `keyframe_videos/{pid}/{sid}/*.mp4` | 文件不动;路径登记到 `shots[i].videos` |
|
||||
| `storyboard_paper` | 已是 `film_settings` 的来源(已迁移)→ 删键 |
|
||||
| 6 个 `ave-flow-*` 视图 | **文件保留**(不删仓库文件),仅从菜单摘掉 |
|
||||
| 4 个空壳视图 | 同上,从菜单摘掉(它们本来也不在菜单里) |
|
||||
| 运行目录里的测试残留 | 移到 `_trash/` |
|
||||
|
||||
---
|
||||
|
||||
## 六、实施顺序(4 批,每批独立可验证)
|
||||
|
||||
**批 1 · 止血(零风险,先让界面不乱)**
|
||||
- 菜单重排(摘掉老流程 + 空壳)
|
||||
- 每个阶段页顶部加「职责卡」(我产出什么 / 下一步用它做什么)
|
||||
- 合并 `🖼 关键帧设计` + `🖼 关键帧` 为一个页面
|
||||
|
||||
**批 2 · 数据归一(动后端,但只加不改)**
|
||||
- `shots` 搬进 `project.json`(写入时双写,读取时优先新位置)
|
||||
- 关键帧/视频的路径登记进 `shots[i]`
|
||||
- 前端改读新位置(保留旧路径兜底)
|
||||
|
||||
**批 3 · 拆巨物**
|
||||
- `ave-director.js` 拆 3 块(配置 / 生成 / 表)
|
||||
- 每块独立测试
|
||||
|
||||
**批 4 · 清理**
|
||||
- 删死键、废弃 `_enrich()`、测试残留移 `_trash/`
|
||||
- 更新文档
|
||||
|
||||
---
|
||||
|
||||
## 七、待你确认的 5 件事
|
||||
|
||||
1. **要不要合并「关键帧设计」和「关键帧」?**(我倾向合并 —— 你已经混过一次)
|
||||
2. **`ave-flow-*` 那 6 个老流程页,从菜单摘掉可以吗?**(文件保留)
|
||||
3. **「环境音库」当前是空的 —— 先藏起来,还是保留在菜单里?**
|
||||
4. **「流程画布」(`workflow`) 你还用吗?**(它是另一套编排方式,功能与工作室重叠)
|
||||
5. **批 1 的菜单重排,要不要现在就做?**(零风险,改完立刻清爽)
|
||||
|
||||
---
|
||||
|
||||
## 附:本次盘查用到的命令(可复现)
|
||||
|
||||
```bash
|
||||
# 视图规模
|
||||
ls -la frontend/src/views/*.js | awk '{print $5, $NF}' | sort -rn
|
||||
# 空壳识别
|
||||
for f in views/*.js; do [ $(wc -c < $f) -lt 1000 ] && echo "$f"; done
|
||||
# 后端端点分布
|
||||
for f in routes/ave*.py; do echo "$(basename $f) $(grep -cE '^@router\.' $f)"; done
|
||||
# 项目对象结构
|
||||
python3 -c "import json;d=json.load(open('.../project.json'));print(list(d.keys()))"
|
||||
```
|
||||
@@ -0,0 +1,175 @@
|
||||
# Task: submission_distill 内容蒸馏任务 🧪
|
||||
> **用途**: 将 `01_submissions/` 中积压的原始采集内容自动蒸馏为结构化报告
|
||||
> **建议添加至**: `ORACLE.yaml → tasks:`
|
||||
> **基于数据**: 2026-05-18 至 06-08 共 70 篇袁本初文章(238KB)
|
||||
|
||||
---
|
||||
|
||||
## 一、任务定义(YAML 片段)
|
||||
|
||||
```yaml
|
||||
- name: submission_distill
|
||||
description: "蒸馏 01_submissions 原始文章为分类摘要+元数据报告"
|
||||
schedule: 0 5 * * 1
|
||||
# ^ 每周一早5点(赶在 inbox_refine 4点+vector_rebuild 3:30 之前)
|
||||
on_machines:
|
||||
- chengzigedeAir
|
||||
action: distill
|
||||
params:
|
||||
source_dir: "01_submissions"
|
||||
output_dir: "03_knowledge/00_stream"
|
||||
batch_size: 10
|
||||
max_age_days: 14
|
||||
# 摘要模式: llm — 用 AI 写自然语言摘要
|
||||
# extract — 仅提取关键词和元数据(快速版)
|
||||
mode: llm
|
||||
```
|
||||
|
||||
也可拆为两个子任务,一个做关键词提取,一个做 AI 摘要:
|
||||
|
||||
```yaml
|
||||
- name: submission_metadata
|
||||
description: "提取 submissions 元数据和关键词索引(快速,每天跑)"
|
||||
schedule: 0 5 * * *
|
||||
on_machines:
|
||||
- chengzigedeAir
|
||||
action: distill
|
||||
params:
|
||||
mode: extract
|
||||
source_dir: "01_submissions"
|
||||
output_dir: "04_memory/long_term"
|
||||
|
||||
- name: submission_abstract
|
||||
description: "提交物 AI 摘要生成(耗时长,每周跑)"
|
||||
schedule: 0 5 * * 1
|
||||
on_machines:
|
||||
- chengzigedeAir
|
||||
action: distill
|
||||
params:
|
||||
mode: llm
|
||||
source_dir: "01_submissions"
|
||||
output_dir: "03_knowledge/00_stream"
|
||||
batch_size: 10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、运行时数据流
|
||||
|
||||
```
|
||||
01_submissions/*.md
|
||||
│
|
||||
├── step 1: extract_metadata (每天)
|
||||
│ ├── 解析文件名 → {date, author, category, seq}
|
||||
│ ├── 解析 front matter → {yaml fields}
|
||||
│ ├── 提取标签 → keywords[]
|
||||
│ ├── 计算字数、行数
|
||||
│ └── 更新 keyword_index.json
|
||||
│
|
||||
├── step 2: group_by_category (每周)
|
||||
│ ├── 按分类聚类
|
||||
│ ├── 按日期排序
|
||||
│ └── 计算跨分类交叉引用
|
||||
│
|
||||
├── step 3: generate_summary (每周)
|
||||
│ ├── 每个分类读最新一篇代表性文章
|
||||
│ ├── LLM 生成 200-300 字摘要
|
||||
│ ├── 提炼核心概念
|
||||
│ └── 输出到 03_knowledge/00_stream/
|
||||
│
|
||||
└── step 4: aggregate (每周)
|
||||
├── 生成跨分类主题网络
|
||||
├── 更新统计表
|
||||
└── 生成 JSON 摘要输出
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、首次执行时的预期输出
|
||||
|
||||
| 输出文件 | 内容 |
|
||||
|:---------|:-----|
|
||||
| `03_knowledge/00_stream/YYYY-MM_submissions_distillation.md` | 全量蒸馏报告(分类摘要+元数据+主题网络) |
|
||||
| `04_memory/long_term/keyword_index_YYYYMMDD.json` | 更新后的关键词索引 |
|
||||
| 同时更新 | `02_skills/kb_manager/` 中的分类知识条目 |
|
||||
|
||||
### 首次处理(基于当前 70 篇)统计预期
|
||||
|
||||
| 分类 | 篇数 | 预计摘要长度 | 代表标签 |
|
||||
|:-----|:----:|:-----------:|:---------|
|
||||
| 社会观察 | 22 | ~2,000字 | 底层逻辑、阶层流动、AI、就业、教育内卷 |
|
||||
| 政治分析 | 18 | ~1,800字 | 地缘政治、中美关系、大国博弈、社会治理 |
|
||||
| 经济分析 | 14 | ~1,600字 | 财务自由、资产配置、被动收入、投资 |
|
||||
| 哲学思考 | 10 | ~1,400字 | 认知升维、思维方式、方法论、阶层跃迁 |
|
||||
| 历史解读 | 6 | ~1,200字 | 历史周期律、文明升维、制度分析 |
|
||||
|
||||
### 跨分类主题网络
|
||||
|
||||
```
|
||||
认知升维 ──→ 社会观察(阶层流动)
|
||||
│
|
||||
├──→ 经济分析(财务自由系统)
|
||||
│
|
||||
├──→ 政治分析(大国博弈底层逻辑)
|
||||
│
|
||||
└──→ 历史解读(文明升维)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、与现有 ORACLE 任务的依赖关系
|
||||
|
||||
| 现有任务 | 时间 | 与 distill 的关系 |
|
||||
|:---------|:----:|:-----------------|
|
||||
| `collect_profiles` | 03:00 每天 | ✅ 前置——先采集后蒸馏 |
|
||||
| `vector_rebuild` | 03:30 每天 | ⚠️ 错峰——distill 改 05:00 |
|
||||
| `knowledge_inbox_refine` | 04:00 每天 | ⚠️ 错峰——distill 改 05:00 |
|
||||
| `git_sync` | 每15分钟 | ✅ 独立,不冲突 |
|
||||
|
||||
---
|
||||
|
||||
## 五、关键技术决策
|
||||
|
||||
### 为什么每天 extract 但每周 generate?
|
||||
|
||||
- **extract**(元数据提取):纯文本处理,每篇 < 0.1秒,70篇 < 10秒,可以每天跑
|
||||
- **generate**(AI摘要):每批10篇需要 LLM 调用,10-30秒/批,7批 ~2分钟,每周一次就够了
|
||||
|
||||
### batch_size=10 的考量
|
||||
|
||||
- 10篇恰好是平均一天的产量
|
||||
- 一批的 token 量约 35KB * 10 = 350KB,在 LLM 上下文窗口内
|
||||
- 分批处理可以防止单批次超时
|
||||
|
||||
### mode=llm vs mode=extract 的区别
|
||||
|
||||
- `extract`:纯文本的 shell 脚本就能完成(提取元数据、关键词、字数)
|
||||
- `llm`:需要 LLM 调用(写摘要、提炼概念、跨分类分析)
|
||||
|
||||
---
|
||||
|
||||
## 六、实现建议
|
||||
|
||||
distill action 的实现可以放在 `05_tools/07_matrix/scripts/` 下:
|
||||
|
||||
```bash
|
||||
# scripts/distill.sh — 内容蒸馏脚本
|
||||
# 用法: bash distill.sh <mode> <source_dir> <output_dir> [batch_size]
|
||||
|
||||
mode=${1:-extract}
|
||||
source_dir=${2:-01_submissions}
|
||||
output_dir=${3:-03_knowledge/00_stream}
|
||||
batch_size=${4:-10}
|
||||
|
||||
case "$mode" in
|
||||
extract)
|
||||
# 遍历所有 .md,提取 front matter + 文件名元数据
|
||||
# 输出 keyword_index.json
|
||||
;;
|
||||
llm)
|
||||
# 按分类聚类 → 每类取最新篇 → LLM 摘要 → 写报告
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
或者封装成 `mc distill` CLI 子命令,统一走 CommandBus。
|
||||
@@ -0,0 +1,373 @@
|
||||
# AgentOS 联邦系统 — 全量审计报告 v1.0
|
||||
|
||||
> 审计日期: 2026-06-19 | 基于代码实际读取,无推断无虚构
|
||||
> 审计范围: `05_tools/07_matrix/` 全部代码 + `05_tools/10_dashboard/` 关键代码 + `ORACLE.yaml`
|
||||
|
||||
---
|
||||
|
||||
## 一、项目状态总览
|
||||
|
||||
### 1.1 三台机器角色(来自 ORACLE.yaml)
|
||||
|
||||
| 机器 | IP (Tailscale) | 角色 | Dashboard Web | 职责 |
|
||||
|:-----|:--------------|:-----|:-------------|:------|
|
||||
| chengzigedeAir | 100.111.43.6 | **master** | ✅ localhost:9988 | 运行Dashboard + 养号 + 知识库 |
|
||||
| 5kechengdeAir | 100.72.182.121 | worker | ❌ 不跑 | 养号工人机器 |
|
||||
| 7kecheng | 100.65.35.28 | worker | ❌ 不跑 | 养号工人机器(大量账号) |
|
||||
|
||||
**Dashboard 只能通过 chengzigedeAir:9988 访问。** 用户在任意电脑浏览器打开 `http://100.111.43.6:9988` 即可操作。
|
||||
|
||||
### 1.2 本机身份(7个)
|
||||
|
||||
| 身份目录 | 所属账号 | 跨平台 |
|
||||
|:---------|:---------|:-------|
|
||||
| `phone_15370103682` | douyin_test + xhs_01 | ✅ 同身份跨平台 |
|
||||
| `douyin_133` | douyin_133 | ❌ 仅抖音 |
|
||||
| `douyin_133_2` | douyin_133_2 | ❌ 仅抖音 |
|
||||
| `douyin_134` | douyin_134 | ❌ 仅抖音 |
|
||||
| `douyin_test` | douyin_test | ❌ 仅抖音 |
|
||||
| `test_login` | (测试) | ❌ |
|
||||
| `xhs_01` | xhs_01 | ❌ |
|
||||
|
||||
**关键发现**: `phone_15370103682` 是唯一个真正"同身份跨平台"的身份——它的 identity_dir 同时绑定了 douyin_test + xhs_01。其他身份尚未启用跨平台模式。
|
||||
|
||||
### 1.3 命令执行链(从 Dashboard 到浏览器)
|
||||
|
||||
```
|
||||
Dashboard → POST /api/ops/run (routes/ops.py)
|
||||
→ CommandBus.dispatch() (services/command_bus.py)
|
||||
→ MachineSession.send()
|
||||
→ 本机: _send_local()
|
||||
→ bash nurture_runner.sh (services/nurture_runner.sh)
|
||||
→ python -m mc run (mc/cli.py → mc/run.py → mc/engine.py)
|
||||
→ CDPConnector.launch() (cdp_connector.py → Camoufox)
|
||||
→ BatchEngine._run_acct_on_conn()
|
||||
→ DouyinOps / XhsOps (douyin_ops.py / ops/xhs_ops.py)
|
||||
→ step by step from JSON blueprint
|
||||
→ 远程: _send_remote()
|
||||
→ SSH command to remote machine
|
||||
→ remote executes same mc run flow
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、CLI 体系
|
||||
|
||||
### 2.1 `mc`(当前主命令)
|
||||
|
||||
定义在: `mc/cli.py` | 入口: `python -m mc`
|
||||
|
||||
| 子命令 | 功能 | 代码位置 |
|
||||
|:-------|:-----|:---------|
|
||||
| `mc run --accounts=A --blueprints=B --rounds=N` | **批量执行引擎** | `mc/run.py` → `mc/engine.py` |
|
||||
| `mc account list` | 账号列表 | `mc/cli.py:cmd_account()` |
|
||||
| `mc account login <name>` | 登录 | → `login_identity.py` |
|
||||
| `mc account status [name]` | 登录状态 | → `matrix_mgmt.py` |
|
||||
| `mc account export/import` | 导入导出 | → `matrix_mgmt.py` |
|
||||
| `mc blueprint list/show` | 蓝图管理 | → `matrix_mgmt.py` |
|
||||
| `mc task comment --url=...` | 定向评论任务 | → `task_engine.py` |
|
||||
| `mc corpus list/add/select` | 语料库管理 | → `mc/corpus.py` |
|
||||
| `mc proxy list/test/set` | 代理管理 | 预留 |
|
||||
| `mc sms config/test` | SMS 配置 | 预留 |
|
||||
| `mc status all/accounts/browsers` | 全局状态 | `mc/cli.py` |
|
||||
|
||||
### 2.2 `matrix`(旧命令,仍可用但非主入口)
|
||||
|
||||
定义在: `matrix.py` | 功能类似于 mc,但接口更老
|
||||
|
||||
| 子命令 | 说明 |
|
||||
|:-------|:------|
|
||||
| `matrix account list` | 列出账号(读 accounts.yaml) |
|
||||
| `matrix account create` | 创建新身份 |
|
||||
| `matrix account login` | 首次登录 |
|
||||
| `matrix nurture run` | 养号(不同于 mc run 的执行路径) |
|
||||
|
||||
### 2.3 其他工具
|
||||
|
||||
| 文件 | 说明 |
|
||||
|:-----|:------|
|
||||
| `guardd.py` | 系统守护进程:每60s检测孤儿浏览器/磁盘/超时/心跳 |
|
||||
| `orchestrator.py` | 养号编排器(旧版,engine.py 已替代) |
|
||||
| `yanghao_runner.py` | 养号运行器(旧版启动方式) |
|
||||
| `task_engine.py` | `mc task` 调度的任务引擎 |
|
||||
| `task_scheduler.py` | 定时任务调度器 |
|
||||
| `atom_ops.py` | 旧版原子操作定义(已废弃,ops/ 已替代) |
|
||||
| `nurture_blueprint.py` | 抖音养号步序列(Python定义,`nurture_loop` 使用) |
|
||||
| `cdp_connector.py` | 浏览器连接管理器(Camoufox/Chrome) |
|
||||
| `browser_utils.py` | GracefulBrowser 浏览器生命周期 |
|
||||
| `browser_manager.py` | 浏览器管理器(旧版) |
|
||||
| `collect_homepage_info.py` | 主页信息采集 |
|
||||
| `collect_batch_runner.py` | 批量采集执行器 |
|
||||
| `publish_video.py` | 视频发布 |
|
||||
| `login_identity.py` | 身份登录入口 |
|
||||
| `vision_bridge.py` | oMLX 视觉分析桥接(2026-06-19 新加) |
|
||||
| `watch_session.py` | 会话监控(2026-06-19 测试用) |
|
||||
| `auth_manager.py` | 认证管理 |
|
||||
| `anti_detection.py` | 反检测工具 |
|
||||
| `page_state.py` | 页面状态读取 |
|
||||
| `step_by_step_v2.py` | 分步执行v2(旧版) |
|
||||
| `step_by_step_v3.py` | 分步执行v3(旧版) |
|
||||
|
||||
---
|
||||
|
||||
## 三、蓝图系统
|
||||
|
||||
### 3.1 蓝图文件(14个 JSON)
|
||||
|
||||
位于: `05_tools/07_matrix/blueprints/`
|
||||
|
||||
| 蓝图 | 平台 | 步骤数 | 说明 |
|
||||
|:-----|:------|:------|:-----|
|
||||
| `douyin_daily` | douyin | 23 | 日常养号:浏览/点赞/收藏/评论循环 |
|
||||
| `douyin_active_v1` | douyin | 27 | 高活跃养号:多浏览+多点赞+搜索+评论 |
|
||||
| `douyin_comment` | douyin | 5 | 定向评论:goto_url → watch → comment |
|
||||
| `douyin_comment_test` | douyin | 5 | 定向评论测试(硬编码URL) |
|
||||
| `douyin_reply` | douyin | 5 | 回复评论:找到我的评论 → 回复 |
|
||||
| `douyin_search` | douyin | 14 | 搜索+浏览:搜关键词 → 浏览 → 互动 |
|
||||
| `douyin_search_browse` | douyin | 7 | 搜索浏览(简版) |
|
||||
| `douyin_collect` | douyin | 5 | 信息采集:搜索 → 打开主页 → 采集 |
|
||||
| `douyin_read_profile` | douyin | 9 | 读主页:昵称/抖音号/关注/粉丝/获赞 |
|
||||
| `xhs_daily` | xiaohongshu | 17 | 小红书日常养号 |
|
||||
| `xhs_active_v1` | xiaohongshu | 26 | 小红书高活跃 |
|
||||
| `xiaohongshu_read_profile` | xiaohongshu | 8 | 小红书读主页 |
|
||||
| `export_douyin_01_*` | douyin | 3 | 导出任务(custom ops) |
|
||||
| `export_xhs_01_*` | xiaohongshu | 4 | 导出任务(custom ops) |
|
||||
|
||||
### 3.2 蓝图步骤格式
|
||||
|
||||
```json
|
||||
{"step_id": 1, "op": "goto_url", "args": {"url": "@url"}}
|
||||
```
|
||||
|
||||
**参数模板系统**(运行时替换):
|
||||
- `@url` → 从任务参数的 url 字段替换
|
||||
- `@corpus` → 从语料库取文案
|
||||
- `@keyword` → 从任务参数的 keyword 字段替换
|
||||
- `@direction` → 评论方向(正面/提问/共鸣/感慨)
|
||||
- `@scene` → 场景(first_comment/reply/repeat)
|
||||
- `@comment_text` → 直接评论文本
|
||||
- `@reply_text` → 回复文本
|
||||
|
||||
### 3.3 蓝图执行方式
|
||||
|
||||
**通过 `mc/engine.py` 的 `BatchEngine._run_acct_on_conn()`**:
|
||||
```
|
||||
1. 加载 JSON blueprint
|
||||
2. 按 platform 创建 DouyinOps / XhsOps 实例
|
||||
3. 导航到平台首页
|
||||
4. 逐个执行步骤:ops.execute(op, args, step_id)
|
||||
5. 参数替换由 _resolve_args() 处理
|
||||
6. 每步间隔 1.5s
|
||||
```
|
||||
|
||||
### 3.4 原生Python蓝图
|
||||
|
||||
除了 JSON,还有 `nurture_blueprint.py` 中的 `BLUEPRINT_NURTURE`(Python列表):
|
||||
```python
|
||||
BLUEPRINT_NURTURE = [
|
||||
("进入视频", op_enter_video, {}, 1.0),
|
||||
("观看", op_watch, {}, 1.0),
|
||||
("点赞", op_like, {}, 0.4), # ← 概率
|
||||
...
|
||||
]
|
||||
```
|
||||
这个由 `nurture_loop()` / `nurture_daily.py` 使用。**注意这个和 JSON 蓝图是两套独立的执行路径。**
|
||||
|
||||
---
|
||||
|
||||
## 四、原子操作体系
|
||||
|
||||
### 4.1 当前实现(ops/ 目录)
|
||||
|
||||
```
|
||||
ops/
|
||||
├── _base.py → PlatformOps 基类 + OpResult
|
||||
├── xhs_ops.py → XhsOps (16个操作) ← 小红书
|
||||
└── douyin/
|
||||
├── __init__.py
|
||||
├── browse.py → 浏览类操作
|
||||
└── interact.py → 互动类操作
|
||||
|
||||
douyin_ops.py → DouyinOps (20个操作) ← 抖音(另一套实现)
|
||||
```
|
||||
|
||||
**注意**: 抖音有**两套**操作实现:
|
||||
1. `douyin_ops.py` → 独立完整类(engine.py 当前使用的)
|
||||
2. `ops/douyin/` → 拆分版(browse.py + interact.py,可能较新)
|
||||
|
||||
### 4.2 DouyinOps 支持的20个操作
|
||||
|
||||
| 操作 | 说明 |
|
||||
|:-----|:------|
|
||||
| goto_home | 回到首页 |
|
||||
| goto_url | 跳转到指定URL |
|
||||
| like | 点赞 |
|
||||
| collect | 收藏 |
|
||||
| follow | 关注 |
|
||||
| open_comments | 打开评论区 |
|
||||
| close_comments | 关闭评论区 |
|
||||
| post_comment | 发表评论 |
|
||||
| next_video | 下一个视频(ArrowDown) |
|
||||
| prev_video | 上一个视频(ArrowUp) |
|
||||
| search | 搜索关键词 |
|
||||
| wait_watch | 等待+观看(随机时长) |
|
||||
| scroll_feed | 滚动瀑布流 |
|
||||
| open_video | 点开视频 |
|
||||
| wait | 等待 |
|
||||
| go_back | 返回 |
|
||||
| goto_profile | 去用户主页 |
|
||||
| read_profile_field | 读主页字段 |
|
||||
| read_my_comments | 读我的评论 |
|
||||
| reply_comment | 回复评论 |
|
||||
| search_browse | 搜索+浏览 |
|
||||
|
||||
### 4.3 XhsOps 支持的16个操作
|
||||
|
||||
| 操作 | 说明 |
|
||||
|:-----|:------|
|
||||
| xhs_goto_home | 回到首页 |
|
||||
| xhs_browse | 浏览(已在首页则跳过) |
|
||||
| xhs_scroll_feed | 滚动瀑布流 |
|
||||
| xhs_click_note | 点击笔记 |
|
||||
| xhs_like | 点赞 |
|
||||
| xhs_collect | 收藏 |
|
||||
| xhs_comment | 评论 |
|
||||
| xhs_post_comment | 发表评论 |
|
||||
| xhs_follow | 关注 |
|
||||
| xhs_search | 搜索 |
|
||||
| xhs_goto_profile | 去用户主页 |
|
||||
| xhs_read_nickname | 读昵称 |
|
||||
| xhs_read_user_id | 读用户ID |
|
||||
| xhs_read_following | 读关注数 |
|
||||
| xhs_read_fans | 读粉丝数 |
|
||||
| xhs_read_likes | 读获赞数 |
|
||||
| xhs_read_bio | 读个人简介 |
|
||||
|
||||
### 4.4 平台操作基类接口
|
||||
|
||||
```python
|
||||
class OpResult:
|
||||
op: str # 操作名
|
||||
step_id: int # 步骤编号
|
||||
success: bool
|
||||
detail: str # 简短描述
|
||||
elapsed: float # 耗时(秒)
|
||||
error: str # 失败原因
|
||||
|
||||
class PlatformOps(ABC):
|
||||
async def execute(self, op, args, step_id) -> OpResult # 统一入口,自动重试
|
||||
async def _do_execute(self, op, args, step_id) -> OpResult # 子类实现
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、命令分发系统
|
||||
|
||||
### 5.1 CommandBus (services/command_bus.py)
|
||||
|
||||
| 方法 | 功能 |
|
||||
|:-----|:------|
|
||||
| `CommandBus.dispatch(type, accounts, params)` | 统一入口,按机器分组 |
|
||||
| `CommandBus.get_status(machine, account)` | 查询命令状态 |
|
||||
| `CommandBus.get_all_machines_status()` | 所有机器聚合状态 |
|
||||
| `CommandBus.cancel(run_id)` | 取消命令 |
|
||||
|
||||
**MachineSession** (每机器一个):
|
||||
|
||||
| 方法 | 功能 |
|
||||
|:-----|:------|
|
||||
| `send(cmd)` | 本地→`_send_local` / 远程→`_send_remote` |
|
||||
| `preflight()` | SSH可达? 活跃命令<3? 资源检查 |
|
||||
| `poll(cmd)` | 轮询结果(本地读文件/远程SSH读取) |
|
||||
| `cancel(cmd)` | 取消命令(本地pkill/远程SSH pkill) |
|
||||
| `graceful_exit()` | 优雅退出+清理 |
|
||||
|
||||
### 5.2 结果文件格式
|
||||
|
||||
```
|
||||
runtime/nurture/results/{run_id}.json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"run_id": "nurture_1234567890_douyin_test",
|
||||
"account": "douyin_test",
|
||||
"blueprint": "douyin_daily",
|
||||
"status": "completed",
|
||||
"hostname": "chengzigedeAir",
|
||||
"steps": {"total": 23, "success": 21, "failed": 2},
|
||||
"duration_secs": 452
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、配置文件体系
|
||||
|
||||
| 文件 | 用途 | 覆盖范围 |
|
||||
|:-----|:------|:---------|
|
||||
| `ORACLE.yaml`(根目录) | 宪法:机器定义/账号分配/任务计划/全局配置 | 三台机器只读 |
|
||||
| `accounts_registry.yaml`(07_matrix/) | 账号注册表:每个账号的机器归属/平台/窗口位置 | 三台机器同步 |
|
||||
| `config_template/accounts.yaml` | 账号配置模板 | 按需部署到 config/ |
|
||||
| `config_template/sms.yaml` | SMS API 配置模板 | 按需部署到 scripts/config/ |
|
||||
| `config_template/screen_layout.yaml` | UI 布局参数(评论框坐标等) | 按需部署 |
|
||||
| `config_template/schedule.yaml` | 定时任务模板 | 按需部署 |
|
||||
| `scripts/config/sms.yaml` | 实际运行的 SMS 配置 | 本机生效 |
|
||||
| `scripts/config/schedule.yaml` | 实际运行的定时任务 | 本机生效 |
|
||||
| `scripts/config/comment_corpus.yaml` | 评论语料库 | 本机生效 |
|
||||
|
||||
---
|
||||
|
||||
## 七、守护进程
|
||||
|
||||
| 进程 | 启动方式 | 功能 |
|
||||
|:-----|:---------|:-----|
|
||||
| `guardd` | launchd 守护 | 每60s检测:孤儿浏览器/磁盘<5GB/Dashboard存活/命令超时30min/浏览器数>3 |
|
||||
| `Dashboard` | launchd 守护 (端口9988) | FastAPI Web服务 |
|
||||
| `socks5-forwarder` | launchd 守护 (端口10800) | SOCKS5 代理转发 |
|
||||
|
||||
guardd 检测结果写入 `runtime/guardd/events.log`,心跳推送到 `localhost:9988/api/push/heartbeat`。
|
||||
|
||||
---
|
||||
|
||||
## 八、语料库体系
|
||||
|
||||
| 文件 | 格式 | 用途 |
|
||||
|:-----|:------|:------|
|
||||
| `corpus/douyin.yaml` | YAML | 抖音语料(已定义) |
|
||||
| `corpus/xiaohongshu.yaml` | YAML | 小红书语料(已定义) |
|
||||
| `scripts/config/comment_corpus.yaml` | YAML | 运行时评论语料库(实际使用) |
|
||||
|
||||
`CorpusManager` 类 (`mc/corpus.py`) 提供:
|
||||
- `get_comment_for_video(title, direction, account_id)` → 根据视频标题和方向选文案
|
||||
- `get_comment_for_scene(persona, scene, keyword, round_num)` → 按场景选文案
|
||||
|
||||
---
|
||||
|
||||
## 九、关键依赖版本
|
||||
|
||||
| 组件 | 版本 | 路径 |
|
||||
|:-----|:------|:------|
|
||||
| Python | 3.13.12 | `~/.workbuddy/binaries/python/envs/agent-os/bin/python3` |
|
||||
| Camoufox | 0.4.11 | agent-os venv |
|
||||
| Playwright | 1.58.0 | agent-os venv |
|
||||
| FastAPI | (在 requirements.txt) | agent-os venv |
|
||||
| uvicorn | (在 requirements.txt) | agent-os venv |
|
||||
|
||||
---
|
||||
|
||||
## 十、代码清理建议
|
||||
|
||||
以下文件经检查为**废弃/归档状态**,不应再被主动使用:
|
||||
|
||||
| 文件 | 被谁取代 | 建议处理 |
|
||||
|:-----|:---------|:--------|
|
||||
| `matrix.py` 整体 | `mc/` | 归档到 `archive/` |
|
||||
| `atom_ops.py` | `ops/_base.py` + `DouyinOps`/`XhsOps` | 归档 |
|
||||
| `nurture_blueprint.py ` 的 `BLUEPRINT_NURTURE` | `blueprints/*.json` + `engine.py` | 保留(nurture_loop 仍在用) |
|
||||
| `yanghao_runner.py` | `mc run` 命令 | 归档 |
|
||||
| `orchestrator.py` | `mc/engine.py` | 归档 |
|
||||
| `step_by_step_v2.py` / `step_by_step_v3.py` | `engine.py` | 归档 |
|
||||
| `archive/` 内全部 | (已在 archive) | 保持不动 |
|
||||
| `browser_manager.py` | `cdp_connector.py` | 保留(CommandBus 可能引用) |
|
||||
| `xhs_session_test.py` / `watch_session.py` | 测试文件 | 删除或归档 |
|
||||
@@ -0,0 +1,430 @@
|
||||
# AgentOS 任务编排与调度架构 v1.0
|
||||
|
||||
> 版本: 1.0 | 日期: 2026-07-04 | 基于全部现有代码审计 + 需求讨论
|
||||
> 前置阅读: `PLANS/SCHEDULER_ARCHITECTURE_v3.md`(调度引擎原始设计)
|
||||
> 本文件替代: 旧版调度设计中的 Phase 2/3 部分,整合为新架构
|
||||
|
||||
---
|
||||
|
||||
## 一、设计目标
|
||||
|
||||
| 目标 | 说明 |
|
||||
|:-----|:------|
|
||||
| **评论与视频内容关联** | 评论不再随机,根据视频标题/标签匹配行业语料 |
|
||||
| **账号行业隔离** | 大健康账号发健康评论,通用账号发通用评论,互不串 |
|
||||
| **三优先级调度** | P0优先/P1日常/P2劣后,插队不中断浏览器 |
|
||||
| **账号互斥** | 同一账号不能同时出现在两个浏览器 |
|
||||
| **中央分析+远程执行** | Master统一做视频分析/分类/选评论,Worker只执行 |
|
||||
|
||||
---
|
||||
|
||||
## 二、最小任务单元
|
||||
|
||||
### 2.1 定义
|
||||
|
||||
```
|
||||
最小任务单元 = {account_id, operation_type, params, machine, priority}
|
||||
```
|
||||
|
||||
一个任务单元 = 一个账号 × 一次浏览器操作的组合,不可再拆。
|
||||
|
||||
### 2.2 任务类型
|
||||
|
||||
| operation_type | 说明 | 默认优先级 | 来源 |
|
||||
|:---------------|:-----|:-----------|:-----|
|
||||
| `smart_comment` | 智能评论(带视频分析+行业匹配) | P0 | Dashboard 提交 |
|
||||
| `comment` | 定向评论(已有模式) | P0 | Dashboard / CLI |
|
||||
| `nurture` | 日常养号 | P1 | 定时任务 / 手动 |
|
||||
| `collect` | 信息采集 | P2 | 手动 / 定时 |
|
||||
| `like` | 点赞互动 | P1 | 蓝图 |
|
||||
| `login` | 登录(特殊,不走调度器) | - | 单独处理 |
|
||||
|
||||
### 2.3 任务状态
|
||||
|
||||
```
|
||||
PENDING → QUEUED → RUNNING → COMPLETED
|
||||
↓ ↓
|
||||
FAILED CANCELLED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、三层编排体系
|
||||
|
||||
### 3.1 系统分层
|
||||
|
||||
```
|
||||
用户提交(Dashboard / API)
|
||||
│
|
||||
▼
|
||||
┌── L3: Master 中央编排 ──────────────────────────────┐
|
||||
│ (chengzigedeAir) │
|
||||
│ │
|
||||
│ ① 接收任务(url列表 + 账号列表 + 操作类型) │
|
||||
│ │
|
||||
│ ② 视频分析(本机浏览器提取信息) │
|
||||
│ ├─ 标题 / 描述 / 标签 │
|
||||
│ ├─ 关键词匹配 → 分类(医疗健康 / 通用) │
|
||||
│ └─ 从对应语料池选评论 │
|
||||
│ │
|
||||
│ ③ 拆解为最小单元 │
|
||||
│ {douyin_133, comment, url, "医生讲得很清楚"} │
|
||||
│ │
|
||||
│ ④ 按机器打包 │
|
||||
│ 7kecheng → [5个单元] │
|
||||
│ 5kechengdeAir → [3个单元] │
|
||||
│ │
|
||||
│ ⑤ POST /scheduler/submit → 各机 guardd │
|
||||
└────────────────────────────┬──────────────────────────┘
|
||||
│ Tailscale
|
||||
▼
|
||||
┌── L2: 各机 guardd 调度器 ──────────────────────────┐
|
||||
│ (7kecheng / 5kechengdeAir) │
|
||||
│ │
|
||||
│ 收到大包 → 展开为独立任务 │
|
||||
│ │
|
||||
│ 三队列管理: │
|
||||
│ P0 优先: 智能评论、定向操作(当前任务结束后插队) │
|
||||
│ P1 日常: 养号、点赞(FIFO 正常排队) │
|
||||
│ P2 劣后: 采集、同步(slot 空闲才执行) │
|
||||
│ │
|
||||
│ 账号互斥守卫 │
|
||||
│ │
|
||||
│ 3 Slot 流水线 │
|
||||
│ slot0: [P1→P1→P1] │
|
||||
│ slot1: [P1→P0→P1] ← P0插队 │
|
||||
│ slot2: [P2→空闲→P2] ← P2填空 │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 各程序职责
|
||||
|
||||
| 节点 | 程序 | 职责 |
|
||||
|:-----|:------|:------|
|
||||
| **Master** | CommandBus | 接收请求→拆解→按机器分组→分发 |
|
||||
| **Master** | VideoAnalyzer 🆕 | 视频URL分析、行业分类、选评论 |
|
||||
| **Master** | Dashboard API | 前端界面、健康监控 |
|
||||
| **Worker** | guardd HTTP Server | 接收任务、返回状态 |
|
||||
| **Worker** | Scheduler 🆕改 | 三队列管理、3 slot流水线、P0抢插、账号互斥 |
|
||||
| **Worker** | Executor | 子进程执行(mc run / mc task comment) |
|
||||
| **Worker** | SlotManager | 浏览器槽位管理、进程监控 |
|
||||
| **Worker** | HeartbeatReporter | 每15秒上报slot/队列/账号状态到Dashboard |
|
||||
|
||||
---
|
||||
|
||||
## 四、三队列调度算法
|
||||
|
||||
### 4.1 队列结构
|
||||
|
||||
```python
|
||||
class Scheduler:
|
||||
# 三个独立优先队列
|
||||
queue_priority = PriorityQueue() # P0: 智能评论/定向操作
|
||||
queue_normal = PriorityQueue() # P1: 养号/点赞/日常
|
||||
queue_filler = PriorityQueue() # P2: 采集/同步/劣后
|
||||
|
||||
# 3 条流水线
|
||||
active_tasks: dict[int, dict] # {slot_id: task}
|
||||
|
||||
# 账号互斥表
|
||||
account_slots: dict[str, int] # {account_id: slot_id}
|
||||
|
||||
# 被 P0 打断的 P1 任务暂存
|
||||
paused_tasks: dict[int, dict] # {slot_id: task}
|
||||
```
|
||||
|
||||
### 4.2 调度循环(每15秒)
|
||||
|
||||
```
|
||||
run_cycle():
|
||||
step 1: 检查所有 slot
|
||||
任务完成 → 释放 slot + 从 account_slots 中移除账号
|
||||
|
||||
step 2: 检查暂停队列
|
||||
有被 P0 打断的 P1 任务 → 放回日常队列恢复
|
||||
|
||||
step 3: 分配空闲 slot
|
||||
for slot_id in [0, 1, 2]:
|
||||
if slot 正在运行: continue
|
||||
|
||||
# 取当前活跃账号列表
|
||||
busy = set(account_slots.values())
|
||||
|
||||
# 按优先级取任务(避开 busy 账号)
|
||||
task = pop_available(P0优先, P1日常, P2劣后)
|
||||
|
||||
if task:
|
||||
account_slots[task.account] = slot_id
|
||||
start_execution(slot_id, task)
|
||||
```
|
||||
|
||||
### 4.3 P0 抢占逻辑
|
||||
|
||||
```
|
||||
收到 P0 任务 → 检查目标账号:
|
||||
├─ 空闲 → 直接分配给空闲 slot
|
||||
└─ 忙碌 → 等到当前任务结束后插入:
|
||||
slot0: [P1养号_01, ▶️P0评论, P1养号_02, P1养号_03]
|
||||
↑ P1完成后立即执行P0
|
||||
P0完成后恢复P1队列
|
||||
|
||||
不中断正在执行的浏览器(不强行 kill 进程)
|
||||
```
|
||||
|
||||
### 4.4 P2 劣后逻辑
|
||||
|
||||
```
|
||||
P2 只在 slot 空闲且 P0/P1 都为空时才执行
|
||||
P2 可被任何 P0/P1 抢占:
|
||||
slot2: [▶️P2采集] → 收到P1养号 → P2回队列 → [▶️P1养号] → P1完成 → [▶️P2采集]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、账号互斥守卫(三层检查)
|
||||
|
||||
### 5.1 检查层级
|
||||
|
||||
| 层级 | 位置 | 检查内容 | 阻止时机 |
|
||||
|:-----|:------|:---------|:---------|
|
||||
| 第1层 | `submit_task()` | 该账号在 task_store 中是否有 running/queued 状态 | 入队时拒绝 |
|
||||
| 第2层 | `_schedule_all_slots()` | 该账号在 `account_slots` 表中是否存在 | 分配时跳过 |
|
||||
| 第3层 | `slot_manager.find_account()` | 该账号是否已打开浏览器 | 执行前拦截 |
|
||||
|
||||
### 5.2 账号状态表
|
||||
|
||||
```python
|
||||
account_slots = {
|
||||
"douyin_133": 0, # slot 0 正在运行
|
||||
"douyin_134": 1, # slot 1 正在运行
|
||||
# "douyin_135" → 不在表中 = 空闲
|
||||
}
|
||||
```
|
||||
|
||||
任务完成自动移除,异常崩溃时 scheduler 清理。
|
||||
|
||||
---
|
||||
|
||||
## 六、视频分析引擎(VideoAnalyzer)
|
||||
|
||||
### 6.1 模块说明
|
||||
|
||||
```
|
||||
新建文件: agent-sync/05_tools/10_dashboard/services/video_analyzer.py
|
||||
运行位置: 仅 Master(本机),Worker 不需要
|
||||
使用技术: Camoufox 浏览器(已有)+ 关键词匹配(已有)
|
||||
```
|
||||
|
||||
### 6.2 核心逻辑
|
||||
|
||||
```python
|
||||
class VideoAnalyzer:
|
||||
"""视频分析器:提取信息 → 行业分类 → 选评论"""
|
||||
|
||||
# 行业关键词映射
|
||||
INDUSTRY_TAGS = {
|
||||
"medical": ["医生","医院","药","健康","养生","中医","体检",
|
||||
"症状","治疗","康复","营养","饮食","锻炼","专家"],
|
||||
"finance": ["股票","基金","理财","投资","经济","A股","财经"],
|
||||
"tech": ["手机","数码","电脑","科技","AI","人工智能","评测"],
|
||||
"food": ["美食","做饭","菜谱","餐厅","好吃","探店"],
|
||||
}
|
||||
|
||||
async def analyze(self, url: str) -> VideoContext:
|
||||
"""分析单个视频URL
|
||||
1. Camoufox 浏览器打开 URL
|
||||
2. 提取: 标题(document.title) / meta描述 / 标签
|
||||
3. 读取评论区热门评论(可选)
|
||||
4. 返回 VideoContext
|
||||
"""
|
||||
|
||||
def classify(self, context: VideoContext) -> str:
|
||||
"""分类行业"""
|
||||
for ind, tags in INDUSTRY_TAGS.items():
|
||||
if any(tag in context.title for tag in tags):
|
||||
return ind
|
||||
return "general" # 兜底
|
||||
|
||||
def pick_comment(self, industry: str, account_industry: str, direction: str) -> str:
|
||||
"""选评论
|
||||
账号行业匹配视频行业 → 行业语料
|
||||
不匹配 → 万能语料
|
||||
"""
|
||||
```
|
||||
|
||||
### 6.3 与现有能力的关系
|
||||
|
||||
| 现有能力 | 是否使用 | 说明 |
|
||||
|:---------|:---------|:------|
|
||||
| **Camoufox + Playwright** | ✅ 直接使用 | 已有,打开视频页取信息 |
|
||||
| **douyin_ops.goto_url()** | ✅ 直接使用 | 已有,导航到指定URL |
|
||||
| **CorpusManager** | ✅ 改造使用 | 加行业过滤 + 万能池 |
|
||||
| **Scrapling / Crawl4AI** | ❌ 不使用 | 抓不了抖音动态内容 |
|
||||
| **ChromaDB (agent-local/vector_db/)** | ⚠️ 可选 | Phase 2 加向量分类时可复用 |
|
||||
|
||||
---
|
||||
|
||||
## 七、语料库结构
|
||||
|
||||
### 7.1 两层语料池
|
||||
|
||||
```yaml
|
||||
# corpus/douyin.yaml
|
||||
categories:
|
||||
# ── 万能池(所有账号可用,不匹配行业时兜底)──
|
||||
万能称赞:
|
||||
accessible: "*"
|
||||
comments:
|
||||
- 博主说得很对
|
||||
- 讲得不错,学到了
|
||||
- 分析得很到位
|
||||
万能提问:
|
||||
accessible: "*"
|
||||
comments:
|
||||
- 请问这个怎么学?
|
||||
- 大概需要多长时间?
|
||||
万能共鸣:
|
||||
accessible: "*"
|
||||
comments:
|
||||
- 太真实了
|
||||
- 说出了我的心声
|
||||
|
||||
# ── 行业池(仅对应行业账号可用)──
|
||||
大健康称赞:
|
||||
accessible: ["health"]
|
||||
match_tags: ["医生","医院","药","健康","养生","中医","体检","症状"]
|
||||
comments:
|
||||
- 医生讲得很清楚,通俗易懂
|
||||
- 这个方子很实用,收藏了
|
||||
- 讲得很专业,学到了
|
||||
大健康提问:
|
||||
accessible: ["health"]
|
||||
comments:
|
||||
- 这个症状一般怎么处理?
|
||||
- 平时饮食有什么需要注意的?
|
||||
```
|
||||
|
||||
### 7.2 账号行业标记
|
||||
|
||||
```json
|
||||
// profiles.json
|
||||
{
|
||||
"douyin_133": {"nickname":"苏州胃肠体检敏敏", "industry":"health"},
|
||||
"douyin_test": {"nickname":"小美养生茶", "industry":"health"},
|
||||
"douyin_134": {"nickname":"在苏州呀", "industry":"general"},
|
||||
"xhs_01": {"nickname":"...", "industry":"general"}
|
||||
}
|
||||
```
|
||||
|
||||
两种行业:`health`(大健康)、`general`(通用)。现阶段统一。
|
||||
|
||||
---
|
||||
|
||||
## 八、完整数据流示例
|
||||
|
||||
### 场景:提交 20 个账号评论 1 个视频
|
||||
|
||||
```
|
||||
Step 1: Master 收到请求
|
||||
POST /api/ops/run {type:"smart_comment", urls:["https://..."], accounts:[...]}
|
||||
↓
|
||||
|
||||
Step 2: VideoAnalyzer 分析视频
|
||||
本机 Camoufox 打开视频URL
|
||||
→ 标题: "胃镜检查到底疼不疼?医生告诉你真相"
|
||||
→ 关键词匹配: "医生"、"胃" → industry: medical
|
||||
→ 选评论: "医生讲得很清楚,通俗易懂"
|
||||
↓
|
||||
|
||||
Step 3: 拆解最小单元
|
||||
20个账号 × 1个视频 = 20个任务单元
|
||||
每个单元 = {account_id, comment:"医生讲得很清楚", url, priority:P0}
|
||||
↓
|
||||
|
||||
Step 4: 按机器打包
|
||||
查 ORACLE 账号→机器分配表:
|
||||
7kecheng → 12个账号 → 12个单元
|
||||
5kechengdeAir → 8个账号 → 8个单元
|
||||
↓
|
||||
|
||||
Step 5: 分发到各机 guardd
|
||||
POST http://100.65.35.28:9090/scheduler/submit (12个P0任务)
|
||||
POST http://100.72.182.121:9090/scheduler/submit (8个P0任务)
|
||||
↓
|
||||
|
||||
Step 6: 各机 scheduler 处理
|
||||
7kecheng:
|
||||
slot0: [P1养号, P1养号, P1养号] (正在执行)
|
||||
slot1: [P1养号, P1养号, P1养号]
|
||||
slot2: [P2采集, P2采集]
|
||||
|
||||
插入 P0 评论包:
|
||||
slot0: [P1养号, ▶️P0评论×4, 恢复P1养号]
|
||||
slot1: [P1养号, ▶️P0评论×4, 恢复P1养号]
|
||||
slot2: [▶️P0评论×4, P2采集, P2采集]
|
||||
↓
|
||||
|
||||
Step 7: 各账号打开视频 → 贴预选评论 → 验证
|
||||
(Worker 只做这一步,不做任何分析)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、要改的文件清单
|
||||
|
||||
### Phase 1:队列改造(核心)
|
||||
|
||||
| 文件 | 改动 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| `guardd/modules/scheduler.py` | 三队列分立 + P0抢插 + P2填空 + 账号互斥表 | 大(~200行) |
|
||||
| `guardd/modules/priority_queue.py` | 现有类不需要大改,加`pop_if()`方法 | 小(~20行) |
|
||||
|
||||
### Phase 2:语料重组
|
||||
|
||||
| 文件 | 改动 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| `corpus/douyin.yaml` | 万能池 + 行业池 分层结构 | 中(重组) |
|
||||
| `scripts/mc/corpus.py` | `get_comment_for_video()` 加行业过滤 + 万能兜底 | 中(~50行) |
|
||||
| `profiles.json` | 各账号加 `industry` 字段 | 手动 |
|
||||
|
||||
### Phase 3:视频分析 + 智能评论
|
||||
|
||||
| 文件 | 改动 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| **新建** `services/video_analyzer.py` | 视频分析+行业分类+选评论 | 中(~150行) |
|
||||
| `services/command_bus.py` | CMD_REGISTRY 加 `smart_comment` 类型 | 小(~20行) |
|
||||
| `routes/ops.py` | 加智能评论端点 | 小(~10行) |
|
||||
|
||||
### Phase 4:指挥台展示(可选)
|
||||
|
||||
| 文件 | 改动 | 工作量 |
|
||||
|:-----|:------|:-------|
|
||||
| `frontend/views/ops-command.js` | 显示三队列 + P0/P1/P2 过滤 | 中(~80行) |
|
||||
|
||||
---
|
||||
|
||||
## 十、回退方案
|
||||
|
||||
| 标签 | commit | 说明 |
|
||||
|:-----|:--------|:------|
|
||||
| `pre-task-architecture` | `7d2b5b14d` | **改架构前的完整备份** |
|
||||
| `stable-ba34e3d56` | `ba34e3d56` | 再往前的稳定版 |
|
||||
| `pre-fix-backup` | 略 | 更早备份 |
|
||||
|
||||
```bash
|
||||
# 回退命令
|
||||
git checkout pre-task-architecture
|
||||
git push origin --force HEAD:main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十一、暂不处理
|
||||
|
||||
| 事项 | 原因 |
|
||||
|:-----|:------|
|
||||
| 三级接力评论 | 需求暂缓 |
|
||||
| 向量模型分类 (ChromaDB) | Phase 2 可选,关键词匹配先行 |
|
||||
| 视频内容深度分析(字幕/画面) | 复杂度高,当前只分析标题+描述 |
|
||||
| AI 生成评论(大模型) | 需配置 API key,后续可加 |
|
||||
| 评论风格跟随热门评论 ("跟风") | 后续可加 |
|
||||
@@ -0,0 +1,74 @@
|
||||
# 20 秒测试片剧本(音频先行 + 对口型 验证用)
|
||||
|
||||
> 目的:验证 P1(音频先行)+ P3(对口型)链路
|
||||
> 结构:**2 个空镜(不说话)+ 2 个角色说话镜头**(口型同步)
|
||||
> 成本:画面约 ¥5~10(可灵)· 对口型 ¥0(走 1800 秒免费额度)· TTS 几分钱
|
||||
|
||||
---
|
||||
|
||||
## 分镜表
|
||||
|
||||
| # | 类型 | 时长(音频先行后会调整) | 画面 | 台词 | 出场人物 |
|
||||
|---|---|---|---|---|---|
|
||||
| shot_01 | 空镜 | 5s | 病房窗外,晨光透过百叶窗在地面投出条纹,窗帘轻微飘动,**画面里没有人** | — | — |
|
||||
| shot_02 | 角色说话 | 5s(按音频调) | 病人半躺在病床上,正面近景,对着镜头说话,表情轻松 | 我住院第三天了,前两天刚做完手术。 | 主角 |
|
||||
| shot_03 | 角色说话 | 5s(按音频调) | 病人微笑看着镜头,稍微侧了一下头 | 说实话,真没想象中那么可怕。 | 主角 |
|
||||
| shot_04 | 空镜 | 5s | 病房走廊尽头,护士推着车经过,画面虚焦 | — | — |
|
||||
|
||||
预计成片:**约 18~20 秒**
|
||||
|
||||
---
|
||||
|
||||
## 演员表配置
|
||||
|
||||
| 代号 | 角色资产 | 音色(voice_id) | 说明 |
|
||||
|---|---|---|---|
|
||||
| 主角 | (选你已建的角色,如「害羞美女患者」或新建) | `longanyang`(阳光大男孩)或按角色性别选 | 音色决定口型用的声音 |
|
||||
|
||||
> 💡 音色建议:`longanyang`(年轻男主)· `longxing_v3`(温婉邻家女)· `longqiang_v3`(御姐)
|
||||
> 完整清单见 `09_ave/docs/cosyvoice_voices.md`
|
||||
|
||||
---
|
||||
|
||||
## 关键要求(对口型的硬条件)
|
||||
|
||||
VideoRetalk 对输入有要求,**我们的参数都能满足**:
|
||||
|
||||
| 要求 | 我们的情况 |
|
||||
|---|---|
|
||||
| 视频:正面近景、人脸清晰 | ✅ 分镜写"正面近景对镜头说话" |
|
||||
| 视频:2~120 秒 | ✅ 单镜头 5s |
|
||||
| 视频:15~60fps、边长 640~2048 | ✅ 我们生成 1080×1920@30fps |
|
||||
| 音频:干净人声(无 BGM/噪音) | ✅ TTS 产物天然纯净 |
|
||||
|
||||
⚠️ **注意**:说话镜头必须是**正面/近景**——大角度侧脸或人脸太小会影响对口型效果。
|
||||
|
||||
---
|
||||
|
||||
## 操作步骤
|
||||
|
||||
```
|
||||
1. 导演台 → 粘贴上面的"分镜表"作为故事/文案(或按它写一段文案)
|
||||
2. 🎭 AI 分析这场戏需要什么 → 演员表绑定角色 + 指定音色
|
||||
3. 生成分镜 → 在卡片里逐镜确认:
|
||||
· shot_02/03 填台词 + 勾「出场人物: 主角」
|
||||
· shot_01/04 台词留空、出场人物不勾(= 空镜)
|
||||
4. 勾选 [✓] 🎙 音频先行 [✓] 🎭 对口型 → 点「🎥 生成成片」
|
||||
5. 完成后 → 「📋 生产记录」→ 🎙 加配音 → 听口型效果
|
||||
```
|
||||
|
||||
## 验证要点(跑完检查这几项)
|
||||
|
||||
- [ ] **音频先行生效**:日志里 shot_02/03 的时长被按台词音频调整过(≠ 原 5s)
|
||||
- [ ] **镜头时长各不相同**:跟台词长短走
|
||||
- [ ] **对口型只作用在 shot_02/03**:日志显示 2 个镜头做了,shot_01/04 跳过
|
||||
- [ ] **口型对上**:播放时人在说那句话,嘴型明显匹配
|
||||
- [ ] **失败兜底**:若对口型失败,日志提示"保留原片段",成片仍完整
|
||||
|
||||
## 成本记录(跑完填这里,用于校准后续估算)
|
||||
|
||||
| 项 | 预估 | 实际 |
|
||||
|---|---|---|
|
||||
| 画面生成(可灵 4 镜头) | ¥5~10 | |
|
||||
| 对口型(约 10 秒) | ¥0(免费额度) | |
|
||||
| TTS | 几分钱 | |
|
||||
@@ -0,0 +1,112 @@
|
||||
# 视频工厂能力现状审计(2026-10-02)
|
||||
|
||||
> 回答「是不是缺东西」—— 逐项列出**能用 / 不能用 / 待接**,以及缺的具体是什么
|
||||
> 基准:三端 `a2b367973`
|
||||
|
||||
---
|
||||
|
||||
## 一、能力层(25 个注册能力)
|
||||
|
||||
**状态**:✅ 可用 19 · 🟡 部分可用 3 · ⚪ 规划中 3
|
||||
|
||||
### 执行器已接入(8 个 —— 流程里能自动跑)
|
||||
|
||||
| 能力 | 用途 | 依赖 | 状态 |
|
||||
|:--|:--|:--|:--|
|
||||
| `storyboard_plan` 分镜规划 | 故事 → 分镜 | LLM(DeepSeek) | ✅ |
|
||||
| `prompt_gen` 提示词生成 | 分镜 → 六模块提示词 | 无 | ✅ |
|
||||
| `text_to_video` 视频生成 | 提示词 → 视频 | **可灵**(已配) | ✅ |
|
||||
| `video_concat` 视频合成 | 片段 → 去AI化 → 拼接 → 混流 | FFmpeg | ✅ |
|
||||
| `tts_generate` 语音合成 | 文本 → 音频 | **阿里百炼**(已配) | ✅ |
|
||||
| `material_search` 素材搜索 | 关键词 → 素材 | **Pexels**(已配) | ✅ |
|
||||
| `music_select` BGM 选择 | 风格 → BGM | 本地音乐库 | ✅ |
|
||||
| `subtitle` 字幕生成 | 台词 → ASS 字幕 | FFmpeg | ✅ |
|
||||
|
||||
### 注册但执行器未接入(流程中**明确跳过并说明原因**,不会静默失败)
|
||||
|
||||
`script_generate`(映射已连但实现待补)· `image_to_video` 图生视频 · `text_to_image` 文生图 ·
|
||||
`person_swap` 人物置换 · `lipsync` 对口型 · `vfx_apply` 特效 · `comfyui_workflow` · `character_3d`
|
||||
|
||||
---
|
||||
|
||||
## 二、模型与供应商(配置现状)
|
||||
|
||||
| 供应商 | 用途 | 配置 | 状态 |
|
||||
|:--|:--|:--|:--|
|
||||
| **可灵 Kling** | 视频生成 / 图片生成 | ✅ 已配 | **视频 ✅ 可用**;**图片 ⚠️ 额度不足**(需单独充值) |
|
||||
| **阿里百炼** | TTS / 人物置换 | ✅ 已配(已充值) | ✅ 可用 |
|
||||
| **DeepSeek** | 文本(剧本/分镜/评论) | ✅ 已配 | ✅ 可用 |
|
||||
| **Pexels** | 素材搜索 | ✅ 已配 | ✅ 可用 |
|
||||
| 火山方舟(即梦) | 图片/视频备选引擎 | ⚪ 未配 / 模型名待确认 | ⚪ 待接 |
|
||||
| fal.ai | 对口型(Kling Lipsync) | ❌ 未配 | ⚪ 待接 |
|
||||
|
||||
---
|
||||
|
||||
## 三、资产库(11 类,全部可用)
|
||||
|
||||
角色 · 场景 · 真实场地 · 产品 · 道具 · 服装 · 音色 · BGM · 音效 · 特效预设 · 素材
|
||||
|
||||
**每类都具备**:搜索/筛选/排序 · 卡片/表格视图 · 编辑字段(**含下拉建议**)· 上传参考图 · **🎨 AI 生成参考图** · 删除
|
||||
|
||||
**角色生成器**(专门页面):**10 层 61 字段**(44 个下拉)+ 5 视角 + 引擎选择
|
||||
|
||||
---
|
||||
|
||||
## 四、导演系统(已接 2 个)
|
||||
|
||||
| 导演 | 类型 | 状态 |
|
||||
|:--|:--|:--|
|
||||
| `legacy_scene_planner` | 本地分镜 | ✅ 可用 |
|
||||
| `storyboard_v52`(AI Storyboard Director v5.2) | 技能型 | ✅ 可用(技能文档已入库) |
|
||||
| ?用户提到的**另 2 种** | — | ⏳ **需名称 / 来源** |
|
||||
|
||||
---
|
||||
|
||||
## 五、缺什么(明确清单)
|
||||
|
||||
| # | 缺的东西 | 影响 | 补法 |
|
||||
|:--|:--|:--|:--|
|
||||
| 1 | **可灵「图片生成」额度** | 定妆照 / 资产参考图生成不可用(视频额度不通用) | 可灵开放平台**单独充值图片生成** |
|
||||
| 2 | **`fal.api_key`** | 口型同步(`lipsync`)不可用 | 申请 fal.ai key → 🔑 API 配置 |
|
||||
| 3 | **另 2 个导演系统** | 只能选 2 种分镜风格 | 提供名称/来源(接入约 3 步) |
|
||||
| 4 | **人脸表情精细控制** | 目前只能靠提示词描述 | 接 **ComfyUI**(表情/风格精细)或等可灵支持 |
|
||||
| 5 | `script_generate` 实现 | 流程里「剧本改编」节点会跳过 | 补实现(约 20 行,复用 LLM) |
|
||||
| 6 | 火山方舟(即梦) | 少一个图片/视频备选引擎 | 控制台确认模型名后接入 |
|
||||
| 7 | `person_swap` 参数接入 | 「人物置换」流程节点会跳过 | 补实现(API 与代码已存在) |
|
||||
|
||||
---
|
||||
|
||||
## 六、现在就能跑的(已验证)
|
||||
|
||||
### ✅ 完整可用 ①:口播视频(素材版,**零生成费用**)
|
||||
```
|
||||
脚本 → 素材(Pexels) → TTS(阿里) → 字幕 → 混流成片
|
||||
```
|
||||
**实测**:20 秒出片 · 3.21MB / 12.46 秒 / 1080x1920 · **含音轨 + 字幕烧录** ✓
|
||||
|
||||
### ✅ 完整可用 ②:分镜驱动视频(可灵版,**按镜头计费**)
|
||||
```
|
||||
脚本 → 分镜(v5.2) → 可灵逐镜头生成 → 去AI化 → 拼接 → 混流
|
||||
```
|
||||
**实测**:3 镜头 **1.9 分钟**(并发生成)· 成片 3.2MB ✓
|
||||
|
||||
### ✅ 可用:流程画布
|
||||
6 个模板 + 节点状态徽章 + 产物预览(视频可播)+ 🔄 重做 + ▶️ 从此起跑 + ⏹ 停止 + **生成前费用确认**
|
||||
|
||||
### ✅ 可用:分镜透明化
|
||||
「🎬 预览生成方案」→ 逐镜头看 **提示词 / 能力 / 引擎 / 参数**(**零费用**)
|
||||
|
||||
### ✅ 可用:通知与产物中心
|
||||
任务完成右上角通知 + 「📋 生产记录」页可播全部产物
|
||||
|
||||
---
|
||||
|
||||
## 七、建议优先级(我的判断)
|
||||
|
||||
| 优先级 | 事项 | 理由 |
|
||||
|:--|:--|:--|
|
||||
| 🔴 高 | **可灵图片充值** | 角色/场景参考图是"资产先行"的前提,没有参考图流程就不完整 |
|
||||
| 🟡 中 | 另 2 个导演系统接入 | 分镜质量多样性(你明确提过) |
|
||||
| 🟡 中 | `script_generate` + `person_swap` 实现 | 两个流程节点目前会跳过(代码量小) |
|
||||
| ⚪ 低 | fal.ai 口型 / ComfyUI 表情 | 精细控制,主流程跑顺后再做 |
|
||||
| ⚪ 低 | 火山方舟即梦 | 备选引擎,可灵够用时不急 |
|
||||
@@ -0,0 +1,526 @@
|
||||
# 视频工厂 · 总体架构 v2.0(唯一权威版)
|
||||
|
||||
> 创建:2026-10-01 | 状态:**讨论中,待确认后动手**
|
||||
> 本文档**替代**此前的 `VIDEO_FACTORY_FRAMEWORK.md` / `VIDEO_FACTORY_ARCHITECTURE.md` / `DCS_VIDEO_FACTORY_PLAN.md`(已归档,见文末)
|
||||
> 原则:**流程是主角,能力是零件,资产是原料** —— 三者是引用关系,不是平级菜单
|
||||
|
||||
---
|
||||
|
||||
## 〇、一句话
|
||||
|
||||
> 我进「流程」做一件事(口播 / 短剧 / 导演创作…)→ 流程由若干「节点」串成 → 每个节点是一个「能力」(可换、可配、可调模型)→ 执行后**每一步都能看结果、能改、能重做** → 产物出片。
|
||||
> 「资产底座」(角色 / 场景 / 道具 / 产品 / 音色…)是所有流程共用的原料库。
|
||||
|
||||
---
|
||||
|
||||
## 一、三层模型(核心,先看这张)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 【流程】Process / Template —— 我要做的一件事 │
|
||||
│ 导演创作 · 口播 · 卡点视频 · 角色叙事 · 数字人口播 │
|
||||
│ 口播+混剪 · 短剧创作 · 人物置换 · …(可扩展、可自建) │
|
||||
│ │
|
||||
│ 流程 = 节点串(每个节点 = 一个能力 + 该节点的配置) │
|
||||
│ 可预制(原来的 6 条)· 可自建(拖节点拼)· 节点可替换 │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│ 节点引用能力
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 【能力】Capability —— 解决"一个环节"的最小可执行单元 │
|
||||
│ 语音合成(文字→音频)· 文生图(文字→图片)· 图生视频 │
|
||||
│ 音色提炼(音频→音色)· 去AI化 · 拼接/变速/转场 · 字幕 │
|
||||
│ 分镜规划 · 提示词生成 · 审核门 · 导演编排(元能力)… │
|
||||
│ │
|
||||
│ 每个能力都有:默认设置 + 可调整参数 + **可选不同大模型** │
|
||||
│ 同一个环节可以有多个能力可选(要声音:调库音色 / AI提炼音色 /│
|
||||
│ 文字直转),节点上可**替换** │
|
||||
│ │
|
||||
│ 能力分两类用途: │
|
||||
│ ① 产出型(生成资产):角色生成 / 背景生成 / 音色提炼 … │
|
||||
│ ② 处理型(流程节点):TTS / 生图 / 生视频 / 合成 … │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│ 产物落入 / 被引用
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 【资产底座】Assets —— 共用原料库(所有流程共享) │
|
||||
│ 角色 · 场景/背景 · 道具 · 产品 · 服装 · 音色 · BGM · 音效 │
|
||||
│ 特效预设 · 风格 · … │
|
||||
│ (字段与分类:**待你给出**,见第九节) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**关键结论**:
|
||||
- **导演创作 = 一条流程**(不是独立板块)
|
||||
- **人物置换 = 一条流程**(选人→换人),不属于资产
|
||||
- **工作流 = 流程本身**(画布是流程的编辑/查看形式)
|
||||
- **资产 ≠ 能力**:资产是"原料"(角色图、音色文件),能力是"做事的手"(生成、合成、转换)
|
||||
|
||||
---
|
||||
|
||||
## 二、前端信息架构(一二级菜单)
|
||||
|
||||
```
|
||||
🎬 视频工厂 ← 一级:大模块
|
||||
│
|
||||
├─ 📦 资源库 ← 二级:基础底座(原料)
|
||||
│ ├─ 🧑 角色库 角色筛选/生成/引用
|
||||
│ ├─ 🏞️ 场景库 AI 生成场景
|
||||
│ ├─ 🏙️ 真实场地库 实拍参考(多角度图 + 视频)
|
||||
│ ├─ 🧰 道具库
|
||||
│ ├─ 📦 产品库 含 must_keep 必保特征
|
||||
│ ├─ 👗 服装库
|
||||
│ ├─ 🔊 音色库 音色样本 + 音色 ID(可从音频提炼)
|
||||
│ ├─ 🎵 BGM 库
|
||||
│ ├─ 💥 音效库
|
||||
│ └─ ✨ 特效预设库 子弹时间/环绕/慢动作(参数模板)
|
||||
│
|
||||
├─ 🎞️ 流程 ← 二级:做事入口(模板)
|
||||
│ ├─ 🎬 导演创作 ★ 剧本→分镜→逐镜头配置→生成→成片
|
||||
│ ├─ 🎭 短剧创作 故事→脚本→角色→分镜→场景→配音→字幕→成片(原有,12 节点)
|
||||
│ ├─ 🎙️ 基础口播 脚本→TTS→素材→BGM→输出(原有)
|
||||
│ ├─ 🥁 卡点视频 BGM→卡点风格→审核→输出(原有)
|
||||
│ ├─ 📖 角色叙事 剧本→改编→角色→策略→生成→旁白→审核→输出(原有)
|
||||
│ ├─ 👤 数字人口播 文案→人声→数字人角色→数字人视频(原有)
|
||||
│ ├─ 🎞️ 口播+混剪 口播脚本→人声→混合风格→混合视频(原有)
|
||||
│ ├─ 🔄 人物置换 选源人物→选目标人物→换人→出片
|
||||
│ └─ ➕ 新建流程 从能力库拖节点自建
|
||||
│
|
||||
├─ 🧩 能力中心 ← 二级:能力配置
|
||||
│ ├─ ⚙️ 能力配置 25 能力 × 供应商 × 模型 × 参数默认值
|
||||
│ ├─ 🔌 供应商管理 各能力可选哪些供应商 + 密钥状态
|
||||
│ └─ 🧪 能力试跑 单独测某个能力(不跑整条流程)
|
||||
│
|
||||
└─ 📊 运营 ← 二级:辅助
|
||||
├─ 📋 生产记录 每次跑流程的记录(产物/耗时/状态)
|
||||
├─ 💰 费用统计 按能力/供应商/项目统计
|
||||
├─ 🕐 历史操作 谁在什么时候改了什么
|
||||
└─ ⚙️ 视频工厂设置 全局默认(去AI化参数/输出规格…)
|
||||
```
|
||||
|
||||
**设计原则**:
|
||||
- **一级只有 4 个**:资源库(原料)· 流程(做事)· 能力中心(零件)· 运营(辅助)
|
||||
- **二级是具体库/流程**(可继续扩)
|
||||
- 你**日常只用「流程」**(选一条 → 画布 → 执行);资源库/能力中心是**配置时**才去
|
||||
|
||||
### 2.1 🧑 角色库细化(重点,按你的要求)
|
||||
|
||||
**列表页**
|
||||
```
|
||||
🔍 [搜索名字/标签] 筛选:类型▾ 用途▾ 项目▾ 标签▾ 有音色☐ 有LoRA☐ 排序:最近使用▾
|
||||
────────────────────────────────────────────────────────────
|
||||
卡片视图(默认):
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ [缩略图] │ │ [缩略图] │ │ [缩略图] │
|
||||
│ 阿远 │ │ 小漫 │ │ 患者A │
|
||||
│ 真人·主角│ │ 动漫·配角│ │ 真人·主角│
|
||||
│ 用过 12 次│ │ 用过 3 次│ │ 用过 8 次│
|
||||
└─────────┘ └─────────┘ └─────────┘
|
||||
表格视图:名字 | 类型 | 用途 | 音色 | 参考图数 | 使用次数 | 更新时间
|
||||
批量操作:☑多选 → 加标签 / 导出 / 删除
|
||||
```
|
||||
|
||||
**角色详情页**
|
||||
```
|
||||
[基本信息] 名字 · 类型(真人/动漫/3D) · 用途(主角/配角/群演) · 项目 · 标签 · 一致性种子
|
||||
[参考图] 正面 / 侧面 / 背面 / 全身 / 多角度缩略图(可上传、可生成、可删)
|
||||
[服装变体] 服装A(图) · 服装B(图) …(每套可切换)
|
||||
[音色] voice_sample.mp3 ▶ + 音色 ID(可从「音色库」选,或现场提炼)
|
||||
[使用记录] 被哪些项目/流程用过(可跳转)
|
||||
[操作] ✏️ 编辑 · 🎨 重新生成参考图 · 📤 导出 · 🔒 锁定(流程中不被覆盖)
|
||||
```
|
||||
|
||||
**生成入口**("基础能力"的体现)
|
||||
```
|
||||
➕ 新建角色 → ① 填描述(性别/年龄/外形/性格)
|
||||
→ ② 调「文生图」能力(Kling Grid Method 出 6 张候选)
|
||||
→ ③ 选 1 张 → ④ 生成多角度(图生图变体)
|
||||
→ ⑤ 补音色(录音上传 / TTS 合成 / 从音色库选)
|
||||
→ ⑥ 确认入库
|
||||
📤 上传已有参考图(跳过生成)
|
||||
```
|
||||
|
||||
**在流程里怎么用**(引用机制)
|
||||
```
|
||||
流程节点「角色」字段 → 点击 → 弹【角色选择器】(带上面的筛选器)
|
||||
选中 → 节点保存 character_id
|
||||
→ 执行器按 ID 从资源库取:参考图路径 + 音色文件 → 注入 API 请求
|
||||
分镜级:每个镜头可指定不同角色(shot.character_id)
|
||||
```
|
||||
|
||||
### 2.2 其他资源库(同结构,字段按 DCS 文档第五节)
|
||||
|
||||
| 库 | 字段要点 |
|
||||
|:--|:--|
|
||||
| **场景库** | id / 名字 / 拓扑结构 / 空间锚点 / 光源 / 材质 / 参考图 + 参考视频 |
|
||||
| **真实场地库** | 多角度图(wide/detail/light)+ 实拍视频 + 备注 |
|
||||
| **道具库** | id / 结构 / 比例 / 可见面 / 持用状态 / 新旧状态 / 参考图 |
|
||||
| **产品库** | id / 名字 / **category** / **must_keep[](必保特征)** / 参考图(front/angle/detail/in_hand)/ 一致性种子 |
|
||||
| **服装库** | 关联角色 / 正面背面图 / 材质 · 可挂到角色的"服装变体" |
|
||||
| **音色库** | id / 名字 / 样本音频 / 来源(官方库/AI提炼/录制)/ owned_by |
|
||||
| **BGM 库 / 音效库** | 标签(情绪/节奏)· 时长 · 版权 |
|
||||
| **特效预设库** | 类型(子弹时间/环绕/慢动作/焦点锁定)· 参数模板 · 适用供应商 |
|
||||
|
||||
**统一能力**(每个库都有):
|
||||
```
|
||||
🔍 搜索 + 筛选 + 排序 📤 上传 ➕ 生成(调对应产出型能力)
|
||||
✏️ 编辑 🗑 删除 🔗 查看被哪些流程引用
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、流程清单与现状(诚实标注)
|
||||
|
||||
| # | 流程 | 节点链 | 现状 | 待修 |
|
||||
|:--|:--|:--|:--|:--|
|
||||
| 1 | **导演创作** | 剧本输入 → 剧本创作(导演系统) → 分镜配置 → 编排执行 → 结果挑选 | 🟡 可跑通(引擎已接),但缺"每步审视/纠正" | 补:分镜后的逐镜头配置面板、执行前预览 |
|
||||
| 2 | 基础口播 | 脚本 → TTS → 素材搜索 → BGM → 视频输出 | ❌ **模板在,执行器空转** | 通电(接能力)+ 逐节点审视 |
|
||||
| 3 | 卡点视频 | BGM导入 → 卡点风格 → 质量审核 → 视频输出 | ❌ 同上 | 同上 |
|
||||
| 4 | 角色叙事 | 剧本→改编→角色→策略→Kling生成→旁白TTS→审核→输出 | ❌ 同上 | 同上 |
|
||||
| 5 | 数字人口播 | 文案 → 人声合成 → 数字人角色 → 数字人视频 | ❌ 同上(且数字人能力未接) | 同上 + 接数字人供应商 |
|
||||
| 6 | 口播+混剪 | 口播脚本 → 人声合成 → 混合风格 → 混合视频 | ❌ 同上 | 同上 |
|
||||
| 7 | 短剧创作 | 12 节点(故事→…→成片) | ❌ 同上(但模板结构完整) | 同上 |
|
||||
| 8 | 人物置换 | 选源人物 → 选目标人物 → 换人 → 出片 | 🟡 能力已接(百炼 wan2.2),未包成流程 | 包成流程 + 界面 |
|
||||
|
||||
> **现状真相**:`workflows.py` 的 6 条模板**结构完整、节点定义齐全**,但 `WorkflowRunner._execute()` **只做拓扑排序然后标记 completed**,**没有任何节点真的执行** —— 这是"点了不跑"的根因。
|
||||
|
||||
---
|
||||
|
||||
## 四、节点与配置体系(你强调的重点)
|
||||
|
||||
### 4.1 节点 = 能力 + 配置 + 上下游
|
||||
|
||||
```yaml
|
||||
node:
|
||||
id: n3
|
||||
capability_id: tts_generate # 用哪个能力(可替换!)
|
||||
provider: volcano # 该能力的供应商(默认可改)
|
||||
model: CosyVoice-v2 # 大模型(默认可改)
|
||||
params: # 该节点所有可配置项(默认值预填,全部可改)
|
||||
text: "{{n1.script}}" # 上游节点输出 → 本节点输入(数据流)
|
||||
emotion: warm
|
||||
speed: 1.0
|
||||
outputs: { audio_path: "var.vo" } # 本节点输出 → 供下游引用
|
||||
```
|
||||
|
||||
### 4.2 配置的三个来源(全部暴露给你)
|
||||
|
||||
```
|
||||
① 能力默认值(出厂设置) ← 打开节点就能看到
|
||||
② 流程级默认(这条流程整体改) ← 比如"这条流程统一用 9:16 竖屏"
|
||||
③ 节点级覆盖(本次执行改) ← 只改这一个节点
|
||||
```
|
||||
|
||||
**UI 规则(你要求的"能改的地方都要能选")**:
|
||||
- 每个节点的**所有可配置项都列出来**(默认值预填)
|
||||
- 显示**来源标记**(默认 / 流程 / 节点),改了就在当前层生效
|
||||
- 提供「恢复默认」
|
||||
- **供应商 + 模型**是独立下拉(每个能力可选多家 → 每个供应商可选自家模型)
|
||||
|
||||
### 4.3 节点可替换("同一个需求找不同能力")
|
||||
|
||||
以"要一段声音"为例,节点里可以选:
|
||||
```
|
||||
▸ 能力 A:TTS 合成 输入文字 → 出音频(默认路径)
|
||||
▸ 能力 B:音色提炼 + 合成 先给一段参考音频 → 提炼音色 → 再合成
|
||||
▸ 能力 C:从资产库调音色 选一个已有音色 → 合成
|
||||
```
|
||||
→ 节点上有个「🔄 替换能力」,选不同能力,参数面板随之切换。
|
||||
|
||||
---
|
||||
|
||||
## 五、执行与审查机制 ★ 你最关心的部分
|
||||
|
||||
### 5.1 两种模式(可随时切换)
|
||||
|
||||
```
|
||||
▸ 自动模式:点「▶▶ 全部执行(默认配置)」→ 一条龙跑完 → 出成品 → 你在成品上审
|
||||
(前提:默认配置必须能走通 —— 我会保证并逐条验证)
|
||||
|
||||
▸ 逐步模式:点「▶ 执行本节点」→ 出结果 → 你审视 → 改 or 继续
|
||||
(可设"断点":跑到某节点自动停)
|
||||
```
|
||||
|
||||
### 5.2 每个节点的结果展示 + 纠正(核心)
|
||||
|
||||
| 节点类型 | 产物形态 | 你怎么审视/纠正 |
|
||||
|:--|:--|:--|
|
||||
| **文本类**(剧本/提示词/台词/字幕) | 原文显示在节点里 | **直接编辑**;不满意可「🔄 重生成」(可加"修改意见"再生成) |
|
||||
| **音频类**(配音/BGM) | 内嵌播放器 | 听;不满意 → 改参数(音色/语速/情绪)→「🔄 重做」 |
|
||||
| **图片类**(参考图/分镜图) | 缩略图预览 | 看;不满意 → 改提示词/换模型 →「🔄 重做」;可「选一张」 |
|
||||
| **视频类**(镜头片段) | 内嵌播放器 | 看;不满意 → 改提示词/换镜头 →「🔄 重做」;可「换一版」多出几条挑 |
|
||||
| **决策类**(策略/风格/审核门) | 选项列表 | 直接改选项;审核门可"通过/打回" |
|
||||
|
||||
**统一交互**:
|
||||
```
|
||||
节点卡片
|
||||
┌───────────────────────────────┐
|
||||
│ 🔊 TTS 合成 [执行] [重做] │
|
||||
│ ├ 供应商 [火山▾] 模型 [Cosy▾] │
|
||||
│ ├ 情绪 [warm▾] 语速 [1.0] │
|
||||
│ ├ 输入: ← 脚本节点"口播稿" │
|
||||
│ └ 结果: ▶ [播放音频] 3.2s ✅ │
|
||||
└───────────────────────────────┘
|
||||
```
|
||||
- **未执行的节点**:灰显 + 「▶ 执行」
|
||||
- **已执行的节点**:绿标 + 产物预览 + 「🔄 重做」(改配置后重跑,下游自动标记"需重跑")
|
||||
- **全局**:可「从某节点起重跑下游」
|
||||
|
||||
### 5.3 导演创作流程的审视点(按你的描述)
|
||||
|
||||
```
|
||||
① 输入剧本/小说/思路 → 你写(或从资产/素材带入)
|
||||
② 剧本创作(导演系统产出分镜) → **审视**:看分镜表,逐镜头改台词/画面/镜头契约
|
||||
③ 逐镜头配置(选特效/角度/模型)→ **审视**:每个镜头有默认配置,你只改不满意的
|
||||
④ 编排执行(生成→去AI化→拼接)→ **审视**:每条片段可看/可重做
|
||||
⑤ 结果挑选 / 调整 → 选终版 or 重跑某镜头
|
||||
```
|
||||
|
||||
> 你的原话:"每个镜头我不需要手动配,但我要去审视一下现在配的结果;中间要修改就修改,不修改就用默认" ✓ **就是这个设计**。
|
||||
|
||||
---
|
||||
|
||||
## 六、后端架构
|
||||
|
||||
```
|
||||
┌── L1 能力层(Capability Registry)── ✅ 已有(25 个),需扩展
|
||||
│ capabilities.yaml + 加载器 + /api/ave/capabilities
|
||||
│ 每个能力:输入输出契约 / 参数 schema / 供应商[] / 默认值 / 实现位置
|
||||
│
|
||||
├── L2 节点层(Node)── 🟡 部分有(workflows.py 的 15 种节点定义)
|
||||
│ Node = 能力引用 + 参数覆盖 + 上下游映射 + 状态(未跑/跑完/失败)
|
||||
│
|
||||
├── L3 流程层(Template/Process)── 🟡 6 条模板已有,需扩展(+导演创作/人物置换)
|
||||
│ Template = 节点 + 连线 + 流程级默认 + 元信息
|
||||
│
|
||||
├── L4 执行器(Runner)── ❌ **空转,必须重做**
|
||||
│ 拓扑执行 → 逐节点调能力 → 产物落地 → 状态回写 → 断点/续跑 → 重跑上游
|
||||
│ (这是"工作流能真跑"的核心)
|
||||
│
|
||||
├── L5 资产层(Assets)── ❌ **要重建**(旧 character_registry 只覆盖角色且字段旧)
|
||||
│ 按你的分类建库 + 生成入口 + 引用机制
|
||||
│
|
||||
└── L6 接口/UI ── 前端页面 + FastAPI 路由
|
||||
```
|
||||
|
||||
**执行通道**:
|
||||
- 轻任务(解析/规划/合成)→ 本地线程
|
||||
- 长任务(可灵生成 / ComfyUI)→ 走 guardd 任务(有任务面板、可停、可重试)
|
||||
|
||||
---
|
||||
|
||||
## 七、与现有代码的映射(哪些复用、哪些重做)
|
||||
|
||||
| 现有资产 | 处置 |
|
||||
|:--|:--|
|
||||
| `capabilities.yaml`(25 能力) | **复用**(L1 底座)→ 按需扩充 |
|
||||
| `workflows.py` 的 6 模板 + 15 节点定义 | **复用结构**(L2/L3)→ 重做执行器 |
|
||||
| `workflow.js` 画布 UI(485 行) | **复用**(拖拽 + 节点配置面板)→ 补"产物预览 + 重做" |
|
||||
| `scheduler.py` / `scorer.py`(模板引擎) | 参考(筛选模板用) |
|
||||
| `composer/*`(去AI化/拼接/变速/转场) | **复用**为能力实现 |
|
||||
| `capabilities/kling_video.py`(可灵) | **复用**为能力实现 |
|
||||
| `character_registry/`(旧角色库) | **改造**:字段按你的要求重建;补场景/道具/产品 |
|
||||
| `character_sheet.py`(定妆照) | **复用**为产出型能力 |
|
||||
| `person_swap/`(百炼换人) | **复用** → 包成"人物置换"流程 |
|
||||
| `story_director/` + `directors/` | **复用**(导演流程的②环节) |
|
||||
| `schemas.py`(统一分镜) | **复用**(导演流程的数据契约) |
|
||||
| `video_factory.py`(CLI 老流程) | **改造**:拆成能力 + 流程模板 |
|
||||
| `workflows.py` 的 Runner | **重写**(执行器) |
|
||||
|
||||
---
|
||||
|
||||
## 八、改造计划与**实际进度**(每阶段以"能点、能看结果、能改"验收)
|
||||
|
||||
| 阶段 | 内容 | 状态 |
|
||||
|:--|:--|:--|
|
||||
| **P1 架构对齐** | 本文档定稿 + 旧文档归档 + 菜单按新结构重组 | ✅ **已完成**(`4.10.0`:菜单 4 组 + 20 占位页) |
|
||||
| **P2 执行器** | 重写 `WorkflowRunner`:真执行 + 逐节点产物 + 状态 + 重做 | ⏳ **待决策**(编排层 A/B)· 前置调研已完成(15 节点映射表见附录 D) |
|
||||
| **P3 节点配置面板** | 每节点全配置暴露(默认值 + 供应商 + 模型 + 参数)+ 替换能力 | ⏳ 属 P2 范围(依赖执行器) |
|
||||
| **P4 导演创作补全** | 统一分镜 Schema + 导演可切换 + 分镜编辑 + 一键出片 | ✅ **已完成**(`2607a973b`→`304d7e30e`;实测 3 镜头 **1.9 分钟**出片 / **3.2MB**) |
|
||||
| **P5 资产底座** | 按分类建库(角色/场景/道具/产品/音色…)+ 上传/编辑 | ✅ **主体完成**(`2b866c23a` `eebeabcbc` `1aa4651f6`:**10 类资产** + 通用组件;**生成入口待图片模型名确认**) |
|
||||
| **P6 流程补齐** | 人物置换 + 6 条老流程逐条通电验证 | ⏳ **待 P2** |
|
||||
| **P7 辅助** | 生产记录 + 费用 + 设置 | ✅ **已完成**(生产记录含磁盘持久化 · 费用统计含可灵估算+AI token · 设置含去AI化/输出/渲染) |
|
||||
| — | **S1 能力注册表**(25 能力 + 能力库页 + 供应商管理 + 能力试跑) | ✅ **已完成**(`952b39970` `4c6caf2f3`:39 个供应商,密钥状态 18/27 已配) |
|
||||
| — | **S2 导演创作**(v5.2 技能入库 + 六模块提示词 + 交付状态三级 + Webhook 验签) | ✅ **已完成**(`82a63f4b3` 起) |
|
||||
|
||||
**当前剩余**:**P2(编排通电)** —— 等编排层决策(① 复用 `workflows.py` / ② 装 n8n)后即可开工;「历史操作」页仍为占位(低优先级)。
|
||||
|
||||
---
|
||||
|
||||
## 九、待你确认(关键,定了才动手)
|
||||
|
||||
1. **资产分类的字段**(你说"我给的分类都没有" —— 请再给一次):
|
||||
- 角色要什么字段?(正面照/多角度/服装变体/表情/音色/年龄/身高…)
|
||||
- 场景/道具/产品各要什么?**产品 vs 道具**怎么区分?
|
||||
- 分类方式(按项目?按类型真人/动漫?按用途主角/配角?)
|
||||
2. **菜单是否按本文第二节重组**?(流程/能力/资产/辅助 四大块)
|
||||
3. **执行模式默认哪个**?(逐步 or 自动;我建议默认"逐步",你熟了可切自动)
|
||||
4. **阶段优先级**:P2(执行器通电)和 P5(资产重建)你想先做哪个?
|
||||
|
||||
---
|
||||
|
||||
## 附录 C|与《导演创作系统说明书 v2.0》的对齐(**重要基准**)
|
||||
|
||||
> 用户原始设计文档:`~/Documents/导演创作系统(Director.docx`(829 行,v2.0,2026-10-01 更新)
|
||||
> 本节把文档的**逻辑架构**映射到**现有看板**,明确哪些复用、哪些要补 —— **以文档为基准,不再自由发挥**
|
||||
|
||||
### C.1 文档的五层架构 → 我们的实现
|
||||
|
||||
| 文档层 | 文档原方案 | 我们的现状 | 处置 |
|
||||
|:--|:--|:--|:--|
|
||||
| **层0 导演控制台** | Appsmith(Docker :80);页面:分镜编辑/资产库/3D角色/特效库/任务状态/成片预览/参数模板/系统设置 | **Dashboard(:9988)** 已有:导演创作 / 能力库 / 工作流 / 生产记录 / 费用 | ✅ **复用现有看板**(功能更全,不必新装 Appsmith) |
|
||||
| **层1 导演层** | 任一导演系统输出统一 Schema | `directors/`(v5.2 + legacy)+ `schemas.py`(14 模型) | ✅ 已完成 |
|
||||
| **层2 编排层** | n8n(Docker :5678):Webhook→读Schema→循环shot→Switch按type分发→等完成→下载→FFmpeg→回调 | `workflows.py`(6 模板 + 15 节点 + 画布)**但执行器空转** | ⚠️ **二选一**(见 C.3) |
|
||||
| **层3 能力层** | 远端 API,8 大类每家多供应商(TTS/口播/动作/背景/ComfyUI/3D/特效) | `capabilities.yaml`(25 能力,含多供应商)+ 可灵/video 引擎 | ✅ 骨架已备,供应商待补 |
|
||||
| **层4 合成层** | FFmpeg:去AI化 → 帧混合 → 拼接 | `composer/`(de_ai.py + pipeline.py) | ✅ 已完成(**注意**:文档写 `-crf 18`,我们改为 `23` 以控体积) |
|
||||
|
||||
### C.2 资产库规范(文档第五节 → 落地基准)
|
||||
|
||||
```
|
||||
assets/
|
||||
├── characters/ 角色 2D — reference.png / _side.png / _full.png / lora.safetensors / voice_sample.mp3 / meta.json
|
||||
├── characters_3d/ 角色 3D — model.glb / model.fbx / texture/ / rig_info.json / meta.json
|
||||
├── locations/ 场景(AI生成)— reference.png / reference_video.mp4 / meta.json
|
||||
├── real_locations/ 真实场地 — reference_wide.jpg / _detail.jpg / _light.jpg / reference_video.mp4 / meta.json
|
||||
├── products/ 产品 — reference_front.png / _angle.png / _detail.png / _in_hand.png / meta.json
|
||||
├── props/ 道具(结构同 products)
|
||||
├── bgm/ sfx/ 音频资产
|
||||
└── vfx_presets/ 特效预设 — bullet_time.yaml / orbit.yaml / slow_motion.yaml
|
||||
```
|
||||
|
||||
**元数据规范(文档原文)**:
|
||||
- **产品**:`id / name / category / must_keep[](必保特征,如"瓶身标签文字""瓶盖金色边框")/ reference_images{front,angle,detail,in_hand} / consistency_seed`
|
||||
- **3D 角色**:`id / name / source_tool / model_formats[] / rigged / rig_type / reference_2d_id / consistency_seed / created_at`
|
||||
- **引用方式**:分镜 Schema 通过 `character_id / character_3d_id / location_id / product_id / props[] / bgm_id / sfx.id / vfx.vfx_id` 引用 → 执行器按 ID 从资产库取文件注入 API
|
||||
|
||||
**我们现状**:只有 `character_registry/registry.yaml`(14 角色;字段:description/appearance/personality/voice_style/art_style/bgm_style/reference_images/prompt_template)→ **需按上述结构重建**
|
||||
|
||||
### C.3 两个关键决策(等你定)
|
||||
|
||||
**决策 1:编排层用哪个?**
|
||||
| 方案 | 说明 | 优劣 |
|
||||
|:--|:--|:--|
|
||||
| **A. 复用现有 workflows.py + 重写执行器** | 已有 6 模板 + 15 节点 + 画布 UI + 节点配置面板;只需把"假执行"换成真执行 | ✅ 不用新装服务 · ✅ 与看板一体 · ⚠️ 执行器要自己写 |
|
||||
| **B. 按文档装 n8n(Docker :5678)** | 照文档原方案,n8n 做编排,看板只当控制台 | ✅ n8n 成熟(可视化/重试/日志) · ⚠️ 要装 Docker 服务 + 学 n8n · ⚠️ 与看板两套系统 |
|
||||
| **C. 混合** | 看板做控制台 + 流程配置,轻任务本地执行;把"逐镜头生成"这段交给 n8n | 复杂度高 |
|
||||
|
||||
**决策 2:控制台用哪个?**
|
||||
- **A. 现有 Dashboard(:9988)** ← 建议(已能跑、功能多、Tailscale 可访问)
|
||||
- B. 按文档装 Appsmith(:80)—— 要重搭所有页面
|
||||
|
||||
### C.4 文档「导演操作流程 12 步」→ 现状对照
|
||||
|
||||
| # | 文档步骤 | 现有看板 | 状态 |
|
||||
|:--|:--|:--|:--|
|
||||
| 1 | 打开浏览器 | :9988 | ✅ |
|
||||
| 2 | 分镜编辑页输入故事大纲 | 视频工厂 → 🎬 导演创作 | ✅ |
|
||||
| 3 | **选内容类型**(产品广告/个人日记/场景短剧) | — | ❌ **缺** |
|
||||
| 4 | **选角色**(2D 参考图 / 3D 绑定模型) | — (Schema 有字段,UI 未暴露) | ❌ **缺** |
|
||||
| 5 | **选场景/场地/产品** | — | ❌ **缺** |
|
||||
| 6 | 点击生成分镜 | 🚀 生成分镜 | ✅ |
|
||||
| 7 | 逐条检查/修改 + **添加特效**(子弹时间/环绕运镜) | 能改文字;**特效面板无** | 🟡 部分 |
|
||||
| 8 | 提交任务 | 🎥 生成成片 | ✅ |
|
||||
| 9 | 编排层调各 API 生成片段 | 我们的流水线(逐镜头→可灵) | ✅ |
|
||||
| 10 | FFmpeg 去AI化 + 拼接 | composer(已修 + 体积优化) | ✅ |
|
||||
| 11 | 刷新预览成片 | 进度条 + 成片路径 | ✅ |
|
||||
| 12 | 不满意 → **改对应镜头参数** → 重试单条 | 有单镜头重生成,但**不是"改参数重试"** | 🟡 部分 |
|
||||
|
||||
**缺的 4 项**:③内容类型 ④选角色 ⑤选场景/产品 ⑦特效面板 ⑫改参数重试
|
||||
|
||||
### C.5 文档里的能力清单(供应商维度,能力注册表要照此扩充)
|
||||
|
||||
| 模块 | 文档列出的可选供应商 |
|
||||
|:--|:--|
|
||||
| TTS | Fish Audio / ElevenLabs / Qwen3-TTS |
|
||||
| 口播视频 | D-ID / HeyGen / 本地 LongCat |
|
||||
| 动作视频 | 可灵 / Wan-Animate-2 / Runway |
|
||||
| 背景空镜 | 通义万相 / Sora 2 / 可灵 |
|
||||
| ComfyUI | RunningHub / ComfyDeploy / 自建 |
|
||||
| 3D 角色 | 混元3D / Autodesk Flow Studio |
|
||||
| 特效·子弹时间 | 万兴天幕 / 海螺AI / 可灵 |
|
||||
| 特效·运镜 | 可灵(camera_control 六参数 ∈[-10,10])/ 海螺AI(T2V-01-Director) |
|
||||
|
||||
---
|
||||
|
||||
## 附录 D|节点 → 能力映射表(P2 执行器的实施依据)
|
||||
|
||||
> 调研结论:`workflows.py` 的 15 种节点定义**只有 UI 元数据**(label/icon/description/default_config/options_map),
|
||||
> **没有绑定到真实能力**;`WorkflowRunner` 是空壳。下表把 15 种节点映射到能力注册表里的实现。
|
||||
|
||||
| # | 节点类型 | 名称 | 对应能力 | 状态 |
|
||||
|:--|:--|:--|:--|:--|
|
||||
| 1 | `story_prototype` | 剧本原型 | `script_generate`(LLM 生成) | ✅ ready |
|
||||
| 2 | `script` | 脚本输入 | **无执行**(用户输入 / 读文件) | — 透传 |
|
||||
| 3 | `script_adaptor` | 剧本改编 | `script_parse` + `script_generate` | ✅ ready |
|
||||
| 4 | `strategy` | 策略选择 | LLM 决策 或 参数选择 | 🟡 待明确 |
|
||||
| 5 | `tts` | TTS 合成 | `tts_generate`(火山/阿里) | ✅ ready |
|
||||
| 6 | `model` | AI 模型 | LLM(DeepSeek)通用调用 | ✅ ready |
|
||||
| 7 | `material` | 素材源 | `material_search`(Pexels/万相/兜底) | ✅ ready |
|
||||
| 8 | `style` | 风格预设 | **无执行**(参数注入) | — 透传 |
|
||||
| 9 | `bgm` | BGM 选择 | `bgm_generate` / `music_select` | ✅ ready |
|
||||
| 10 | `character` | 角色 | **资产引用**(无执行,取资产注入) | — 引用 |
|
||||
| 11 | `audit_gate` | 审核门 | **人工暂停/继续**(需实现断点机制) | 🟡 待实现 |
|
||||
| 12 | `output` | 输出 | `video_concat` + `de_ai` | ✅ ready |
|
||||
| 13 | `storyboard` | 分镜规划 | `storyboard_plan`(v5.2/clip/legacy) | ✅ ready |
|
||||
| 14 | `prompt_gen` | 分镜提示词 | `prompt_gen`(六模块编译器) | ✅ ready |
|
||||
| 15 | `subtitle` | 字幕生成 | `subtitle` | 🟡 partial |
|
||||
|
||||
**结论**:
|
||||
- **12/15 节点已有现成能力**(ready 或 partial)
|
||||
- 4 个是"无执行"节点(`script` 输入 / `style` 参数 / `character` 引用 / `strategy` 决策)→ 执行器**透传**即可
|
||||
- 1 个需新机制:`audit_gate`(人工审核门 → 暂停/继续)
|
||||
|
||||
**P2 执行器工作量**(已明确):
|
||||
1. 建 `NODE_TYPE → capability_id` 映射(上表)
|
||||
2. 执行器:拓扑排序 → 逐节点调能力 → 产物存 run context → 下游按 `{{node.xxx}}` 引用 → 状态回写
|
||||
3. 特殊处理:无执行节点透传 · `audit_gate` 暂停 · 失败重试 · 「从某节点起重跑下游」
|
||||
4. 前端:节点卡片显示产物预览(文本可编辑 / 音视频可播放)+ 🔄 重做
|
||||
|
||||
---
|
||||
|
||||
## 附录 E|P2 实施要点(执行器改动清单 —— 决策后即可开工)
|
||||
|
||||
**目标文件**:`05_tools/10_dashboard/workflows.py`(599 行)
|
||||
|
||||
**现状(3 处关键代码)**:
|
||||
|
||||
| 位置 | 现状 |
|
||||
|:--|:--|
|
||||
| `WorkflowRunner._execute()`(519 行) | 只做拓扑排序 → 把节点标记 `completed`,**无任何真实执行** |
|
||||
| `NODE_DEFINITIONS`(35 行) | 15 种节点**只有 UI 元数据**(label/icon/description/options_map),**未绑定能力** |
|
||||
| `start_run()`(510 行) | 起后台线程调 `_execute` ✓ 骨架可用(可直接复用) |
|
||||
|
||||
**改动清单(3 步)**:
|
||||
|
||||
1. **建映射**:`NODE_TO_CAPABILITY = {node_type: capability_id}` —— 附录 D 已给出 15 项对应(12 项有现成能力)
|
||||
2. **写节点执行** `_run_node(node, ctx) -> dict`:
|
||||
- 查映射 → 取能力 → 合并参数(**能力默认 ← 流程覆盖 ← 节点覆盖**)→ 调实现 → 返回产物
|
||||
- **4 个无执行节点**(`script` / `style` / `character` / `strategy`)→ **透传**(直接传上游值)
|
||||
- `audit_gate` → 置 run 状态为 `paused`,等外部 `resume`
|
||||
3. **改 `_execute()`**:逐节点调 `_run_node` → 产物存 `run["context"][node_id]` → 下游按 `{{node.xxx}}` 解析 → 状态回写(success/failed/skipped)→ 失败按节点重试配置重试
|
||||
|
||||
**后端新接口(3 个)**:
|
||||
|
||||
| 接口 | 用途 |
|
||||
|:--|:--|
|
||||
| `POST /api/workflow/runs/{run_id}/redo/{node_id}` | 单节点重做(改配置后重跑) |
|
||||
| `POST /api/workflow/runs/{run_id}/resume` | `audit_gate` 审核通过 → 继续 |
|
||||
| `GET /api/workflow/runs/{run_id}/artifacts` | 各节点产物列表(供前端预览) |
|
||||
|
||||
**前端配合**(`views/workflow.js` 画布已就绪):
|
||||
- 节点卡片加**状态徽章** + **产物预览**(文本可编辑 / 视频可播放)
|
||||
- 「🔄 重做此节点」·「▶️ 从此刻起跑下游」按钮
|
||||
|
||||
**可复用**(无需重写):
|
||||
- 能力注册表(`capabilities/`)· 可灵引擎(`kling_video.py`)· 流水线(`composer/pipeline.py`)· 资产库(`assets_manager/`)· 成本统计(`api_costs`)
|
||||
|
||||
---
|
||||
|
||||
## 附:归档说明
|
||||
|
||||
以下文档**已归档**(内容被本文档取代,避免误导后续开发):
|
||||
- `VIDEO_FACTORY_FRAMEWORK.md`(v1 框架:菜单分类有误,见第二节)
|
||||
- `VIDEO_FACTORY_ARCHITECTURE.md`(技术细节,已并入本文第六节)
|
||||
- `DCS_VIDEO_FACTORY_PLAN.md`(调研 + M1 计划,M1 已完成)
|
||||
|
||||
归档位置:`90_archive/video_factory_docs_20261001/`
|
||||
@@ -0,0 +1,99 @@
|
||||
# 视频工厂 · 使用指南
|
||||
|
||||
> 更新: 2026-10-02 · 对应版本 4.11.x
|
||||
> 架构文档: `PLANS/VIDEO_FACTORY_MASTER.md` · 原始设计: `PLANS/reference/DCS_说明书_v2.0_原文.md`
|
||||
|
||||
---
|
||||
|
||||
## 一、快速开始(3 步出片)
|
||||
|
||||
1. 打开看板 **http://localhost:9988**(如果是旧界面,`Cmd+Shift+R` 硬刷新)
|
||||
2. 侧边栏 → **🎞️ 视频工厂 · 流程** → 任选一条流程(如「🎙️ 基础口播」)
|
||||
3. 看到流程步骤链 + 预估成本 → 点 **▶️ 开始** → 画布自动加载模板
|
||||
4. 把「**镜头数**」设为 **1**(首次试跑,控成本)→ 点 **▶ 运行**
|
||||
5. 观察节点状态(🟢完成 / 🔵执行中 / 🔴失败 / ⚪跳过)→ 点节点看**产物预览**(视频/音频可直接播放)
|
||||
|
||||
---
|
||||
|
||||
## 二、流程清单
|
||||
|
||||
| 流程 | 模板 | 节点数 | 说明 |
|
||||
|:--|:--|:--|:--|
|
||||
| 🎬 导演创作 | (单页) | — | 故事 → 分镜(可编辑)→ 一键出片 |
|
||||
| 🎭 短剧创作 | `short_drama` | 12 | 完整短剧流程 |
|
||||
| 🎙️ 基础口播 | `basic_dub` | 5 | 脚本 → TTS → 素材 → BGM → 输出 |
|
||||
| 🥁 卡点视频 | `beat_sync` | 4 | BGM 卡点 |
|
||||
| 📖 角色叙事 | `character_narrative` | 8 | 角色 + 旁白 |
|
||||
| 👤 数字人口播 | `digital_human` | 4 | 需数字人能力(待接入) |
|
||||
| 🎞️ 口播+混剪 | `hybrid_dub` | 4 | — |
|
||||
| ➕ 新建流程 | (空白画布) | — | 自己拖节点 |
|
||||
|
||||
---
|
||||
|
||||
## 三、能力与依赖(配 key 就能用)
|
||||
|
||||
| 能力 | 状态 | 依赖 | 备注 |
|
||||
|:--|:--|:--|:--|
|
||||
| 🎬 分镜规划 | ✅ | `llm.api_key`(DeepSeek) | 已配 |
|
||||
| 📝 提示词生成 | ✅ | 同上 | 已配 |
|
||||
| 🎥 视频生成 | ✅ | `kling.api_key` | 已配(`kling-v3`) |
|
||||
| 📦 视频合成 | ✅ | 本地 FFmpeg | 含去AI化 |
|
||||
| **🔊 混流** | ✅ | 本地 FFmpeg | 视频+人声+BGM+字幕 |
|
||||
| **🎤 TTS 语音** | ⚠️ | `aliyun.api_key` **(欠费)** / `volcano.voice_app_key`(缺 token) | **充值阿里即用** |
|
||||
| 🔌 素材搜索 | ⚠️ | `pexels.api_key` | 免费申请 pexels.com/api |
|
||||
| 🎵 BGM 选择 | ✅ | 本地音乐库 | — |
|
||||
| 💬 字幕生成 | ✅ | 本地 | ASS 格式 |
|
||||
| 🔄 人物置换 | ⚠️ | `aliyun.api_key`(同 TTS) | 充值即用 |
|
||||
| 💋 对口型 | ⚠️ | `fal.api_key` | 未配 |
|
||||
|
||||
**配置入口**:Dashboard → **⚙️ 服务 → 🔑 API 配置**(每项可「🧪 测试」验证连通性)
|
||||
|
||||
---
|
||||
|
||||
## 四、常见问题
|
||||
|
||||
**Q: 报「阿里百炼账号欠费(Arrearage)」**
|
||||
→ 阿里云控制台充值(同时解锁 TTS + 人物置换)
|
||||
|
||||
**Q: 报「Pexels API Key 未配置」**
|
||||
→ https://www.pexels.com/api/ 免费申请 → 「🔑 API 配置」填入
|
||||
|
||||
**Q: 出片很慢(10+ 分钟)**
|
||||
→ 可灵服务端排队(高峰期常见),非代码问题。可在「能力试跑」页用预检查看任务状态
|
||||
|
||||
**Q: 成片没有声音**
|
||||
→ 检查流程里是否有 TTS 节点 + TTS 是否成功(阿里欠费会失败)
|
||||
|
||||
**Q: 节点显示「跳过」**
|
||||
→ 该能力尚未接入执行器(如 ComfyUI/特效/3D 角色),或缺少必要上游产物
|
||||
|
||||
**Q: 分镜不满意**
|
||||
→ 「🎬 导演创作」页可逐镜头编辑 + 🔄 单镜头重生成;或换导演(v5.2 / 本地)
|
||||
|
||||
---
|
||||
|
||||
## 五、省钱的调试技巧
|
||||
|
||||
1. **镜头数先设 1**(默认 3)—— 每镜头约 ¥1-3
|
||||
2. **优先只读**:查任务列表/状态用 GET(不扣费),别反复跑生成
|
||||
3. **用「🧪 能力试跑」的预检**(dry_run,零费用):确认供应商/模型/参数/密钥状态后再真跑
|
||||
4. **复用已有产物**:TTS 音频、字幕文件可跨 run 复用(修改配置只重做必要节点 → 「🔄 重做此节点」)
|
||||
|
||||
---
|
||||
|
||||
## 六、关键命令(运维)
|
||||
|
||||
```bash
|
||||
# 重启看板(必须用 launchctl,禁止 pkill+nohup)
|
||||
launchctl kickstart -k gui/$(id -u)/com.agentos.dashboard
|
||||
curl -s http://localhost:9988/api/health
|
||||
|
||||
# 查看运行
|
||||
curl -s http://localhost:9988/api/workflow/runs | python3 -m json.tool | head -30
|
||||
|
||||
# 产物位置
|
||||
ls ~/workbuddy-agent-os/agent-local/runtime/ave/workflow/<run_id>/
|
||||
|
||||
# 出片记录(导演创作页产物)
|
||||
ls ~/workbuddy-agent-os/agent-local/runtime/ave/renders/
|
||||
```
|
||||
@@ -0,0 +1,837 @@
|
||||
# 导演创作系统(Director Creative System, DCS)· 项目开发说明书 v2.0
|
||||
|
||||
> **来源**:用户原始设计文档 `~/Documents/导演创作系统(Director.docx`(829 行,2026-10-01 09:48 更新)
|
||||
> **入库原因**:作为视频工厂的**设计基准**(`PLANS/VIDEO_FACTORY_MASTER.md` 附录 C 即对照本文档)
|
||||
> **入库时间**:2026-10-01 | 原文由 textutil 从 docx 提取(仅格式变换,内容未改)
|
||||
|
||||
---
|
||||
|
||||
导演创作系统(Director Creative System, DCS)
|
||||
|
||||
项目开发说明书 v2.0
|
||||
|
||||
一、项目定位
|
||||
|
||||
DCS是一套面向广告导演/制片人的AI视频生产系统。导演用自然语言描述故事,系统自动完成分镜拆解、资产调度、视频生成、特效叠加和后期合成,输出接近真人实拍质感的20-30秒短片。
|
||||
|
||||
核心设计原则:
|
||||
|
||||
1. 解耦:导演系统、编排系统、能力API、合成后期互相独立,可单独替换。
|
||||
2. 标准化:所有模块通过统一分镜Schema交互,换模块不改流程。
|
||||
3. 导演优先:3D角色、特效运镜、产品资产均可由导演在控制台按需调用,不盲目抽卡。
|
||||
4. 真实感优先:分镜遵循伪纪录片/手机随手拍美学,后期强制走去AI化处理链。
|
||||
5. 低成本起步:本地零GPU,所有算力走远端API。
|
||||
|
||||
二、系统架构
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────────────┐
|
||||
│ 层0:导演控制台(Appsmith,本地Docker,端口80) │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │分镜编辑 │ │资产库 │ │3D角色 │ │特效库 │ │任务状态 │ │
|
||||
│ │ │ │ │ │生产 │ │ │ │ │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │成片预览 │ │参数模板 │ │系统设置 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────┬─────────────────────────────────────────┘
|
||||
↓
|
||||
┌───────────────────────────────────────────────────────────────────────┐
|
||||
│ 层1:导演层(可替换) │
|
||||
│ │
|
||||
│ 导演系统(当前选型:AI Storyboard Director v5.2) │
|
||||
│ 职责:自然语言故事 → 统一分镜Schema (JSON) │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ 统一分镜Schema(标准接口) │ │
|
||||
│ │ 所有模块的“普通话” │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────┬─────────────────────────────────────────┘
|
||||
↓
|
||||
┌───────────────────────────────────────────────────────────────────────┐
|
||||
│ 层2:编排层(n8n,本地Docker,端口5678) │
|
||||
│ │
|
||||
│ 读取分镜Schema → 按type分发 → 调用各API → 收集输出 → 交给合成层 │
|
||||
│ │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │TTS节点 │ │口播节点│ │动作节点│ │背景节点│ │特效节点│ │3D节点 │ │
|
||||
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │
|
||||
└─────────────────────────────┬─────────────────────────────────────────┘
|
||||
↓
|
||||
┌───────────────────────────────────────────────────────────────────────┐
|
||||
│ 层3:能力层(全部远端API,可替换) │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐│
|
||||
│ │Fish Audio│ │D-ID/ │ │可灵/ │ │通义万相 │ │RunningHub ││
|
||||
│ │TTS │ │HeyGen │ │Wan-Anim │ │背景/空镜 │ │(ComfyUI) ││
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────────┘│
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │混元3D │ │万兴天幕 │ │海螺AI │ │其他特效 │ │
|
||||
│ │角色生成 │ │子弹时间 │ │运镜 │ │ │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────┬─────────────────────────────────────────┘
|
||||
↓
|
||||
┌───────────────────────────────────────────────────────────────────────┐
|
||||
│ 层4:合成层(FFmpeg,本地) │
|
||||
│ │
|
||||
│ 去AI化处理链:轻微模糊 → 胶片颗粒 → 调色 → 帧混合 → 拼接 │
|
||||
│ 输出:成片mp4 │
|
||||
└───────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
三、分层职责与模块规范
|
||||
|
||||
3.1 层0:导演控制台
|
||||
|
||||
部署:Appsmith,本地Docker,端口80。跨平台(macOS/Linux),迁移时导出数据库+环境变量即可。
|
||||
|
||||
页面清单:
|
||||
|
||||
页面 功能 数据源
|
||||
分镜编辑 输入故事大纲 → 调用导演系统 → 展示分镜表 → 逐条修改 FastAPI /api/director/generate
|
||||
资产库 角色/场景/道具/产品/BGM/音效管理 FastAPI /api/assets/*
|
||||
3D角色生产 上传概念图 → 生成多视图+骨骼绑定 → 存入资产库 混元3D API
|
||||
特效库 浏览可用特效,查看参数说明,预览示例 FastAPI /api/vfx/list
|
||||
任务状态 查看n8n任务队列,每条分镜状态 FastAPI /api/task/*
|
||||
成片预览 按项目分组播放成片 本地文件系统
|
||||
参数模板 管理各内容类型的模板(广告/日记/短剧) config/templates/
|
||||
系统设置 API Key管理、提供商切换、去AI化参数 config/providers.yaml
|
||||
|
||||
控制台可设置参数:
|
||||
|
||||
A. 导演系统配置
|
||||
|
||||
· 当前导演系统:下拉选择
|
||||
· 导演系统API地址
|
||||
· 默认输出Schema版本
|
||||
|
||||
B. 能力提供商配置
|
||||
|
||||
模块 可选提供商 切换方式
|
||||
TTS Fish Audio / ElevenLabs / Qwen3-TTS 下拉 + Key
|
||||
口播视频 D-ID / HeyGen / 本地LongCat 下拉 + Key
|
||||
动作视频 可灵 / Wan-Animate-2 / Runway 下拉 + Key
|
||||
背景/空镜 通义万相 / Sora 2 / 可灵 下拉 + Key
|
||||
ComfyUI RunningHub / ComfyDeploy / 自建 下拉 + API地址
|
||||
3D角色 混元3D / Autodesk Flow Studio 下拉 + Key
|
||||
特效-子弹时间 万兴天幕 / 海螺AI / 可灵 下拉 + Key
|
||||
特效-运镜 可灵 / 海螺AI 下拉 + Key
|
||||
|
||||
C. 去AI化参数(全局默认,可被分镜覆盖)
|
||||
|
||||
· 模糊 sigma:默认 0.4
|
||||
· 胶片颗粒强度:默认 12
|
||||
· 饱和度偏移:默认 -0.12
|
||||
· 色温偏移:默认 +0.03
|
||||
· 帧混合帧数:默认 2
|
||||
|
||||
3.2 层1:导演层
|
||||
|
||||
职责:接收自然语言故事,输出统一分镜Schema。
|
||||
|
||||
可替换性:任何导演系统,只要输出符合统一分镜Schema的JSON,即可接入。若输出格式不同,需写薄适配器转换。
|
||||
|
||||
导演系统输入:
|
||||
|
||||
```json
|
||||
{
|
||||
"story": "我住院第三天,躺在病床上录了一段……",
|
||||
"content_type": "personal_vlog",
|
||||
"template_id": "vlog_hospital_001",
|
||||
"global_anchors": {
|
||||
"character_id": "char_001",
|
||||
"location_id": "loc_hospital_302",
|
||||
"shooting_style": "documentary_realism"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当前推荐:AI Storyboard Director v5.2(支持“假设标记”,可强制保留不完美细节)。备选:clip-storyboard-director(4D持久化缓冲区,跨场景一致性最强)。
|
||||
|
||||
3.3 层2:编排层(n8n)
|
||||
|
||||
部署:本地 Docker,端口 5678。
|
||||
|
||||
工作流设计:
|
||||
|
||||
```
|
||||
[Webhook触发]
|
||||
→ [读取分镜Schema JSON]
|
||||
→ [循环每条shot]
|
||||
→ [Switch节点:按type分发]
|
||||
├─ type == "talking_head" → [HTTP Request: 口播API]
|
||||
├─ type == "action" → [HTTP Request: 动作API]
|
||||
├─ type == "background" → [HTTP Request: 背景API]
|
||||
├─ type == "comfyui" → [HTTP Request: RunningHub API]
|
||||
├─ type == "vfx" → [HTTP Request: 特效API]
|
||||
└─ type == "3d_character" → [HTTP Request: 混元3D API]
|
||||
→ [等待任务完成(轮询)]
|
||||
→ [下载输出片段到本地临时目录]
|
||||
→ [FFmpeg节点:去AI化处理链]
|
||||
→ [FFmpeg节点:拼接所有片段]
|
||||
→ [输出成片mp4到指定目录]
|
||||
→ [回调控制台更新任务状态]
|
||||
```
|
||||
|
||||
3.4 层3:能力层
|
||||
|
||||
统一接口约定:所有能力API返回格式统一为:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"video_url": "https://.../output.mp4",
|
||||
"duration": 8.0,
|
||||
"format": "mp4",
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
各模块调用方式:
|
||||
|
||||
模块 API 调用方式 关键参数
|
||||
TTS Fish Audio POST /v1/tts text, voice_id, emotion_tags
|
||||
口播 D-ID POST /talks source_url, script.audio_url, config.sentiment
|
||||
动作 可灵 POST /v1/videos image_url, prompt, camera_control
|
||||
背景 通义万相 POST /api/v1/video prompt, size, seconds
|
||||
ComfyUI RunningHub POST /api/v1/workflow workflow_id, node_overrides
|
||||
3D角色 混元3D SubmitHunyuanTo3DProJob Prompt/ImageUrl, ViewImage
|
||||
子弹时间 万兴天幕 POST /api/v1/vfx image_url, effect_type
|
||||
运镜 可灵 camera_control参数 pan/tilt/roll/zoom ∈ [-10,10]
|
||||
运镜 海螺AI 嵌套指令 环绕+降速+焦点锁定
|
||||
|
||||
四、统一分镜 Schema(标准接口)
|
||||
|
||||
src/schemas.py:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional, Literal
|
||||
|
||||
class GlobalAnchors(BaseModel):
|
||||
character_id: str
|
||||
character_3d_id: Optional[str] = None
|
||||
location_id: str
|
||||
product_id: Optional[str] = None
|
||||
wardrobe: str
|
||||
lighting_state: str
|
||||
camera_lens: str
|
||||
shooting_style: str = "documentary_realism"
|
||||
consistency_seed: int = 42
|
||||
|
||||
class ShotContract(BaseModel):
|
||||
shot_size: str
|
||||
angle: str
|
||||
camera_move: str
|
||||
lens_feel: str
|
||||
depth_of_field: str
|
||||
frame_rate_feel: str
|
||||
|
||||
class VFXConfig(BaseModel):
|
||||
vfx_id: Optional[str] = None
|
||||
vfx_type: Optional[Literal["bullet_time", "orbit", "slow_motion",
|
||||
"focus_lock", "custom"]] = None
|
||||
provider: Optional[str] = None
|
||||
params: Optional[dict] = None
|
||||
|
||||
class ExpressionDetail(BaseModel):
|
||||
eyes: Optional[str] = None
|
||||
mouth: Optional[str] = None
|
||||
brow: Optional[str] = None
|
||||
|
||||
class SFX(BaseModel):
|
||||
id: str
|
||||
at_second: float
|
||||
volume: float = 0.4
|
||||
|
||||
class AudioConfig(BaseModel):
|
||||
voice_volume: float = 1.0
|
||||
bgm_id: Optional[str] = None
|
||||
bgm_volume: float = 0.15
|
||||
bgm_fade_in: float = 1.0
|
||||
bgm_fade_out: float = 1.0
|
||||
sfx: List[SFX] = []
|
||||
audio_cue: Optional[str] = None
|
||||
denoise: bool = False
|
||||
|
||||
class Subtitle(BaseModel):
|
||||
enabled: bool = True
|
||||
text: str
|
||||
style: str = "手机系统默认"
|
||||
position: str = "bottom_center"
|
||||
|
||||
class Transition(BaseModel):
|
||||
type: Literal["cut", "dissolve", "fade", "wipe"] = "cut"
|
||||
duration: float = 0
|
||||
|
||||
class Speed(BaseModel):
|
||||
factor: float = 1.0
|
||||
ramp: Optional[str] = None
|
||||
|
||||
class ColorConfig(BaseModel):
|
||||
lut: Optional[str] = None
|
||||
saturation_offset: float = -0.12
|
||||
temperature_shift: float = 0.03
|
||||
|
||||
class PostProcess(BaseModel):
|
||||
grain_intensity: int = 12
|
||||
blur_sigma: float = 0.4
|
||||
frame_interpolation: bool = False
|
||||
|
||||
class OutputConfig(BaseModel):
|
||||
resolution: str = "1080x1920"
|
||||
fps: int = 30
|
||||
bitrate: str = "8M"
|
||||
|
||||
class Shot(BaseModel):
|
||||
shot_id: str
|
||||
scene_id: str
|
||||
duration: float
|
||||
type: Literal["talking_head", "action", "background",
|
||||
"comfyui", "vfx", "3d_character"]
|
||||
character_id: str
|
||||
character_3d_id: Optional[str] = None
|
||||
location_id: str
|
||||
product_id: Optional[str] = None
|
||||
product_focus: bool = False
|
||||
product_placement: Optional[str] = None
|
||||
props: List[str] = []
|
||||
continuity_mode: Literal[
|
||||
"fresh_location",
|
||||
"previous_frame_continuation",
|
||||
"location_reappearance"
|
||||
]
|
||||
shot_contract: ShotContract
|
||||
vfx: Optional[VFXConfig] = None
|
||||
visual_description: str
|
||||
text: Optional[str] = None
|
||||
sentiment: Optional[str] = None
|
||||
expression_detail: Optional[ExpressionDetail] = None
|
||||
action: Optional[str] = None
|
||||
audio: Optional[AudioConfig] = None
|
||||
subtitle: Optional[Subtitle] = None
|
||||
transition_in: Transition = Transition()
|
||||
transition_out: Transition = Transition()
|
||||
speed: Speed = Speed()
|
||||
color: ColorConfig = ColorConfig()
|
||||
post_process: PostProcess = PostProcess()
|
||||
output: OutputConfig = OutputConfig()
|
||||
|
||||
class Storyboard(BaseModel):
|
||||
project_id: str
|
||||
schema_version: str = "2.0"
|
||||
global_anchors: GlobalAnchors
|
||||
shots: List[Shot]
|
||||
```
|
||||
|
||||
特效参数示例(vfx字段):
|
||||
|
||||
```json
|
||||
{
|
||||
"vfx": {
|
||||
"vfx_id": "vfx_bullet_time_01",
|
||||
"vfx_type": "bullet_time",
|
||||
"provider": "wondershare_tianmu",
|
||||
"params": {
|
||||
"source_image": "keyframe_01.png",
|
||||
"duration": 3.0,
|
||||
"freeze_radius": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
可灵环绕运镜参数(写入shot_contract.camera_move或vfx.params):
|
||||
|
||||
可灵的camera_control支持六种运镜参数,取值范围均为[-10, 10]:horizontal(水平平移)、vertical(垂直平移)、pan(水平摇镜,绕y轴旋转)、tilt(垂直摇镜,绕x轴)、roll(旋转运镜,绕z轴)、zoom(变焦)。同时支持预定义运镜类型:simple、down_back(下移拉远)、forward_up(推进上移)、right_turn_forward(右旋推进)、left_turn_forward(左旋推进)。导演可在控制台选择预定义类型或手动指定六参数组合。
|
||||
|
||||
五、资产库规范
|
||||
|
||||
目录结构:
|
||||
|
||||
```
|
||||
assets/
|
||||
├── characters/
|
||||
│ └── char_001/
|
||||
│ ├── reference.png
|
||||
│ ├── reference_side.png
|
||||
│ ├── reference_full.png
|
||||
│ ├── lora.safetensors
|
||||
│ ├── voice_sample.mp3
|
||||
│ └── meta.json
|
||||
├── characters_3d/
|
||||
│ └── char_001_3d/
|
||||
│ ├── model.glb
|
||||
│ ├── model.fbx
|
||||
│ ├── texture/
|
||||
│ ├── rig_info.json
|
||||
│ └── meta.json
|
||||
├── locations/
|
||||
│ └── loc_hospital_302/
|
||||
│ ├── reference.png
|
||||
│ ├── reference_video.mp4
|
||||
│ └── meta.json
|
||||
├── real_locations/
|
||||
│ └── loc_cafe_01/
|
||||
│ ├── reference_wide.jpg
|
||||
│ ├── reference_detail.jpg
|
||||
│ ├── reference_light.jpg
|
||||
│ ├── reference_video.mp4
|
||||
│ └── meta.json
|
||||
├── products/
|
||||
│ └── prod_skin_cream/
|
||||
│ ├── reference_front.png
|
||||
│ ├── reference_angle.png
|
||||
│ ├── reference_detail.png
|
||||
│ ├── reference_in_hand.png
|
||||
│ └── meta.json
|
||||
├── props/
|
||||
├── bgm/
|
||||
├── sfx/
|
||||
└── vfx_presets/
|
||||
├── bullet_time.yaml
|
||||
├── orbit.yaml
|
||||
└── slow_motion.yaml
|
||||
```
|
||||
|
||||
角色3D元数据(meta.json) :
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "char_001_3d",
|
||||
"name": "患者A-3D",
|
||||
"source_tool": "hunyuan_3d",
|
||||
"model_formats": ["glb", "fbx"],
|
||||
"rigged": true,
|
||||
"rig_type": "humanoid",
|
||||
"reference_2d_id": "char_001",
|
||||
"consistency_seed": 42,
|
||||
"created_at": "2026-10-01"
|
||||
}
|
||||
```
|
||||
|
||||
产品元数据:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "prod_skin_cream",
|
||||
"name": "XX精华面霜",
|
||||
"category": "护肤品",
|
||||
"must_keep": ["瓶身标签文字", "瓶盖金色边框", "整体配色"],
|
||||
"reference_images": {
|
||||
"front": "reference_front.png",
|
||||
"angle": "reference_angle.png",
|
||||
"detail": "reference_detail.png",
|
||||
"in_hand": "reference_in_hand.png"
|
||||
},
|
||||
"consistency_seed": 88
|
||||
}
|
||||
```
|
||||
|
||||
调用方式:分镜Schema中通过 character_id、character_3d_id、location_id、product_id、props、bgm_id、sfx.id、vfx.vfx_id 引用。n8n根据ID从资产库读取文件路径,注入API请求。
|
||||
|
||||
六、3D角色生产模块
|
||||
|
||||
功能:导演上传角色概念图,系统自动生成多视图+骨骼绑定3D模型,存入资产库,后续分镜通过 character_3d_id 引用。
|
||||
|
||||
调用流程:
|
||||
|
||||
```
|
||||
导演上传正面概念图
|
||||
↓ 控制台 → FastAPI → 混元3D API
|
||||
混元3D SubmitHunyuanTo3DProJob
|
||||
↓ 传入 Prompt/ImageUrl + ViewImage(多视角图片)
|
||||
返回 JobId → 轮询 DescribeProfileTo3DJob
|
||||
↓ Status == DONE
|
||||
获得 File3D(OBJ/GLB格式,含Url和PreviewImageUrl)
|
||||
↓ 下载到 assets/characters_3d/
|
||||
自动绑定骨骼(混元3D内置AutoRigging)
|
||||
↓ 存入资产库
|
||||
后续分镜通过 character_3d_id 引用
|
||||
```
|
||||
|
||||
混元3D API关键参数:
|
||||
|
||||
· 输入:Prompt(文本)或 ImageUrl(图片URL,有效期24小时)或 ViewImage(多视角图片,支持back/left/right)
|
||||
· 输出:File3D 数组,包含 Type(文件格式)、Url(文件URL)、PreviewImageUrl(预览图)
|
||||
· 任务查询:DescribeProfileTo3DJob 返回 Status(WAIT/RUN/FAIL/DONE)和 ResultFile3Ds
|
||||
· 支持接口:SubmitHunyuanTo3DProJob(专业版)、SubmitHunyuanTo3DRapidJob(极速版)、SubmitAutoRiggingJob(自动骨骼绑定)
|
||||
|
||||
七、特效运镜库
|
||||
|
||||
7.1 子弹时间
|
||||
|
||||
提供商 调用方式 关键参数
|
||||
万兴天幕 POST /api/v1/vfx image_url, effect_type="bullet_time", duration
|
||||
可灵 camera_control参数组合 pan ∈ [-10,10], roll ∈ [-10,10], zoom
|
||||
海螺AI T2V-01-Director模型 内置Bullet Time模板,自动应用时间凝滞+环绕视角
|
||||
ComfyUI RunningHub工作流 VFX-Bullet Time Effect工作流,两阶段渲染
|
||||
|
||||
万兴天幕的“子弹时间”特效支持单张静态图片一键生成影视级动态视频,无需复杂拍摄,且已开放API接口支持MCP协议。海螺AI的T2V-01-Director模型预置了标准化运镜模组,调用内置Bullet Time模板即可触发基础子弹时间逻辑,系统自动应用时间凝滞+环绕视角参数。
|
||||
|
||||
7.2 环绕运镜
|
||||
|
||||
可灵支持精细的环绕运镜控制。预定义类型中,right_turn_forward 实现“先右旋转后前进”,left_turn_forward 实现“先左旋并前进”。手动模式下可通过 pan 参数实现水平面上的旋转,pan 负值表示绕y轴向左旋转,正值表示向右旋转,取值范围[-10, 10]。
|
||||
|
||||
7.3 慢动作/升格
|
||||
|
||||
可灵的 frame_rate_feel 参数控制帧率感觉。海螺AI支持嵌套运镜指令,将“环绕+降速+焦点锁定”三重动作按时间顺序嵌套至提示词中。
|
||||
|
||||
7.4 特效库的导演操作方式
|
||||
|
||||
导演在控制台分镜编辑页面中,每条镜头可展开“特效”面板:
|
||||
|
||||
1. 从下拉菜单选择特效类型(子弹时间/环绕/慢动作/焦点锁定/自定义)
|
||||
2. 选择提供商(万兴天幕/可灵/海螺AI/ComfyUI)
|
||||
3. 填写参数表单(根据特效类型动态显示)
|
||||
4. 点击“预览”可调用测试API生成样片
|
||||
5. 确认后,参数写入分镜Schema的 vfx 字段
|
||||
|
||||
八、去AI化处理链
|
||||
|
||||
de_ai.py:
|
||||
|
||||
```python
|
||||
class DeAIProcessor:
|
||||
def process(self, input_path: str, output_path: str,
|
||||
params: PostProcess, color: ColorConfig):
|
||||
"""
|
||||
按顺序执行:
|
||||
1. gblur sigma={blur_sigma} # 消除AI边缘锐利感
|
||||
2. noise alls={grain_intensity}:allf=t+u # 添加真实传感器噪点
|
||||
3. eq saturation={1+saturation_offset} # 饱和度降低
|
||||
4. curves=all='0/0 0.5/0.55 1/1' # S曲线拉反差
|
||||
5. colortemperature=temperature=5300 # 色温偏移
|
||||
"""
|
||||
```
|
||||
|
||||
FFmpeg命令模板:
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 \
|
||||
-vf "gblur=sigma=0.4,noise=alls=12:allf=t+u,\
|
||||
eq=saturation=0.88,curves=all='0/0 0.5/0.55 1/1',\
|
||||
colortemperature=temperature=5300" \
|
||||
-c:v libx264 -preset medium -crf 18 \
|
||||
output.mp4
|
||||
```
|
||||
|
||||
拼接:所有处理后的片段用 concat 滤镜拼接,输出最终mp4。
|
||||
|
||||
九、FastAPI入口
|
||||
|
||||
端点列表:
|
||||
|
||||
方法 路径 功能
|
||||
POST /api/director/generate 输入故事,返回分镜Schema
|
||||
POST /api/task/submit 提交分镜,返回task_id
|
||||
GET /api/task/{task_id} 查询任务状态
|
||||
POST /api/task/{task_id}/retry 重试某镜头
|
||||
GET /api/assets/characters 列出所有角色
|
||||
POST /api/assets/characters 上传角色
|
||||
GET /api/assets/characters_3d 列出3D角色
|
||||
POST /api/assets/characters_3d/generate 调用混元3D生成角色
|
||||
GET /api/assets/products 列出产品资产
|
||||
POST /api/assets/products 上传产品
|
||||
GET /api/vfx/list 列出可用特效
|
||||
POST /api/vfx/preview 生成特效样片
|
||||
GET /api/output/{project_id} 列出成片
|
||||
GET /api/config/providers 获取当前提供商配置
|
||||
PUT /api/config/providers 切换提供商
|
||||
|
||||
十、部署说明
|
||||
|
||||
10.1 本地环境
|
||||
|
||||
组件 部署方式 端口 备注
|
||||
n8n Docker 5678 挂载 ~/dcs/n8n
|
||||
Appsmith Docker 80 挂载 ~/dcs/appsmith
|
||||
FastAPI Docker 8000 挂载 assets/output/temp/config
|
||||
FFmpeg 本地安装 — brew install ffmpeg / apt install ffmpeg
|
||||
资产库 本地文件夹 — ~/dcs/assets
|
||||
导演系统 本地脚本或远端API — 包装为FastAPI端点
|
||||
|
||||
10.2 Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
n8n:
|
||||
image: n8nio/n8n
|
||||
ports:
|
||||
- "5678:5678"
|
||||
volumes:
|
||||
- ./n8n:/home/node/.n8n
|
||||
environment:
|
||||
- N8N_BASIC_AUTH_ACTIVE=true
|
||||
- N8N_BASIC_AUTH_USER=admin
|
||||
- N8N_BASIC_AUTH_PASSWORD=admin
|
||||
|
||||
appsmith:
|
||||
image: appsmith/appsmith-ce
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- ./appsmith:/appsmith-stacks
|
||||
|
||||
api:
|
||||
build: .
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- ./assets:/app/assets
|
||||
- ./output:/app/output
|
||||
- ./temp:/app/temp
|
||||
- ./config:/app/config
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
- n8n
|
||||
```
|
||||
|
||||
10.3 远程访问
|
||||
|
||||
Tailscale:本地机器和其他设备安装Tailscale,登录同一账号。访问 http://<Tailscale IP>:80(Appsmith)和 http://<Tailscale IP>:5678(n8n)。
|
||||
|
||||
十一、环境变量清单
|
||||
|
||||
```bash
|
||||
# ========== 导演系统 ==========
|
||||
DIRECTOR_TYPE=storyboard_director_v52
|
||||
|
||||
# ========== TTS ==========
|
||||
TTS_PROVIDER=fish_audio
|
||||
FISH_AUDIO_API_KEY=
|
||||
FISH_AUDIO_VOICE_ID=
|
||||
ELEVENLABS_API_KEY=
|
||||
|
||||
# ========== 口播视频 ==========
|
||||
TALKING_HEAD_PROVIDER=d_id
|
||||
D_ID_API_KEY=
|
||||
D_ID_AVATAR_ID=
|
||||
HEYGEN_API_KEY=
|
||||
|
||||
# ========== 动作视频 ==========
|
||||
ACTION_PROVIDER=kling
|
||||
KLING_API_KEY=
|
||||
KLING_API_SECRET=
|
||||
WAN_ANIMATE_API_KEY=
|
||||
|
||||
# ========== 背景视频 ==========
|
||||
BACKGROUND_PROVIDER=tongyi_wanxiang
|
||||
TONGYI_API_KEY=
|
||||
SORA_API_KEY=
|
||||
|
||||
# ========== ComfyUI ==========
|
||||
COMFYUI_PROVIDER=runninghub
|
||||
RUNNINGHUB_API_KEY=
|
||||
RUNNINGHUB_WORKFLOW_ID=
|
||||
|
||||
# ========== 3D角色 ==========
|
||||
CHARACTER_3D_PROVIDER=hunyuan_3d
|
||||
HUNYUAN_3D_SECRET_ID=
|
||||
HUNYUAN_3D_SECRET_KEY=
|
||||
HUNYUAN_3D_REGION=ap-guangzhou
|
||||
|
||||
# ========== 特效 ==========
|
||||
VFX_BULLET_TIME_PROVIDER=wondershare_tianmu
|
||||
WONDERSHARE_TIANMU_API_KEY=
|
||||
VFX_CAMERA_PROVIDER=kling
|
||||
# 可灵camera_control参数在分镜Schema中动态传入
|
||||
|
||||
# ========== 本地路径 ==========
|
||||
ASSETS_DIR=./assets
|
||||
OUTPUT_DIR=./output
|
||||
TEMP_DIR=./temp
|
||||
|
||||
# ========== 去AI化默认参数 ==========
|
||||
DEAI_BLUR_SIGMA=0.4
|
||||
DEAI_GRAIN_INTENSITY=12
|
||||
DEAI_SATURATION_OFFSET=-0.12
|
||||
DEAI_TEMPERATURE_SHIFT=0.03
|
||||
DEAI_FRAME_BLEND=2
|
||||
|
||||
# ========== 服务端口 ==========
|
||||
API_PORT=8000
|
||||
N8N_PORT=5678
|
||||
APPSMITH_PORT=80
|
||||
```
|
||||
|
||||
十二、项目目录结构
|
||||
|
||||
```
|
||||
dcs/
|
||||
├── README.md
|
||||
├── docker-compose.yml
|
||||
├── .env.example
|
||||
├── requirements.txt
|
||||
├── start.sh
|
||||
├── stop.sh
|
||||
│
|
||||
├── config/
|
||||
│ ├── providers.yaml
|
||||
│ ├── templates/
|
||||
│ │ ├── vlog_hospital.yaml
|
||||
│ │ ├── product_ad.yaml
|
||||
│ │ └── daily_diary.yaml
|
||||
│ └── post_process.yaml
|
||||
│
|
||||
├── assets/
|
||||
│ ├── characters/
|
||||
│ ├── characters_3d/
|
||||
│ ├── locations/
|
||||
│ ├── real_locations/
|
||||
│ ├── products/
|
||||
│ ├── props/
|
||||
│ ├── bgm/
|
||||
│ ├── sfx/
|
||||
│ └── vfx_presets/
|
||||
│
|
||||
├── src/
|
||||
│ ├── main.py
|
||||
│ ├── schemas.py
|
||||
│ │
|
||||
│ ├── director/
|
||||
│ │ ├── base.py
|
||||
│ │ ├── storyboard_director.py
|
||||
│ │ └── adapter.py
|
||||
│ │
|
||||
│ ├── orchestrator/
|
||||
│ │ ├── dispatcher.py
|
||||
│ │ └── task_manager.py
|
||||
│ │
|
||||
│ ├── providers/
|
||||
│ │ ├── base.py
|
||||
│ │ ├── tts/
|
||||
│ │ │ ├── fish_audio.py
|
||||
│ │ │ └── elevenlabs.py
|
||||
│ │ ├── talking_head/
|
||||
│ │ │ ├── d_id.py
|
||||
│ │ │ └── heygen.py
|
||||
│ │ ├── action/
|
||||
│ │ │ ├── kling.py
|
||||
│ │ │ └── wan_animate.py
|
||||
│ │ ├── background/
|
||||
│ │ │ ├── tongyi_wanxiang.py
|
||||
│ │ │ └── sora.py
|
||||
│ │ ├── comfyui/
|
||||
│ │ │ └── runninghub.py
|
||||
│ │ ├── character_3d/
|
||||
│ │ │ ├── hunyuan_3d.py
|
||||
│ │ │ └── flow_studio.py
|
||||
│ │ └── vfx/
|
||||
│ │ ├── wondershare_tianmu.py
|
||||
│ │ ├── hailuo.py
|
||||
│ │ └── kling_vfx.py
|
||||
│ │
|
||||
│ ├── compositor/
|
||||
│ │ ├── de_ai.py
|
||||
│ │ ├── concat.py
|
||||
│ │ └── ffmpeg_utils.py
|
||||
│ │
|
||||
│ ├── assets_manager/
|
||||
│ │ ├── loader.py
|
||||
│ │ └── validator.py
|
||||
│ │
|
||||
│ └── utils/
|
||||
│ ├── logger.py
|
||||
│ ├── retry.py
|
||||
│ └── file_utils.py
|
||||
│
|
||||
├── n8n/
|
||||
│ └── workflow.json
|
||||
│
|
||||
├── appsmith/
|
||||
│ └── application.json
|
||||
│
|
||||
├── output/
|
||||
├── temp/
|
||||
│
|
||||
└── tests/
|
||||
├── test_schemas.py
|
||||
├── test_director.py
|
||||
├── test_providers.py
|
||||
├── test_compositor.py
|
||||
└── fixtures/
|
||||
└── sample_storyboard.json
|
||||
```
|
||||
|
||||
十三、开发路线图
|
||||
|
||||
阶段 目标 交付物
|
||||
阶段1:手动验证 用现有API跑通一条20秒测试片 分镜JSON、测试视频、去AI化参数
|
||||
阶段2:本地环境 部署n8n + Appsmith + FFmpeg 可访问的控制台
|
||||
阶段3:导演系统接入 导演系统输出统一Schema 分镜编辑页面可用
|
||||
阶段4:n8n工作流 串联TTS+口播+背景+FFmpeg 自动生成第一条成片
|
||||
阶段5:3D角色+特效 接入混元3D + 万兴天幕/可灵运镜 3D角色和特效可用
|
||||
阶段6:ComfyUI接入 RunningHub API调用 精细控制镜头
|
||||
阶段7:批量生产 循环分镜表,批量输出 批量任务队列
|
||||
阶段8:优化迭代 调参、换API、迁移服务器 稳定生产系统
|
||||
|
||||
十四、AI编程工具执行清单
|
||||
|
||||
```
|
||||
请按以下顺序生成项目代码:
|
||||
|
||||
1. 创建项目根目录结构(mkdir -p dcs/src/...)
|
||||
2. requirements.txt(fastapi, uvicorn, pydantic, requests, pyyaml, ffmpeg-python)
|
||||
3. .env.example(按第十一节)
|
||||
4. src/schemas.py(按第四节)
|
||||
5. src/director/base.py + storyboard_director.py + adapter.py
|
||||
6. src/providers/base.py
|
||||
7. src/providers/tts/fish_audio.py
|
||||
8. src/providers/talking_head/d_id.py
|
||||
9. src/providers/action/kling.py(含camera_control参数支持)
|
||||
10. src/providers/background/tongyi_wanxiang.py
|
||||
11. src/providers/comfyui/runninghub.py
|
||||
12. src/providers/character_3d/hunyuan_3d.py
|
||||
13. src/providers/vfx/wondershare_tianmu.py
|
||||
14. src/providers/vfx/hailuo.py
|
||||
15. src/providers/vfx/kling_vfx.py
|
||||
16. src/compositor/de_ai.py + concat.py + ffmpeg_utils.py
|
||||
17. src/assets_manager/loader.py + validator.py
|
||||
18. src/orchestrator/dispatcher.py + task_manager.py
|
||||
19. src/main.py
|
||||
20. src/utils/logger.py + retry.py
|
||||
21. docker-compose.yml
|
||||
22. start.sh
|
||||
23. config/providers.yaml + templates/vlog_hospital.yaml
|
||||
24. tests/test_schemas.py + fixtures/sample_storyboard.json
|
||||
25. n8n/workflow.json
|
||||
26. appsmith/application.json(可先留框架)
|
||||
|
||||
生成后运行 pytest 确保测试通过。
|
||||
所有API Key从环境变量读取,不硬编码。
|
||||
所有异步API调用使用统一的 poll_until_complete 轮询逻辑。
|
||||
所有Provider继承 BaseProvider,实现 generate(shot, assets) -> dict 方法。
|
||||
```
|
||||
|
||||
十五、需团队手动完成的事项
|
||||
|
||||
事项 操作
|
||||
注册API Fish Audio、D-ID、可灵、通义万相、RunningHub、混元3D、万兴天幕
|
||||
填写.env 把Key填入.env文件
|
||||
导入n8n工作流 n8n界面 → Import from File
|
||||
导入Appsmith应用 Appsmith界面 → Import Application
|
||||
准备角色参考图 放入assets/characters/char_001/
|
||||
准备产品参考图 放入assets/products/
|
||||
在RunningHub搭建工作流 导入社区工作流或手动搭建,发布为API工作流
|
||||
跑第一条测试 在控制台输入故事,点击生成
|
||||
|
||||
十六、导演操作流程(日常使用)
|
||||
|
||||
```
|
||||
1. 打开浏览器 → http://localhost
|
||||
2. 在分镜编辑页输入故事大纲
|
||||
3. 选择内容类型(产品广告/个人日记/场景短剧)
|
||||
4. 选择角色(2D参考图 或 3D绑定模型)
|
||||
5. 选择场景/场地/产品
|
||||
6. 点击“生成分镜” → 导演系统返回分镜表
|
||||
7. 逐条检查/修改 → 可添加特效(子弹时间/环绕运镜等)
|
||||
8. 点击“提交任务”
|
||||
9. n8n自动调用各API生成片段
|
||||
10. FFmpeg自动去AI化+拼接
|
||||
11. 刷新页面 → 预览成片
|
||||
12. 不满意 → 修改对应镜头参数 → 重试单条
|
||||
```
|
||||
Reference in New Issue
Block a user