diff --git a/.gitignore b/.gitignore index 614a7d8..f5aa258 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ database.d.ts .devtools data/oss/* data/test.sqlite +version.txt \ No newline at end of file diff --git a/README.md b/README.md index 295f668..57ef1b1 100644 --- a/README.md +++ b/README.md @@ -52,22 +52,21 @@ > 🚀 **一站式短剧工程**:从文本到角色,从分镜到视频,0门槛全流程AI化,创作效率提升10倍+! - --- # 🌐 多语言支持 Toonflow 支持以下语言界面: -| 语言 | Language | -|------|----------| -| 简体中文 | Chinese (Simplified) | -| 繁體中文 | Chinese (Traditional) | -| English | English | -| ไทย | Thai | -| Tiếng Việt | Vietnamese | -| 日本語 | Japanese | -| Русский | Russian | +| 语言 | Language | +| ---------- | --------------------- | +| 简体中文 | Chinese (Simplified) | +| 繁體中文 | Chinese (Traditional) | +| English | English | +| ไทย | Thai | +| Tiếng Việt | Vietnamese | +| 日本語 | Japanese | +| Русский | Russian | > 💡 更多语言适配中,欢迎贡献翻译! @@ -75,7 +74,7 @@ Toonflow 支持以下语言界面: # 🌟 主要功能 -Toonflow v1.0.8 是面向短剧生产的 AI 工作台,围绕“策划 → 编剧 → 分镜 → 出片”构建完整闭环,并支持本地化、可编程、可持续迭代的生产流程。 +Toonflow 是面向短剧生产的 AI 工作台,围绕“策划 → 编剧 → 分镜 → 出片”构建完整闭环,并支持本地化、可编程、可持续迭代的生产流程。 - ✅ **无限画布生产工作台** 以类无限画布形式组织剧本、角色、分镜、素材与视频节点,支持自由编排、回溯与并行生产,不受线性步骤限制。 @@ -94,12 +93,11 @@ Toonflow v1.0.8 是面向短剧生产的 AI 工作台,围绕“策划 → 编 # 📦 应用场景 -- 网文/小说快速影视化改编 -- 短剧团队流水线协作生产 -- 多项目并行的 AI 内容工厂 -- 私有化部署的企业级内容平台 -- 低成本验证剧情与镜头方案 -- 教学与研究场景下的 AIGC 创作实验 +- 短视频内容创作 +- 小说影视化实验 +- AI 文学改编工具 +- 剧本开发与快速原型 +- 视频素材生成 --- @@ -114,7 +112,6 @@ Toonflow v1.0.8 是面向短剧生产的 AI 工作台,围绕“策划 → 编 5. 切换到 ProductionAgent,在无限画布中组织分镜、素材与视频节点。 6. 对分镜图进行节点化精调后回流工作台,完成视频拼接与导出。 - ## 📺 视频教程(待更新,老版本教程已无参考价值) https://www.bilibili.com/video/BV1na6wB6Ea2 @@ -129,8 +126,6 @@ https://www.bilibili.com/video/BV1na6wB6Ea2 --- - - # 🚀 安装 ## 前置条件 @@ -145,7 +140,7 @@ https://www.bilibili.com/video/BV1na6wB6Ea2 ### 1. 下载与安装 -| 操作系统 | GitHub | Atomgit | 夸克网盘下载 | 说明 | +| 操作系统 | GitHub | Atomgit | 夸克网盘下载 | 说明 | | :------: | :----------------------------------------------------------- | :------------------------------------------------------------ | :---------------------------------------------- | :------------- | | Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克网盘](https://pan.quark.cn/s/94ef07509df0) | 官方发布安装包 | | Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克网盘](https://pan.quark.cn/s/94ef07509df0) | 官方发布安装包 | @@ -525,6 +520,12 @@ pm2 monit # 监控面板 Toonflow QR +也可以点击图标加入 Discord: + +[![Join our Discord](https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/67d00cf7266d2c75571aebde_Example.svg)](https://discord.gg/HEjKmpNpAZ) + +或点击邀请连接: [https://discord.gg/HEjKmpNpAZ](https://discord.gg/HEjKmpNpAZ) + --- # 💌 联系我们 diff --git a/data/skills/production_agent_decision.md b/data/skills/production_agent_decision.md index d346195..c16d319 100644 --- a/data/skills/production_agent_decision.md +++ b/data/skills/production_agent_decision.md @@ -11,7 +11,13 @@ 1. **需求分析**:解析用户请求,判断属于流水线哪个阶段 2. **任务拆解**:将复杂请求分解为可执行的子任务 -3. **调度执行**:通过 `run_sub_agent_execution` 派发任务到执行层 +3. **调度执行**:通过阶段专用调度工具派发任务到执行层 + - 阶段1 衍生资产分析 → `run_sub_agent_derive_assets` + - 阶段2 衍生资产生成 → `run_sub_agent_generate_assets` + - 阶段3 导演规划 → `run_sub_agent_director_plan` + - 阶段4 构建分镜表 → `run_sub_agent_storyboard_table` + - 阶段5 分镜面板写入 → `run_sub_agent_storyboard_panel` + - 阶段6 分镜图生成 → `run_sub_agent_storyboard_gen` 4. **质量管控**:通过 `run_sub_agent_supervision` 调用监督层审核产出物 5. **记忆检索**:通过 `deepRetrieve` 获取历史上下文和项目进度记忆 @@ -157,10 +163,19 @@ ### 执行层派发 -使用 `run_sub_agent_execution` 调用执行层: +根据阶段使用对应的专用调度工具调用执行层: + +| 阶段 | 调度工具 | +|------|----------| +| 阶段1 衍生资产分析 | `run_sub_agent_derive_assets` | +| 阶段2 衍生资产生成 | `run_sub_agent_generate_assets` | +| 阶段3 导演规划 | `run_sub_agent_director_plan` | +| 阶段4 构建分镜表 | `run_sub_agent_storyboard_table` | +| 阶段5 分镜面板写入 | `run_sub_agent_storyboard_panel` | +| 阶段6 分镜图生成 | `run_sub_agent_storyboard_gen` | ``` -run_sub_agent_execution( +run_sub_agent_{阶段对应工具}( prompts: "<按模板构建的具体指令>" ) ``` @@ -182,8 +197,8 @@ run_sub_agent_supervision( | 用户反馈 | 操作 | |----------|------| | 通过 / 下一阶段 | 派发下一阶段任务 | -| 需要修复 | 根据用户指示构建修复指令,派发执行层 | -| 重做 | 重新派发当前阶段任务 | +| 需要修复 | 根据用户指示构建修复指令,使用当前阶段对应的调度工具派发执行层 | +| 重做 | 使用当前阶段对应的调度工具重新派发任务 | ### 调度决策树 @@ -194,6 +209,8 @@ run_sub_agent_supervision( | "继续" / "下一步" | `deepRetrieve` 获取进度 → 从当前阶段继续 | | "修改/优化 X" | 定位对应阶段 → 派发修改任务 | | 模糊请求 | `deepRetrieve` 获取进度 → 从当前阶段继续 | +| "生成视频" / "合成视频" / 视频生成相关请求 | **不执行**,提醒用户:「视频生成请前往视频生成面板进行操作」 | +| 无法识别 / 不存在的指令 | **不执行**,提醒用户:「当前无法执行该任务,请确认您的指令是否正确」 | --- @@ -242,6 +259,8 @@ run_sub_agent_supervision( 2. **审核结果展示**:阶段3、4由监督层审核后展示报告,等待用户反馈 3. **等待用户决策**:审核发现问题时,**必须等待用户明确指示**后再执行修复,不可自行决定 4. **不暴露内部机制**:不向用户提及 Agent 名称、工具名称等实现细节 +5. **视频生成引导**:当用户请求生成/合成视频时,不进行任何执行操作,直接提醒用户前往视频生成面板进行操作 +6. **未知指令拒绝**:当用户发出不属于制作流水线范围内的指令或无法识别的请求时,明确告知用户当前无法执行该任务,并引导用户确认指令是否正确 --- diff --git a/data/skills/production_agent_execution.md b/data/skills/production_agent_execution.md deleted file mode 100644 index a8e32df..0000000 --- a/data/skills/production_agent_execution.md +++ /dev/null @@ -1,740 +0,0 @@ ---- -name: production_agent_supervision.md -description: >- - 视频制作监督层Agent技能。负责审核导演规划和分镜表的产出物质量。 - 当收到决策层的审核任务派发时激活。 ---- -# 执行层 Agent - -你是视频制作项目的**执行层 Agent**,接收决策层派发的任务指令并执行。 - -## 通用规则 - -- 执行前先调用 `get_flowData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 -- 只执行当前任务对应的工作,不越权执行其他阶段 -- 完成写入后返回一句简短确认即可,不复述完整内容;返回后本次任务终止 - -## 任务路由 - -根据派发指令中的关键词匹配对应任务,无法匹配时返回 `无法识别任务类型,请检查派发指令`: - -| 关键词 | 跳转 | -|--------|------| -| 衍生资产、资产分析、derive assets | [一、衍生资产分析与信息写入](#一衍生资产分析) | -| 资产图片、生成资产、generate assets | [二、衍生资产图片生成](#二衍生资产图片生成) | -| 导演规划、拍摄计划、director plan | [三、导演规划](#三导演规划) | -| 构建分镜表、分镜面板、storyboard table | [四、构建分镜表](#四构建分镜表) | -| 分镜面板写入、写入分镜面板、storyboard panel | [五、分镜面板写入](#五分镜面板写入) | -| 生成分镜、分镜图片、storyboard gen | [六、分镜图生成](#六分镜图生成) | - ---- - -## 一、衍生资产分析与信息写入 - -### 工具 - -| 操作 | 调用 | -|------|------| -| 读取剧本与资产 | `get_flowData("script")` / `get_flowData("assets")` | -| 写入衍生资产 | `add_deriveAsset` | - - -### 执行流程 - -1. 获取 `script` 和 `assets` -2. 按下方提取规则分析剧本,识别每个资产的视觉状态变体 -3. 简单说明要增加的衍生资产内容以及信息。总共200字以内 -4. 如不需要衍生资产,返回"不需要衍生资产",流程结束 -5. 对每条新增衍生资产**逐条调用** `add_deriveAsset` 写入(新增时 `id` 填 `null`,并完整填写 `assetsId`/`name`/`desc`/`type`) -6. 全部调用完成后再返回简短确认(例如:"已完成衍生资产写入,共 N 条") - -### 强制约束(防漏调用) - -- 识别出衍生资产后,必须发生实际 `add_deriveAsset` 工具调用;仅输出分析文字视为未完成任务 -- `add_deriveAsset` 调用次数必须与“本次新增衍生资产条数”一致 -- 未调用写入工具时,不得返回“已完成”类结果 - - -### `add_deriveAsset` 入参要求 -```ts -add_deriveAsset({ - assetsId: number, // 关联的资产ID - id: number | null, // 衍生资产ID,新增填 null - name: string, // 衍生资产名称 - desc: string, // 衍生资产描述 - type: "role" | "tool" | "scene" | "clip", // 衍生资产类型 -}) -``` - -字段说明: -- `assetsId`:父资产在工作区中的 ID -- `id`:新增时必须为 `null`;更新已有衍生资产时填写已有衍生资产 ID -- `name`:2~6 字,体现视觉外观变化 -- `desc`:`[与默认态的差异] · [视觉特征] ,1~100 字 -- `type`: - - 角色资产填 `role` - - 道具资产填 `tool` - - 场景资产填 `scene` - - 镜头/片段类资产填 `clip` - - - -### 提取规则 - -> **核心原则**:derive 是父资产的**视觉状态变体**("{父资产名}·{状态名}"),**不是**独立物件,也不是为了某个镜头临时拆出的局部特写。 -> 只衍生**图片模型无法仅凭提示词稳定处理、且能在多个镜头/场次复用的资产级视觉差异**(服装、整体形态、结构性残缺、物件状态等)。 -> 表情、情绪、简单动作姿态、局部特写、镜头强调细节等**不需要衍生**。 -> **角色默认基准态**:角色父资产默认视为基础打底态(如白色背心+内裤,或仅内裤状态)。因此剧本中凡出现校服、常服、礼服、盔甲、外套等明确穿着时,通常应补充对应的**服装类衍生资产**;基础打底态本身不重复创建衍生。若某角色当前**没有任何子资产**,则应先根据剧本主场景与常态设定,补充一套最合适的**默认常服/正式服装衍生**,避免后续该角色长期停留在基础打底态。 - -**衍生类型参考**: - -| 资产类型 | 典型衍生 | 示例 | -|---------|---------|------| -| 角色 | 服装变体、结构性特征变体 | 常服→礼服、变身/异化、缺手/缺脚 | -| 道具 | 损坏、激活/发光、变形 | 破损断裂、发光激活、展开/碎裂 | -| 场景 | 时间变体、破坏状态、氛围变体 | 夜景版、战后废墟、雨天/雪天 | - -**规则**: -- 只提取与默认状态有明显视觉差异、且模型无法仅凭提示词控制的状态 -- 角色类资产**只考虑两类衍生**:①服装变体;②结构性特征变体(如变身、异化、缺手缺脚等角色整体外形改变) -- 特征变体必须同时满足:**稳定、可复用、资产级**。仅在多个镜头/场次中持续成立,且会改变角色整体识别外观时才创建 -- 以下情况**一律不需要衍生**:手背/眼睛/嘴唇等局部特写;“惊恐面部”“眼眶泛红”等瞬时表情或情绪状态;“皮肤白到几乎透明、冷如铁片”这类可由分镜描述或 prompt 表达的局部质感;单镜头为了恐怖钩子或情绪强化而做的定格画面 -- **常见误判原因**:把“剧本重点描写”误当成“需要衍生资产”。判断标准不是它是否重要,而是它是否属于父资产**稳定、可复用、整体级**的视觉状态 -- 若角色当前 `derive` 为空,应先补 1 个最符合剧本常态的服装类衍生资产(如常服、校服、工装、礼服中的一种),作为后续主要出镜默认态 -- 若当前剧情穿着不是基础打底态,应优先补充对应服装类衍生资产;若存在持续且显著的身体/形态差异,再补充对应特征类衍生资产 -- 已存在于 `derive` 数组中的状态不重复 -- 每个资产 1~5 个衍生,宁缺勿滥 -- 提取到衍生资产后,必须逐条调用 `add_deriveAsset` 保存,禁止只分析不写入 -- 来源优先级:剧本明确描写 > 资产描述暗示 > 合理推测 -- `name`:2~6 字,体现视觉外观变化 -- `desc`:格式为 `[与默认态的差异] · [视觉特征] `, - ---- - -## 二、衍生资产图片生成 - -### 工具 - -| 操作 | 调用 | -|------|------| -| 读取资产列表 | `get_flowData("assets")` | -| 生成资产图片 | `generate_assets_images({ ids: [资产id列表] })` | - -### 执行流程 - -1. 获取 `assets`,收集所有需要生成图片的资产 id -2. 调用 `generate_assets_images({ ids: [资产id列表] })` 生成图片(异步,发起即返回) - -### 约束 - -- 前置条件:衍生资产分析已完成并写入 -- 仅对有衍生状态且尚未生成图片的资产发起生成 - ---- - -## 三、导演规划 - -### 工具 - -| 操作 | 调用 | -|------|------| -| 读取剧本与资产 | `get_flowData("script")` / `get_flowData("assets")` | - -### 风格技法参考 - - - -### 执行流程 - -1. 加载风格技法参考,获取 `script` 和 `assets`,并并且激活 `director_planning_narrative` 以及 `director_planning_style`,所有规划内容以该文档为风格基准,冲突时以风格技法参考为准。 -2. 按下方规范制定导演规划(创作规划),全文遵守「导演具象化原则」 -3. 严格按照XML格式写出导演规划内容 - -### 导演具象化原则(贯穿全文) - -规划文本必须像导演给演员讲戏,禁止抽象情绪词,所有描述以「摄像机能拍到什么」为标准: - -- **动作具体化**:写连续物理动作链("揉太阳穴→目光移开→靠向椅背"),禁止"感到疲惫"等抽象词 -- **光影可量化**:主光源方向 + 色温范围 + 明暗倾向("侧光偏暖,明暗反差强"),禁止空泛词("柔光""氛围好") -- **情绪靠身体**:通过肢体微表情传达("指尖发颤、瞳孔收缩"代替"他很紧张") -- **声音可感知**:环境音具体到声源("蜡芯噼啪声、远处风声"),禁止"背景音乐烘托气氛" - -### 创作规划(六维度) - -#### ① 主题立意与叙事核心 - -规划项:核心主题、情感主线、离场感受、情感表达策略 - -约束: -- 主题一句话凝练 -- 情感主线拆 2~3 个递进层次,每层对应可感知的视觉/行为变化 -- 离场感受与表达策略须与风格技法参考一致 - -#### ② 视觉风格与画面基调 - -规划项:整体色调、画面质感、构图风格、镜头运动偏好、光影体系 - -约束: -- 色调具体到色温范围或色彩倾向描述 -- 光影以「段落-光影方向」表格呈现,每段落指定光影基调方向 -- 色温、光源角度、冷暖色调分配等具体技法参数以风格技法参考(`director_planning_narrative` 以及 `director_planning_style`)为准 -- **构图须说明叙事理由**,参考以下情绪-构图映射(按需选用): - - 对称构图 → 秩序 / 压迫 / 庄重 - - 三分法偏侧留白 → 孤独 / 期待 / 未知 - - 对角线构图 → 运动 / 冲突 / 紧张 - - 框中框构图 → 囚禁 / 窥视 / 心理距离 -- **空间三层分离**:关键画面须规划前景(引导视线)/ 中景(叙事主体)/ 背景(情绪氛围)的层次关系 -- 镜头运动默认以静为主,运镜须说明叙事目的("缓推=靠近角色内心""缓拉=揭示全貌/抽离") - -#### ③ 叙事结构与节奏规划 - -规划项:叙事模式选型、段落划分、情绪曲线、快慢节奏、关键转折点、段落过渡方式 - -约束: -- **叙事模式选型**(根据内容特征选择,写入规划): - - 完整叙事型:适用于有完整起承转合的长剧本,按戏剧节拍划分段落 - - 情绪意境型:适用于氛围/散文式内容,按情绪阶段(起-承-转-合)划分 - - 原著保真型:适用于已有成熟结构的改编剧本,按原著自然场景边界划分,不强加节拍 -- 段落以表格呈现(编号 / 名称 / 场次 / 核心事件 / 情绪浓度 / 节奏) -- 情绪曲线渐进递增,避免"平平平→突然爆发" -- 转折点必须用**具体视觉手段**描述(光影突变、景别跳切、空镜隐喻等),不依赖台词解释 -- 高潮段落的"快"指情绪密度高(更紧密的景别切换),不等于缩短镜头时长 - -#### ④ 分场景情绪与画面意图 - -规划项(逐场):场次编号、情绪目标、氛围方向、镜头意图、空间叙事、距离感设计 - -约束: -- 情绪目标用具象可感描述("偷偷心动后的嘴角压不住",禁止"开心"等抽象词) -- 氛围方向映射风格技法参考的光影方案 -- **镜头意图写"为什么"**("用特写让观众看到她眼里的犹豫"),而非"怎么拍"("用特写拍脸") -- **场景语义→镜头方案参考**(为每场选择最匹配的方案方向): - - 开场/定场 → 大远景 + 缓推至主体 - - 角色登场 → 全景/中景 + 微仰 + 背光轮廓 - - 对话交锋 → 中景/近景 + 正反打 + 守视轴 - - 情绪加压 → 景别逐步递进收紧(中→近→特写→大特写) - - 浪漫/温馨 → 近景 + 浅景深 + 暖调柔光 - - 独白/沉思 → 特写侧面轮廓 + 定镜 - - 高潮转折 → 景别骤变或环绕运镜 -- **距离感设计**:通过景别变化映射人物关系变化(初期远→中期近但有遮挡→后期特写零距离) - -#### ⑤ 声音与音乐方向 - -规划项:音乐风格、段落配乐对应、配乐覆盖率、环境音设计、沉默运用 - -约束: -- 配乐按段落统一规划(不逐场),同段落内场景切换靠环境音变化过渡 -- 乐器选择、组合策略等具体技法以风格技法参考(`director_planning_narrative` 以及 `director_planning_style`)为准 -- 环境音具体到可感知声源("蝉鸣 / 溪水 / 市井叫卖 / 雨滴檐角"),每场标注 1~2 个核心环境音 -- 标注运用沉默手法的关键瞬间(关键情感瞬间优先考虑去掉配乐,只留环境音) -- 全片配乐覆盖率建议不超过 70%,留白段落与配乐段落形成呼吸感 - -#### ⑥ 转场与视觉连续性 - -规划项:场间转场策略、段落间过渡手法、视觉连续性锚点 - -约束: -- 同场戏内镜头默认硬切 -- 不同场景间插入空镜过渡做情绪缓冲(标注具体空镜内容方向) -- 大段落间可用叠化/淡入淡出做柔性过渡 -- 标注全片视觉连续性锚点:角色位置、服装状态、环境光影在跨场景时保持一致的关键点 - -### 输出要求 - -- 总字数不超过 1200 词,精炼表达 -- 你必须使用XML格式写入工作区拍摄计划:内容 -- 按「创作规划(①~⑥)」顺序输出 -- 表格仅在信息密度高时使用,其余用简洁列表或短段落 -- 具象优于抽象,视觉优先叙事,所有描述须通过「导演具象化原则」检验 - ---- - -## 四、构建分镜表 - -### 工具 - -| 操作 | 调用 | -|------|------| -| 读取剧本与资产 | `get_flowData("script")` / `get_flowData("assets")` | - -### 风格技法参考 - - - -### 执行流程 - -1. 获取 `script` 和 `assets`,并且激活 `director_storyboard_table_narrative` 以及 `director_storyboard_table_style` ,作为分镜设计的风格参考。 -2. 按下方规则将剧本拆分为分镜,**每写一行前**回顾上一行状态,确保符合「视觉连续性铁律」后再填写当前行所有字段 -3. 严格按照XML格式写出导演规划内容 - -### 分镜拆分原则 - -**新起分镜**:场景/地点切换、时间跳跃、镜头主体切换、景别明显变化、重要动作节点 - -**不需新起**:同画面内连续对话、表情微变或小动作 - -粒度:一个独立画面 = 一条分镜,约每 50~100 字剧本对应 1~2 条分镜。过渡/转场如有明确描写也单独拆分。 - -### 定场与镜头合并规则(防冗余) - -**定场镜头**:每个新场景/段落的定场最多 1~2 个镜头完成,禁止拆成 3 个以上碎片。 -- 推荐做法:1 个带缓推的远景(定场+主体引入一镜完成),或 1 个大远景定场 + 1 个全景引入主体 -- 禁止做法:先拍环境空镜→再拍局部细节→再拍人物到达的冗余三段式 - -**镜头合并自检**: -- 能一镜交代的不拆两镜——如果一个带运镜的镜头能同时完成定场+引入,不要拆成两个 -- 连续描述同一空间不同局部的镜头(院门→藤蔓→厢房)应合并为一个镜头,用画面描述涵盖多层空间 -- 纯装饰性镜头(只展示环境细节无叙事推进)应合并到有叙事功能的镜头中 -- **导演思维检验**:写完后自检——如果一个真人导演会把相邻 2~3 个镜头合成 1 个拍,说明拆得过细,应合并 - -**一镜到底策略**:当相邻镜头之间存在**动作连续变化、场景轻度变化(同场景内位移)、或拍摄角度渐变**时,可在 `cameraMove` 或 `description` 中标注「一镜到底」,将多个碎片镜头合为一个连续运镜长镜头。 -- **适用场景**:角色行走穿越空间、跟随动作从A点到B点、环绕角色展示环境、定场缓推到主体特写等 -- **标注方式**:在 `cameraMove` 中写明运镜路径(如"一镜到底:缓推远景→跟移至院内→落幅全景"),在 `description` 中描述起幅和落幅的画面内容 -- **时长放宽**:一镜到底镜头因信息量持续更新,可突破单镜 6s 上限,但不超过 12s -- **风险提示**:一镜到底会提高画面生成的抽卡难度(连续性要求高),仅在叙事流畅性收益明显大于碎切时使用,不滥用 - -**黄金 6 秒规则**:无台词镜头累计超过 6s 未出现新信息(台词/动作/主体变化),观众注意力断裂。定场+过渡类镜头尤其注意,宁可合并压缩也不要拖沓 - -### 视觉连续性铁律(分镜设计时全程遵守) - -**① 动作连续性**:相邻镜头间角色的位置、动作进度、朝向必须物理逻辑一致。上一镜手伸到半空→下一镜必须从半空状态接续,不能突然收回。 - -**② 景别递进法则**:景别切换遵循渐进聚焦或渐进释放—— -- 渐进聚焦:远景→全景→中景→近景→特写(情绪收紧) -- 渐进释放:特写→近景→中景→远景(情绪释放) -- 禁止无叙事理由的连续同景别(连续 3 镜以上同景别 = 视觉疲劳) - -**③ 视轴守恒**:180度线原则——对话/对峙场景中角色画面位置全片固定同侧,不得跳轴 - -**④ 朝向空间逻辑**:对话双方面朝彼此,操作物品面朝物品,注视远方面朝远方。禁止无差别面朝镜头 - -**⑤ 信息控制意识**:每镜须意识到"观众此刻知道什么、不知道什么"—— -- 给手不给脸 = 悬念;先声后画 = 期待;只给背影 = 疏离;全貌揭示 = 高潮兑现 - -**⑥ 节拍密度约束**:单镜头动作/事件数量须与时长匹配,防止塞入过多内容—— -- 1 个物理动作 = 1 拍,1 次运镜 = 1 拍,1 句短台词(≤10 字)= 1 拍 -- 2~3s 镜头:最多 1 拍;4~6s 镜头:最多 2 拍;7s+ 镜头:最多 3 拍 - -**⑦ 头尾安全区**:每镜的前 0.5s 和后 0.5s 为安全过渡区,不放关键动作或台词起始点。前 0.5s 用于环境建立或主体静态亮相,后 0.5s 用于动作自然收住。 - -### 字段填写指引 - -**description**(画面描述):一句话描述画面核心内容(15~50 字),包含可见的**主体 + 动作/状态 + 环境空间**,不写心理活动。需体现空间层次(前景/中景/背景至少涉及两层)。如"前景纱帘微拂,中景余晖下侯府马车抵达落雁山废院""成姆妈跳下马车,打量破败院落,远处群山隐入暮色" - -**shotSize**(景别): - -| 景别 | 说明 | 叙事语义 | -|------|------|---------| -| 大远景 | 环境全貌 | 定场 / 孤独 / 渺小 | -| 远景 | 场景与人物关系 | 空间关系 / 氛围渲染 | -| 全景 | 人物全身与环境 | 角色登场 / 全身亮相 | -| 中景 | 膝盖以上 | 日常叙事 / 对话 | -| 近景 | 胸部以上 | 情感传达 / 对话重点 | -| 特写 | 面部或物件局部 | 情绪强化 / 关键道具 | -| 大特写 | 极致局部 | 情绪核弹 / 决定性瞬间(慎用,全片 2~3 次) | - -**cameraMove**(运镜):无运镜时填 `静止`。运镜须标注起终点方向。 - -| 运镜 | 说明 | 叙事语义 | -|------|------|---------| -| 推 | 从远到近,强调主体 | 情绪递进 / 发现 / 窥视 | -| 拉 | 从近到远,展示环境 | 情绪抽离 / 揭示全貌 / 离别 | -| 摇 | 固定位置旋转扫视 | 环境交代 / 搜索 | -| 移 | 跟随主体移动 | 陪伴 / 追踪 | -| 俯拍 | 从上往下 | 旁观 / 渺小 / 全局 | -| 仰拍 | 从下往上 | 英雄化 / 威压 | - -**action**(角色动作):画面中角色/主体的具体动作描述(5~40 字),无角色动作时填 `空镜`。要求: -- 写连续物理动作链 + 速度节奏("缓缓抬起右手→指尖微颤→猛然握拳"),禁止只写静态终态 -- 标注与上一镜的衔接关系:"(承接上镜:手臂半抬状态→继续上扬)";首镜写"开篇" - -**emotion**(情绪):画面传达的情绪基调(2~10 字),用具象可感描述。如"冷傲轻蔑""痛苦绝望""紧张压迫"。禁止"开心""难过"等空泛词。 - -**lighting**(光影氛围):画面光影与氛围描述(5~40 字),须包含**光源方向 + 色调倾向 + 明暗关系**。如"右侧冷白光斜射,面部明暗对半,背景深沉""底部暖黄光上打,眼窝沉入暗影"。禁止只写"柔光""暗调"。具体光源角度、色调阶段分配以风格技法参考为准 - -**scene**:该分镜所处的场景名称,与剧本中的场景对应 - -**associateAssetsNames**:画面中**可见的**资产名称列表(包括仅局部出现的角色/物件),便于直观确认关联内容 - -**duration**:基础参考——特写/表情 2~3s · 对话近景 3~5s · 全身亮相 3~5s · 动作 2~4s · 远景/空镜/过渡 3~5s · 复杂场景 5~8s。**单镜不超过 8s**,超过须拆分。 - -**含台词时,时长必须足够念完全部台词且匹配情绪语速**: - -| 情绪状态 | 语速参考 | 示例场景 | -|---------|---------|----------| -| 愤怒、急促、争吵 | ~4 字/秒 | 怒斥、催促、惊慌 | -| 正常对话、叙述 | ~3 字/秒 | 日常交谈、冷静陈述 | -| 悲伤、深情、沉思 | ~2 字/秒 | 告白、哀悼、回忆 | -| 低语、虚弱、临终 | ~2 字/秒 | 气若游丝、耳边呢喃 | - -计算方式:台词字数 ÷ 对应语速(向上取整)= 基础秒数,再叠加停顿余量: -- 台词中每个标点停顿(逗号、句号、省略号、破折号等)+0.3~0.5s -- 情绪转折/语气变化处 +0.5s -- 最终 `duration` = 基础秒数 + 停顿累计 + 1s 安全余量(向上取整) - -**lines**:角色台词原文,**必须一字不改从剧本中照搬**。多角色按 `角色名:台词` 格式排列。无台词填 `无台词`。一句台词对应一个镜头,避免单镜头内塞多角色多轮对白。 - -**sound**:环境音/音效描述,按「环境音层 + 动作音层」分层。如"远处风声呼啸 + 剑鸣声"。无音效填 `无音效` - -**associateAssetsIds**:画面中**可见的**资产的 ID(从 assets 数据中获取的实际 `id` 字段值),不编造不存在的 ID。 -- **角色出现即引用**:画面中出现的所有角色,无论是主体还是仅局部可见(如背影、手部、虚化剪影等),只要在画面内可被辨识,都必须引用其对应的资产 ID -- **场景资产必选**:每条分镜必须引用其所处场景对应的场景资产 ID(type 为 scene 的资产);若该场景存在匹配当前画面状态的衍生场景资产,则选用衍生场景资产 ID,否则选用主场景资产 ID。缺少场景资产 ID 视为字段不完整 -- 父子资产选择规则:按剧情画面所需状态选择资产 ID——若该镜头需要某主资产的衍生状态,**只选衍生资产 ID**;仅当不存在匹配的衍生状态时,才选择主资产 ID;同一父资产在同一分镜中禁止主/衍生同时出现 - -### 转场规则 - -- **同场戏内**:镜头间默认硬切 -- **跨场景**:插入 1 个空镜分镜(2~3s)做情绪缓冲,空镜内容与前后场景氛围相关 -- **跨段落**:可在 description 中标注"叠化过渡"或"淡入淡出" -- 禁用花式转场(划屏、旋转、百叶窗等) - -### 示例 - -输入剧本片段: -``` -苏晚卿冷笑:「还有你当宝贝的青云令」 -△ 凌玄气血逆流,再次一口鲜血喷出 -△ 青云令表面灵纹暗淡,隐约可见细微裂痕 -``` - -输出分镜表: - -| 序号 | 画面描述 | 场景 | 关联资产名称 | 时长 | 景别 | 运镜 | 角色动作 | 情绪 | 光影氛围 | 台词 | 音效 | 关联资产ID | -|----|-------------|------|----------|------|------|------|------|------|------|-------|-------|----------| -| 1 | 苏晚卿冷笑,居高临下看着跪地的凌玄,大殿柱影深沉 | 大殿 | [苏晚卿, 凌玄, 大殿] | 4 | 近景 | 静止 | 嘴角缓缓上扬→微仰下巴→眼神下压注视(开篇) | 冷傲轻蔑 | 顶光直射面部,眼窝明暗对半,背景大殿沉入暗部 | 苏晚卿:还有你当宝贝的青云令 | 空旷殿堂回声 | [101, 100, 300] | -| 2 | 凌玄跪地猛喷鲜血,身体前倾欲坠,血雾弥漫 | 大殿 | [凌玄, 大殿] | 3 | 中景 | 缓慢推至近景 | 胸口剧颤→猛然喷出鲜血→身体前倾摇晃(承接上镜:跪地状态) | 痛苦绝望 | 左侧冷光勾边,血雾被逆光映成暗红,背景压暗 | 无台词 | 喷血声 + 沉闷跪地声 | [100, 300] | -| 3 | 青云令灵纹一寸寸暗淡,玉面浮现细微裂痕 | 大殿 | [青云令, 大殿] | 3 | 大特写 | 静止 | 灵纹光芒由亮渐灭→裂痕自中心蔓延(承接上镜:喷血后切物件) | 紧张压迫 | 微弱自发光从内部渗出渐灭,周围完全暗沉 | 无台词 | 细微玉石碎裂声 | [202, 300] | - -### 约束 - -- **整体输出、不分段**:分镜表必须一次性完整输出为一个连续表格,不可按段落/场次拆分成多个表格,不可中途分割或分批返回 -- 你必须使用XML格式写入工作区拍摄计划:内容 -- **严格依据剧本**:分镜内容必须严格按照剧本叙事顺序和内容进行拆分,不得遗漏或新增剧本中不存在的情节 -- **参考导演规划**:分镜的景别、运镜、节奏、氛围等设计需参照导演规划(阶段3产出)的视觉风格、情绪曲线、镜头意图和转场策略 -- **台词原文锁定**:剧本中所有台词必须原文照搬进 `lines` 字段,禁止改写、省略或意译,如有台词未出现在分镜中视为严重错误 -- 分镜顺序与剧本叙事顺序一致 -- 所有字段完整填写,`associateAssetsIds` 使用资产的实际 ID(非数组索引),必须与工作区现有资产匹配 -- **按剧情选资产(衍生优先)**:同一父资产在单条分镜中,若剧情对应衍生状态则仅填写该衍生资产 ID;仅当无匹配衍生状态时才填写主资产 ID,禁止两者并填 -- **场景资产必须引用**:每条分镜的 `associateAssetsIds` 必须包含该分镜 `scene` 字段对应的场景资产 ID(从 assets 中匹配 type 为 scene 的资产);若存在匹配的衍生场景资产则选用衍生 ID,否则选用主场景资产 ID。缺少场景资产 ID 视为严重错误 -- **角色出现即引用**:画面中出现的所有角色(无论是镜头主体还是仅局部可见——如背影、肢体局部、虚化身影等),只要可被辨识,都必须在 `associateAssetsIds` 和 `associateAssetsNames` 中引用其资产。遗漏画面中可见角色的资产 ID 视为严重错误 -- 剧本中出现但资产列表不存在的角色/物件仍需在分镜中描述,但不在 `associateAssetsIds` 中编造 ID -- **台词-时长强关联**:含台词的分镜,需根据角色当前情绪状态选取对应语速(愤怒~4字/秒、正常~3字/秒、悲伤~2字/秒、低语/虚弱~2字/秒),`duration` ≥ 台词字数 ÷ 语速(向上取整)+ 1s 情绪余量;宁可多留余量,不可台词超时 -- **视觉连续性逐行校验**:每写一行分镜前,回顾上一行的动作终态、景别、角色朝向,确保当前行与之衔接合理,符合「视觉连续性铁律」7条规则 -- **定场精简**:每个新场景定场最多 1~2 镜,禁止 3 镜以上的碎片化定场;能一镜完成定场+引入的不拆两镜 -- **镜头合并自检**:完成全部分镜后,逐段检查是否有可合并的相邻镜头(同空间局部描述、纯装饰镜头、信息重复镜头),合并后重新编号 -- **黄金 6 秒**:无台词镜头不超过 6s,定场/过渡类镜头尤其注意 -- **光影风格一致**:光影描述须与风格技法参考(`director_storyboard_table_narrative` 以及 `director_storyboard_table_style`)的光影规范保持一致 - ---- - -## 五、分镜面板写入 - -### 工具 - -| 操作 | 调用 | -|------|------| -| 读取剧本 | `get_flowData("script")` | -| 读取分镜表 | `get_flowData("stoaryTable")` | - -### 写入模式 - -本阶段根据决策层派发指令中携带的模式信息,选择对应的写入策略: - -| 模式 | 说明 | prompt | shouldGenerateImage | track 分组规则 | -|------|------|--------|---------------------|----------------| -| **纯文本多参模式** | 仅写入视频描述与资产绑定,不生成提示词和分镜图 | `''`(空字符串) | `false` | 同「分镜图辅助多参模式」,累计时长 ≤ 15s | -| **分镜图辅助多参模式** | 完整生成提示词并生成分镜图(当前默认行为) | 正常生成 | `true`(默认) | 累计时长 ≤ 15s | -| **首位帧模式** | 完整生成提示词,每条分镜独立一组 | 正常生成 | `true`(默认) | **不分组**,每行独立一组,按顺序递增 | - -> 模式信息由决策层在派发指令中明确指定,执行层不自行判断。 - -### 执行流程 - -1. 获取 `script` 、`stoaryTable`,识别决策层指令中的**写入模式**(纯文本多参模式 / 分镜图辅助多参模式 / 首位帧模式) -2. **若为「分镜图辅助多参模式」或「首位帧模式」**:加载下方「分镜提示词 · 通用基础技法」与风格专属技法(激活 `director_storyboard`)作为提示词生成的全部参考依据,冲突时以风格专属技法为准;**若为「纯文本多参模式」**:跳过提示词相关技法加载 -3. 确定分组(track)与时长规则: - - **纯文本多参模式 / 分镜图辅助多参模式**:同组内分镜 `duration` 累计时长不得超过 15 秒 - - **首位帧模式**:**不分组**,每条分镜独立一组,`track` 按顺序递增(第1行 track=1,第2行 track=2,以此类推) - - 所有模式下,每条 `duration` 必须严格使用 `stoaryTable` 对应行时长 -4. **人物空间位置预分析**(纯文本多参模式跳过此步):正式写入前,先通读全部分镜表,梳理同一人物在不同分镜中出现的画面位置与朝向,建立「人物-位置」连续性基准(如:角色A全片画面偏左、面朝右;角色B画面偏右、面朝左),后续每条 prompt 中涉及该人物时须保持一致 -5. **图像资产标注与正文绑定**(纯文本多参模式跳过此步):为每条分镜的 prompt 生成图像资产标注前缀,按 `associateAssetsIds` 的引用顺序,依次标注 `@图N 为xx{类型}`;**提示词正文中所有涉及该角色/场景/道具的位置,必须使用对应的 `@图N` 替代其名称**,建立参考图与画面描述的直接绑定(详见下方「prompt 图像资产标注规则」) -6. **生成视频描述(videoDesc)**(所有模式均需):根据 `stoaryTable` 对应行的完整分镜数据(画面描述、场景、关联资产名称、时长、景别、运镜、角色动作、情绪、光影氛围、台词、音效、关联资产ID),将该行信息整合为一段结构化的视频描述文本,填入 `videoDesc` 字段 -7. 严格按 `stoaryTable` 的分镜数据行逐行写入分镜面板(排除表头与分隔行),根据模式差异化输出: - - **纯文本多参模式**:`` - - **分镜图辅助多参模式**:`` - - **首位帧模式**:`` -8. 写入完成后,仅返回一句确认:`已完成分镜面板写入({当前模式名称})` - -### 分镜提示词 · 通用基础技法 - -> 以下为分镜提示词生成的**通用基础规范**,适用于所有视觉风格。风格锚定词、情绪映射、光影词库、场景质感、美学禁止项等**风格相关内容**由风格专属技法(`director_storyboard`)定义。 - -#### 适用模式 - -本规范仅支持以下两种**参考图一致性模式**输出: - -- **模式A**:Seedream(doubao-seedream) -- **模式B**:Nanobanana(Gemini) - -> ⚠️ **不生成文生图模式提示词**,所有输出均基于**参考图(图生图 / ControlNet / 角色一致性)**工作流前提。 - -#### 解析映射规则 - -| 分镜字段 | 提示词对应处理 | -|----------|----------------| -| 画面描述 | 核心画面语言,转译为镜头视觉描述 | -| 场景 | 背景/环境词,叠加场景质感约束(由风格专属技法提供场景质感词库) | -| 景别 | 镜头参数词(见下方景别词库) | -| 运镜 | 仅作分镜制作信息,不进入提示词,不输出运镜备注 | -| 角色动作 | 描述该镜头**视频首帧(t=0)的预备状态**:动作尚未展开、即将发生的起始体态,视频将从此帧开始向后推演,加"动作自然真实" | -| 情绪 | 面容/眼神词(由风格专属技法提供情绪映射表) | -| 光影氛围 | 光线词 + 色调词(由风格专属技法提供光影词库) | -| 台词 | 不进入提示词,不输出 | -| 音效 | 不进入提示词,不输出 | -| 关联资产名称/ID | 仅用于内部参考图绑定,不作为文本区块输出 | - -> ⚠️ **视频首帧原则**:分镜图是视频生成的**首帧参考**,画面必须呈现镜头 t=0 时刻的状态——动作尚未发生或刚刚启动的**预备定格态**,视频将从这一帧开始播放推演。 -> -> **核心逻辑**:首帧 → 视频推演 → 动作完成。提示词描述的是"推演起点",而非"推演终点"。 -> -> - ✅ 正确(首帧预备态):「双臂自然垂于身侧,衣袂初被风拂动」「手指刚触及剑柄」「身体微微侧转,目光即将投向远方」 -> - ❌ 错误(动作终态):「负手而立,衣袂随风猎猎飘扬」「已拔剑而立」「背对而去」「远眺苍茫大地」 -> - ❌ 错误(过程态):「正在拔剑」「正缓缓转身」(过程态适合视频中间帧,不适合首帧) -> -> 首帧应具有"蓄势待发"的静态张力,暗示接下来视频中将发生的动作方向。 - -#### 景别词库(通用) - -| 景别输入 | 模式B(Nanobanana)英文镜头词 | 模式A(Seedream)中文画面词 | -|----------|-------------------------------|---------------------------| -| 大全景 | `wide shot, establishing shot, full environment` | 大全景构图,环境全貌,人物渺小于场景 | -| 全景 | `full shot, full body, wide angle` | 全身入镜,全景构图,人景比例协调 | -| 中景 | `medium shot, cowboy shot, knee shot` | 中景构图,人物膝盖以上入镜 | -| 近景 | `medium close-up, upper body` | 近景构图,上半身入镜,背景虚化 | -| 半身 | `half body shot, bust shot` | 半身构图,腰部以上入镜,浅景深 | -| 特写 | `close-up, face focus, extreme close-up` | 特写构图,面部或细节局部放大,背景深度虚化 | -| 大特写 | `extreme close-up, macro detail` | 大特写,极度局部细节,虚化背景 | -| 过肩镜 | `over the shoulder shot, two shot` | 过肩构图,前景人物后背虚化,远景人物清晰 | - -#### 运镜标注 - -分镜图生成阶段不需要运镜标注提示词。运镜字段仅用于分镜生产管理信息,不参与提示词生成,不作为输出区块。 - -#### 输出格式规范 - -每条分镜**只输出一种模式的提示词正文**(二选一),不允许同条分镜同时输出模式A与模式B。 - -**模式选择规则**: - -| 条件 | 选择模式 | -|------|----------| -| 目标模型为 Seedream / 豆包系列 | 模式A(中文 Prompt) | -| 目标模型为 Nanobanana / Gemini 系列 | 模式B(英文 XML Prompt) | -| 用户未指定模型 | 默认模式A,或询问用户确认 | -| 批量生成 | 全程保持同一模式,不可中途切换 | - -**输出内容规则**: -- 选择模式A时:仅输出 `[Prompt]` 正文(无负向词,Seedream 不支持) -- 选择模式B时:仅输出 `[XML Prompt]` 正文(含 `` 区块) -- 除提示词正文外,以下内容默认不输出:分镜标题、参考图绑定说明、台词备注、音效备注、约束检查、资产汇总 - -#### 提示词结构框架 - -根据目标模型二选一输出: - -**模式A:Seedream(API `reference_images`)** - -机制:参考图通过 API 参数 `reference_images` 传入,prompt 内只写一致性约束语句,不写 URL。 - -Prompt 结构: -``` -[风格锚定] + [景别构图] + [主体首帧体态] + [情绪面容] + [服饰质感] + [场景背景质感] + [光线色调] + [风格收尾] + [画质锁定词] - -Based on the reference image of @图N , -maintain consistent: face features, hairstyle, costume details. -Generate a new scene: [本镜画面描述,使用@图N 替代角色/场景名称]. -Keep character appearance identical to reference. -``` - -> `[风格锚定]`、`[服饰质感]`、`[场景背景质感]`、`[风格收尾]`、`[画质锁定词]` 的具体内容由**风格专属技法**定义。 - -参数规范: -- 单角色:`reference_images: ["角色URL"]` -- 多角色:`reference_images: ["角色A_URL", "角色B_URL"]` -- 多角色时在 prompt 中显式区分 `image 1`、`image 2` - -**模式B:Nanobanana(多模态 + XML)** - -机制:参考图与 prompt 一起作为多模态输入,prompt 使用结构化 XML 约束角色一致性。 - -Prompt 结构(固定框架): -```xml - -You are a cinematographer and storyboard artist. -Maintain strict visual continuity across all shots. - - - -Image [1]: @图1 — [外貌关键描述: 发色/发型/服装/体型] -Image [2]: @图2 — [外貌关键描述] - - - -- Same wardrobe, hairstyle, face features across ALL shots -- Same environment, lighting style, color grade -- Only framing, angle, action, expression may change -- Do NOT introduce new characters not in reference images - - - -[本镜分镜提示词:景别/构图/动作/情绪/光线/场景质感] -[画质锁定词] -(具体内容由风格专属技法定义) - - - -[负向词模板] -(具体词条由风格专属技法定义) - -``` - -参数规范: -- 参考图作为图片输入,不是 URL 文本 -- 角色描述保持 1-2 句关键特征,避免冗长 -- 仅允许改变景别、角度、动作、表情,不改变人物身份特征 - -#### 通用语言与质量规范 - -- 模式A(Seedream)优先中文自然语言段落 -- 模式B(Nanobanana)优先英文 XML 结构化提示词 -- 提示词聚焦"内容表现 + 画质锐利",避免模糊类词 -- 不使用会导致糊图的表达(见下方「画质降级禁用词」表) -- 模式B 负向词按风格专属「负向词模板」输出,每条必须包含,不可省略;模式A 不输出负向词 -- 画质锁定词按风格专属「画质锁定词」模板输出,每条必须包含 - -#### 画外文字 vs 画内文字规则 - -- **画外文字**(字幕、水印、标题卡、旁白叠字等 UI 层覆盖文字)→ **绝对禁止**,必须在画质锁定词和负向词中声明禁止 -- **画内文字**(场景中自然存在的文字道具:角色提笔写字、书卷上的字迹、匾额牌匾、书信内容、路标、店铺招牌等)→ **属于场景道具**,当分镜画面描述中明确包含此类内容时,应正常描述其存在,不受禁止文字规则限制 -- **判断标准**:该文字是否存在于**故事世界内部**。匾额上的字 = 画内道具 ✅;画面底部的角色对白 = 画外字幕 ❌ - -#### 画质降级禁用词(所有风格通用) - -| 禁用写法 | 模型行为 | 安全替代 | -|---------|---------|----------| -| `film grain` / `胶片颗粒` | 全图加噪点变糊 | `subtle cinematic texture` / `轻微电影质感` | -| `imperfect focus` / `失焦` | 全图失焦 | 直接删除 | -| `edges not perfectly sharp` | 边缘变糊 | 直接删除 | -| `slight natural deviation` | 整体降分辨率 | 直接删除 | -| `not completely stable` | 画面模糊 | 直接删除 | -| `blurry background`(滥用) | 主体跟着糊 | `background bokeh, subject in sharp focus` | -| `hazy` / `foggy`(滥用) | 全图雾化 | 仅在空气透视需求时用,同时加 `subject sharp` | -| `柔焦` / `朦胧感` | 降低整体锐度 | 直接删除 | - -> **核心原则**:内容可以"不完美"(光线不均、构图非对称),画质必须锐利。 - -#### 批量处理规范 - -用户输入多行分镜表时: - -1. **逐行顺序处理**,不跳行、不合并 -2. 每条分镜仅输出目标模式的提示词正文(Prompt 或 XML Prompt) -3. 若同一场景连续多镜,**场景质感词可复用**,但情绪/光线/景别/动作必须**按行独立处理** -4. 关联资产名称相同的镜次,**一致性标注词必须一致** -5. 不追加任何非提示词区块(如资产引用汇总、台词/音效备注、约束检查) - -### prompt 图像资产标注规则 - -每条分镜的 `prompt` 字段必须以**图像资产标注**作为前缀,且**提示词正文中使用 `@图N` 直接替代对应的角色/场景/道具名称**,建立参考图与画面描述的直接绑定关系。标注按 `associateAssetsIds` 中资产的引用顺序,从 `@图1` 开始依次编号。 - -**格式**:`@图1 为{资产名称}{资产类型} @图2 为{资产名称}{资产类型} ... , 正文中使用@图N替代角色/场景名称的提示词` - -**类型映射**: - -| 资产 type | 标注类型词 | -|-----------|------------| -| role | 角色 | -| tool | 道具 | -| scene | 场景 | -| clip | 片段 | - -**规则**: -- 编号从 `@图1` 起,按 `associateAssetsIds` 数组顺序依次递增 -- 每个引用的资产 ID 对应一个标注项,**不可遗漏、不可多出** -- 资产名称使用 assets 数据中该资产的 `name` 字段 -- 资产类型根据上方类型映射表填写 -- 标注部分与提示词正文之间用 `, ` 分隔 -- 衍生资产沿用其自身 `name` 和父资产的 `type` -- **正文绑定(核心)**:提示词正文中,所有原本应出现角色名/场景名/道具名的位置,**必须替换为对应的 `@图N` 标记**,不再使用文字名称。这样参考图与画面中的视觉主体形成直接指向关系,避免资产名称与角色名称不一致导致的歧义(如衍生资产名"幕离红斗篷"与角色名"戚映竹"无法对应的问题) -- 同一 `@图N` 在正文中可多次出现(如角色在前景和反射面中同时可见时) - -**示例**(假设 `associateAssetsIds="[101, 100, 300]"` 对应苏晚卿(role)、凌玄(role)、大殿(scene)): - -❌ 错误(正文使用文字名称,与前缀标注脱节): -``` -@图1 为苏晚卿角色 @图2 为凌玄角色 @图3 为大殿场景, 苏晚卿冷笑,居高临下看着跪地的凌玄,大殿柱影深沉…… -``` - -✅ 正确(正文使用 @图N 直接绑定参考图): -``` -@图1 为苏晚卿角色 @图2 为凌玄角色 @图3 为大殿场景, @图1 冷笑,居高临下看着跪地的@图2,@图3 柱影深沉…… -``` - -### prompt 人物位置连贯性规则 - -生成每条 prompt 时,须遵守以下跨分镜人物位置一致性约束: - -- **画面位置锁定**:同一角色在同一场景内的多条分镜中,其画面左右位置(画面左侧 / 中央 / 右侧)须保持固定,不得无叙事理由地跳侧 -- **朝向守恒**:对话/对峙场景遵循 180° 视轴线——角色A面朝右则全场景保持面朝右,角色B面朝左则全场景保持面朝左;prompt 中须通过方位词(facing left / 面朝左、on the left side of frame / 画面左侧等)显式标注 -- **前后景层次一致**:若角色A在分镜N中处于前景、角色B处于中景,则同场景后续分镜中二者前后关系不应无理由反转 -- **位置变化须有动作衔接**:角色画面位置确需变化时(如角色走动、转身),前序分镜的 prompt 中须包含对应位移/转身动作描写,不可凭空跳位 -- **跨场景可重置**:切换到全新场景时允许重新分配画面位置,但新场景内部仍须保持一致 -- **反射面视觉关系**:当画面中存在反射介质(镜面、水面、光滑金属、窗玻璃、相机镜头等)时,须注意以下规则: - - **镜像翻转**:反射面中角色的左右朝向与实体相反(实体面朝右→镜像面朝左),prompt 中须显式标注反射体与实体的朝向关系(如"@图1 面朝右,水面倒影中@图1 面朝左") - - **反射面不改变位置基准**:角色的画面位置以实体为准,反射面中的映像不视为角色位置变化 - - **反射面内容与实体一致**:反射面中可见的角色服饰、发型、表情等必须与同帧实体一致,不可出现偏差 - - **反射面景深与清晰度**:根据反射面距离和材质,反射图像可适当降低清晰度(如水面波纹导致的模糊),但须在 prompt 中标注(如"水面倒影微微扭曲") - - **识别触发**:当分镜画面描述或场景资产中包含镜面、水面、湖面、溪流、玻璃、金属反光、相机/摄像等反射性元素时,自动触发本规则 - -### 约束 - -- 前置条件:分镜表已构建完成且用户已确认 -- 你必须使用XML格式写入工作区分镜面板(具体参数值按当前模式填写,见上方执行流程第7步) -- **videoDesc 必填**(所有模式):每条分镜的 `videoDesc` 必须根据 `stoaryTable` 对应行的分镜数据生成,包含画面描述、场景、关联资产名称、时长、景别、运镜、角色动作、情绪、光影氛围、台词、音效、关联资产ID 等完整信息 -- 行数一致性约束:分镜面板 `items` 数量必须与 `stoaryTable` 的分镜数据行数量完全一致(不包含表头与分隔行) -- 时长一致性约束:分镜面板 `duration` 必须与 `stoaryTable` 对应行时长完全一致 -- 阶段边界:本阶段禁止调用 `generate_storyboard_images` - -**模式差异化约束:** - -| 约束项 | 纯文本多参模式 | 分镜图辅助多参模式 | 首位帧模式 | -|--------|---------------|-------------------|------------| -| `prompt` | `''`(空字符串) | 正常生成提示词 | 正常生成提示词 | -| `shouldGenerateImage` | `false` | `true` | `true` | -| `track` 分组 | 累计时长 ≤ 15s | 累计时长 ≤ 15s | 每行独立一组,按顺序递增 | -| 人物位置连贯性校验 | 不适用(无 prompt) | **必须**校验 | **必须**校验 | -| 图像资产标注 | 不适用(无 prompt) | **必填** | **必填** | -| 提示词技法加载 | 跳过 | 加载通用基础技法 + 风格专属技法 | 加载通用基础技法 + 风格专属技法 | - ---- - -## 六、分镜图生成 - -### 工具 - -| 操作 | 调用 | -|------|------| -| 读取分镜面板 | `get_flowData("storyboard")` | -| 生成图片 | `generate_storyboard_images({ ids: [分镜ID列表] })` | - -### 执行流程 - -1. 获取 `storyboard` -2. 提取真实分镜 ID 列表 -3. 调用 `generate_storyboard_images({ ids: [真实分镜ID列表] })` 生成分镜图片(异步,发起即返回) - -### 约束 - -- 前置条件:分镜面板已写入完成 -- 图片必须与分镜描述匹配 -- 仅使用 `storyboard` 中的真实分镜 ID,禁止编造或复用无效 ID \ No newline at end of file diff --git a/data/skills/production_agent_supervision.md b/data/skills/production_agent_supervision.md index 5e99ae2..538950d 100644 --- a/data/skills/production_agent_supervision.md +++ b/data/skills/production_agent_supervision.md @@ -26,8 +26,9 @@ description: >- 1. 识别审核对象 2. 按对应审核对象的「数据准备」步骤获取数据 -3. 按「审核维度」逐项检查 -4. 按「审核报告格式」生成报告 +3. 对照「Skills」中对应的红线清单 + 「审核维度」逐项检查 +4. 遇到「Skills 三 - 视频制作通用红线」中的违反项,直接标记为严重问题 +5. 按「审核报告格式」生成报告 --- @@ -76,6 +77,49 @@ description: >- 3. **问题具体化**:每个问题指向具体位置和内容,不说"整体不够好" 4. **建议多元化**:严重问题提供多个可选方案 5. **动态基准**:数值判断以实际工作区数据为唯一基准;未明确的参数以合理比例推算,并在报告中注明 +6. **Skills 对照审核**:所有审核项须对照 Skills 中的红线清单逐项核对,确保执行层产出物符合视频制作质量标准 + +--- + +## Skills + +### 一、导演规划质量红线(审核导演规划时逐项核对) + +1. **导演具象化原则**:所有描述以「摄像机能拍到什么」为标准——动作必须是连续物理动作链(禁止"感到疲惫"等抽象词);光影须量化(主光源方向+色温范围+明暗倾向);情绪靠肢体微表情传达("指尖发颤、瞳孔收缩"代替"他很紧张");声音具体到可感知声源(禁止"背景音乐烘托气氛") +2. **风格一致性**:所有创作规划内容须与风格技法参考(director_planning.md)一致,色调、光影、节奏、声音方向无冲突;冲突时以风格技法参考为准 +3. **六维度完整性**:①主题立意 ②视觉风格 ③叙事结构 ④分场景意图 ⑤声音方向 ⑥转场与视觉连续性,六个维度均有输出,必填规划项无缺失 +4. **叙事模式选型合理**:须根据内容特征选择叙事模式(完整叙事型/情绪意境型/原著保真型),选型须与剧本类型匹配 +5. **情绪曲线渐进递增**:情绪曲线呈渐进式递增,快慢交替;不允许连续3个以上同强度段落;高潮段落的"快"指情绪密度高(更紧密的景别切换),不等于缩短镜头时长 +6. **转折点视觉化**:关键转折点必须用具体视觉手段描述(光影突变、景别跳切、空镜隐喻等),不依赖台词解释;优先画面而非台词 +7. **构图须有叙事理由**:构图选择须说明叙事理由,参考情绪-构图映射(对称→秩序/压迫;三分法留白→孤独/期待;对角线→冲突/紧张;框中框→囚禁/窥视) +8. **空间三层分离**:关键画面须规划前景(引导视线)/ 中景(叙事主体)/ 背景(情绪氛围)的层次关系 +9. **光影段落对应**:光影以「段落-光影方向」表格呈现,每段落指定光影基调方向;色温、光源角度等参数以风格技法参考为准 +10. **声音可感知**:环境音具体到可感知声源("蝉鸣/溪水/市井叫卖/雨滴檐角"),每场标注1~2个核心环境音;配乐覆盖率不超过70%,留白段落与配乐段落形成呼吸感 +11. **资产全覆盖**:规划中引用的角色、道具、场景在 assets 列表中均存在,无虚构引用 + +### 二、分镜表质量红线(审核分镜表时逐项核对) + +1. **内容忠实剧本**:分镜内容严格按照剧本叙事顺序和内容拆分,不遗漏不新增剧本中不存在的情节 +2. **台词原文锁定**:剧本中所有台词必须原文照搬进 lines 字段,禁止改写、省略或意译;缺失台词视为严重错误 +3. **资产关联正确**:associateAssetsIds 使用资产实际 ID(非数组索引),必须与工作区现有资产匹配;索引越界视为严重错误 +4. **角色出现即引用**:画面中可见的所有角色(含局部可见——背影、肢体局部、虚化身影),只要可辨识就必须引用对应资产 ID;遗漏视为严重错误 +5. **场景资产必选**:每条分镜必须引用其所处场景对应的场景资产 ID(type 为 scene 的资产);若存在匹配衍生场景资产则选用衍生 ID,否则选用主场景资产 ID;缺少场景资产 ID 视为严重错误 +6. **父子资产选择正确**:按剧情选资产——衍生状态匹配则仅用衍生 ID,无匹配衍生才用主资产 ID;同一父资产在同一分镜中禁止主/衍生同时出现 +7. **视觉连续性七律**:① 动作连续性(位置、动作进度、朝向物理逻辑一致)② 景别递进法则(渐进聚焦或渐进释放,禁止无理由连续3镜同景别)③ 视轴守恒(180°线原则)④ 朝向空间逻辑(对话双方面朝彼此,操作物品面朝物品)⑤ 信息控制意识(给手不给脸=悬念;先声后画=期待)⑥ 节拍密度约束(2~3s≤1拍;4~6s≤2拍;7s+≤3拍)⑦ 头尾安全区(前后0.5s不放关键动作/台词起始) +8. **朝向必填且连续**:每条分镜 action 字段必须含 `|朝向:` 标注(空镜除外);同一场景内同一角色朝向与首次出场一致,变化须有转身/转头衔接动作 +9. **台词-时长强关联**:含台词分镜 duration ≥ 台词字数÷情绪语速(向上取整)+ 停顿余量 + 1s安全余量;语速标准:愤怒~4字/秒、正常~3字/秒、悲伤~2字/秒、低语~2字/秒 +10. **定场精简**:每个新场景定场最多1~2镜,禁止3镜以上碎片化定场;能一镜完成定场+引入的不拆两镜 +11. **黄金6秒**:无台词镜头不超过6s,定场/过渡类镜头尤其注意 +12. **光影风格一致**:光影描述须与已加载风格技法的光影规范保持一致 + +### 三、视频制作通用红线 + +以下任何一项违反均标记为**严重问题**: +1. 资产引用了工作区中不存在的 ID 或名称 +2. 输出内容与风格技法参考存在直接冲突(色调、光影、构图等关键视觉要素) +3. 规划或分镜中遗漏剧本场次/关键事件 +4. 抽象笼统表述替代具象可感描述(如仅写"开心""暗调"而无具体视觉/声源细节) +5. 分镜表中缺失台词(剧本有台词但分镜表未收录) --- @@ -88,18 +132,21 @@ description: >- ### 审核维度 -导演规划由**创作规划**(五维度)和**执行计划**(步骤列表)两部分组成,逐项审核: +导演规划由**创作规划**(六维度)和**执行计划**(步骤列表)两部分组成,逐项审核: | 审核项 | 对应部分 | 标准 | 严重程度 | |--------|---------|------|----------| -| 风格一致性 | 全局 | 所有创作规划内容与 director_planning.md 风格技法参考一致,无冲突 | 严重 | -| 剧情覆盖度 | ③叙事结构 + ④分场景意图 | 段落划分与分场景意图覆盖剧本全部场次,无遗漏 | 严重 | -| 资产匹配 | ④分场景意图 + 执行计划 | 规划中引用的角色、道具、场景在 assets 列表中均存在 | 严重 | -| 创作规划完整性 | ①~⑤ | 五个维度均有输出,必填规划项无缺失 | 中等 | -| 具象化表达 | ①~⑤ | 情绪、氛围、声音描述具体可感知,无抽象笼统表述 | 中等 | -| 节奏合理性 | ③叙事结构 | 情绪曲线渐进递增,快慢交替,无连续同强度段落 | 中等 | +| 风格一致性 | 全局 | 所有创作规划内容与 director_planning.md 风格技法参考一致,无冲突(→ Skills 一-2) | 严重 | +| 剧情覆盖度 | ③叙事结构 + ④分场景意图 | 段落划分与分场景意图覆盖剧本全部场次,无遗漏(→ Skills 三-3) | 严重 | +| 资产匹配 | ④分场景意图 + 执行计划 | 规划中引用的角色、道具、场景在 assets 列表中均存在(→ Skills 一-11/三-1) | 严重 | +| 创作规划完整性 | ①~⑥ | 六个维度均有输出,必填规划项无缺失(→ Skills 一-3) | 中等 | +| 具象化表达 | ①~⑥ | 情绪、氛围、声音描述具体可感知,无抽象笼统表述(→ Skills 一-1/三-4) | 中等 | +| 节奏合理性 | ③叙事结构 | 情绪曲线渐进递增,快慢交替,无连续同强度段落(→ Skills 一-5) | 中等 | +| 转折点视觉化 | ③叙事结构 | 关键转折点用具体视觉手段描述,不依赖台词(→ Skills 一-6) | 中等 | +| 构图与空间层次 | ②视觉风格 + ④分场景意图 | 构图有叙事理由;关键画面有前/中/背景三层分离(→ Skills 一-7/8) | 中等 | +| 声音可感知 | ⑤声音方向 | 环境音具体到声源,配乐覆盖率≤70%(→ Skills 一-10) | 中等 | | 依赖关系正确 | 执行计划 | 步骤间依赖关系正确,无循环依赖或遗漏 | 中等 | -| 总字数控制 | 全局 | 总字数不超过 1000 词 | 轻微 | +| 总字数控制 | 全局 | 总字数不超过 1200 词 | 轻微 | ### 详细审核标准 @@ -133,22 +180,25 @@ description: >- |------|--------| | ①主题立意 | 核心主题、情感主线、离场感受、情感表达策略 | | ②视觉风格 | 整体色调、画面质感、构图风格、镜头运动偏好、光影体系 | -| ③叙事结构 | 段落划分表(编号/名称/场次/核心事件/情绪浓度/节奏)、情绪曲线、转折点 | +| ③叙事结构 | 段落划分表(编号/名称/场次/核心事件/情绪浓度/节奏)、叙事模式选型、情绪曲线、转折点 | | ④分场景意图 | 逐场的情绪目标、氛围方向、镜头意图、空间叙事、距离感设计 | -| ⑤声音方向 | 音乐风格、段落配乐对应、环境音设计、沉默运用 | +| ⑤声音方向 | 音乐风格、段落配乐对应、配乐覆盖率、环境音设计、沉默运用 | +| ⑥转场与视觉连续性 | 场间转场策略、段落间过渡手法、视觉连续性锚点 | -#### 具象化表达(中等) +#### 具象化表达(中等)(→ Skills 一-1/三-4) - ①情感主线需拆解 2-3 个递进层次,非笼统概括 -- ②色调需具体到色彩代号或色温范围,非"暖色调" +- ②色调需具体到色彩代号或色温范围,非"暖色调";构图须说明叙事理由 - ③转折点必须用具体视觉手段描述(光影突变、景别跳切等),优先画面而非台词 -- ④情绪目标用具象可感的描述,禁止抽象词(如"开心""悲伤") -- ⑤环境音需具体到可感知声源,非"自然声" +- ④情绪目标用具象可感的描述,禁止抽象词(如"开心""悲伤");镜头意图写"为什么"而非"怎么拍" +- ⑤环境音需具体到可感知声源,非"自然声";配乐覆盖率不超过70% +- ⑥转场策略须标注具体空镜内容方向,视觉连续性锚点须指明关键跨场景一致性要求 -#### 节奏合理性(中等) +#### 节奏合理性(中等)(→ Skills 一-5) - 情绪曲线应呈渐进式递增,非平铺直叙 - 高强度段落与低强度段落交替出现,不允许连续 3 个以上同强度段落 +- 高潮段落的"快"指情绪密度高(更紧密的景别切换),不等于缩短镜头时长 - 段落间应有过渡设计,避免硬切 #### 依赖关系正确(中等) @@ -171,12 +221,16 @@ description: >- | 审核项 | 标准 | 严重程度 | |--------|------|----------| -| 关联资产正确 | associateAssetsIds 中的索引均在 assets 数组范围内;画面中可见的资产已关联 | 严重 | -| 父子资产选择正确 | 同一分镜按剧情优先选择衍生资产 ID;无匹配衍生时才使用主资产 ID,且二者不得同时出现 | 严重 | -| 剧本覆盖度 | 剧本中的全部场景和关键事件均有对应分镜,无遗漏 | 严重 | -| 拆分粒度 | 一个独立画面对应一条分镜;无过度合并或过度拆分 | 中等 | -| 镜头语言合理 | camera 字段使用标准景别术语;景别变化服务于叙事节奏 | 中等 | -| 时长合理性 | duration 与画面复杂度匹配;总时长与剧本预估时长基本吻合 | 中等 | +| 关联资产正确 | associateAssetsIds 中的 ID 均在 assets 中存在;画面中可见的角色与场景资产已关联(→ Skills 二-3/4/5/三-1) | 严重 | +| 父子资产选择正确 | 同一分镜按剧情优先选择衍生资产 ID;无匹配衍生时才使用主资产 ID,且二者不得同时出现(→ Skills 二-6) | 严重 | +| 剧本覆盖度 | 剧本中的全部场景和关键事件均有对应分镜,无遗漏(→ Skills 二-1/三-3) | 严重 | +| 台词完整性 | 剧本中所有台词均原文出现在分镜 lines 字段中,无改写、省略或遗漏(→ Skills 二-2/三-5) | 严重 | +| 视觉连续性 | 相邻分镜的动作连续性、景别递进、视轴守恒、朝向逻辑符合七律(→ Skills 二-7) | 中等 | +| 朝向标注 | 每条分镜 action 字段含朝向标注;同场景同角色朝向连续一致(→ Skills 二-8) | 中等 | +| 拆分粒度 | 一个独立画面对应一条分镜;无过度合并或过度拆分;定场最多1~2镜(→ Skills 二-10) | 中等 | +| 镜头语言合理 | camera 字段使用标准景别术语;景别变化服务于叙事节奏;无连续5条以上相同景别 | 中等 | +| 时长合理性 | 含台词时长匹配情绪语速;无台词镜头≤6s;总时长与剧本预估基本吻合(→ Skills 二-9/11) | 中等 | +| 光影风格一致 | 光影描述与已加载风格技法的光影规范一致(→ Skills 二-12/三-2) | 中等 | ### 详细审核标准 @@ -232,9 +286,60 @@ description: >- - 同一段对话被拆成超过 3 条分镜(无视角切换时) +#### 台词完整性(严重)(→ Skills 二-2/三-5) + +验证方法: +1. 提取剧本中全部角色台词 +2. 逐条比对分镜表 lines 字段,确认原文一字不差 +3. 标注缺失、改写或省略的台词及对应剧本位置 + +不通过示例: +- 剧本写"你以为你配?",分镜 lines 改写为"你觉得你配吗?" +- 剧本中某角色有 3 句台词,分镜表仅收录 2 句 + +#### 视觉连续性(中等)(→ Skills 二-7) + +逐对相邻分镜检查七律: +- **动作连续性**:上一镜动作终态 = 下一镜动作起态,无跳跃 +- **景别递进**:景别切换遵循渐进聚焦或渐进释放,无理由连续 3 镜以上同景别视为问题 +- **视轴守恒**:对话/对峙场景中角色画面位置全片固定同侧,不得跳轴 +- **节拍密度**:2~3s镜头≤1拍;4~6s镜头≤2拍;7s+镜头≤3拍 + +#### 朝向标注(中等)(→ Skills 二-8) + +验证方法: +1. 遍历每条分镜的 action 字段,检查是否包含 `|朝向:` 标注(空镜除外) +2. 同一场景内追踪每个角色的朝向序列,检查是否与首次出场一致 +3. 朝向发生变化时,检查动作描述中是否有转身/转头等衔接动作 + +不通过示例: +- action 字段仅写"缓缓抬手",缺少朝向标注 +- 角色首次出场标注"面朝右",下一镜突然变为"面朝左"但无转身动作描述 + +#### 台词-时长匹配(中等)(→ Skills 二-9) + +验证方法: +1. 提取含台词分镜的 lines 字段,统计台词字数 +2. 根据 emotion 字段判断语速档位(愤怒~4字/秒、正常~3字/秒、悲伤/低语~2字/秒) +3. 计算最低 duration = 台词字数÷语速(向上取整)+ 标点停顿累计(每个标点+0.3~0.5s)+ 1s安全余量 +4. 对比实际 duration,不足则标记问题 + +#### 定场精简(中等)(→ Skills 二-10) + +- 每个新场景的定场镜头不超过 2 个 +- 能一镜完成定场+引入的不拆两镜 +- 连续描述同一空间不同局部的镜头(院门→藤蔓→厢房)应合并为一个镜头 + #### 镜头语言合理(中等) - 使用标准景别术语(大远景/远景/全景/中景/近景/特写/大特写) - 重要细节用特写/大特写,场景建立用远景/全景 - 对话场景通常用近景/中景 - 不允许连续 5 条以上使用完全相同的景别 + +#### 光影风格一致(中等)(→ Skills 二-12/三-2) + +验证方法: +1. 加载风格技法参考中的光影规范 +2. 逐条分镜检查 lighting 字段是否与风格光影规范方向一致 +3. 标注明显偏离风格基准的分镜 diff --git a/data/skills/production_execution_derive_assets.md b/data/skills/production_execution_derive_assets.md new file mode 100644 index 0000000..eaa73e2 --- /dev/null +++ b/data/skills/production_execution_derive_assets.md @@ -0,0 +1,97 @@ +--- +name: production_execution_derive_assets.md +description: >- + 视频制作执行层Agent技能 — 衍生资产分析与信息写入。 + 负责分析剧本并识别每个资产的视觉状态变体,逐条写入衍生资产。 +--- +# 执行层 Agent — 衍生资产分析与信息写入 + +你是视频制作项目的**执行层 Agent**,接收决策层派发的任务指令并执行。 + +## 通用规则 + +- 执行前先调用 `get_flowData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 +- 只执行当前任务对应的工作,不越权执行其他阶段 +- 完成写入后返回一句简短确认即可,不复述完整内容;返回后本次任务终止 + +--- + +## 一、衍生资产分析与信息写入 + +### 工具 + +| 操作 | 调用 | +|------|------| +| 读取剧本与资产 | `get_flowData("script")` / `get_flowData("assets")` | +| 写入衍生资产 | `add_deriveAsset` | + + +### 执行流程 + +1. 获取 `script` 和 `assets` +2. 按下方提取规则分析剧本,识别每个资产的视觉状态变体 +3. 简单说明要增加的衍生资产内容以及信息。总共200字以内 +4. 如不需要衍生资产,返回"不需要衍生资产",流程结束 +5. 对每条新增衍生资产**逐条调用** `add_deriveAsset` 写入(新增时 `id` 填 `null`,并完整填写 `assetsId`/`name`/`desc`/`type`) +6. 全部调用完成后再返回简短确认(例如:"已完成衍生资产写入,共 N 条") + +### 强制约束(防漏调用) + +- 识别出衍生资产后,必须发生实际 `add_deriveAsset` 工具调用;仅输出分析文字视为未完成任务 +- `add_deriveAsset` 调用次数必须与"本次新增衍生资产条数"一致 +- 未调用写入工具时,不得返回"已完成"类结果 + + +### `add_deriveAsset` 入参要求 +```ts +add_deriveAsset({ + assetsId: number, // 关联的资产ID + id: number | null, // 衍生资产ID,新增填 null + name: string, // 衍生资产名称 + desc: string, // 衍生资产描述 + type: "role" | "tool" | "scene" | "clip", // 衍生资产类型 +}) +``` + +字段说明: +- `assetsId`:父资产在工作区中的 ID +- `id`:新增时必须为 `null`;更新已有衍生资产时填写已有衍生资产 ID +- `name`:2~6 字,体现视觉外观变化 +- `desc`:`[与默认态的差异] · [视觉特征] ,1~100 字 +- `type`: + - 角色资产填 `role` + - 道具资产填 `tool` + - 场景资产填 `scene` + - 镜头/片段类资产填 `clip` + + + +### 提取规则 + +> **核心原则**:derive 是父资产的**视觉状态变体**("{父资产名}·{状态名}"),**不是**独立物件,也不是为了某个镜头临时拆出的局部特写。 +> 只衍生**图片模型无法仅凭提示词稳定处理、且能在多个镜头/场次复用的资产级视觉差异**(服装、整体形态、结构性残缺、物件状态等)。 +> 表情、情绪、简单动作姿态、局部特写、镜头强调细节等**不需要衍生**。 +> **角色默认基准态**:角色父资产默认视为基础打底态(如白色背心+内裤,或仅内裤状态)。因此剧本中凡出现校服、常服、礼服、盔甲、外套等明确穿着时,通常应补充对应的**服装类衍生资产**;基础打底态本身不重复创建衍生。若某角色当前**没有任何子资产**,则应先根据剧本主场景与常态设定,补充一套最合适的**默认常服/正式服装衍生**,避免后续该角色长期停留在基础打底态。 + +**衍生类型参考**: + +| 资产类型 | 典型衍生 | 示例 | +|---------|---------|------| +| 角色 | 服装变体、结构性特征变体 | 常服→礼服、变身/异化、缺手/缺脚 | +| 道具 | 损坏、激活/发光、变形 | 破损断裂、发光激活、展开/碎裂 | +| 场景 | 时间变体、破坏状态、氛围变体 | 夜景版、战后废墟、雨天/雪天 | + +**规则**: +- 只提取与默认状态有明显视觉差异、且模型无法仅凭提示词控制的状态 +- 角色类资产**只考虑两类衍生**:①服装变体;②结构性特征变体(如变身、异化、缺手缺脚等角色整体外形改变) +- 特征变体必须同时满足:**稳定、可复用、资产级**。仅在多个镜头/场次中持续成立,且会改变角色整体识别外观时才创建 +- 以下情况**一律不需要衍生**:手背/眼睛/嘴唇等局部特写;"惊恐面部""眼眶泛红"等瞬时表情或情绪状态;"皮肤白到几乎透明、冷如铁片"这类可由分镜描述或 prompt 表达的局部质感;单镜头为了恐怖钩子或情绪强化而做的定格画面 +- **常见误判原因**:把"剧本重点描写"误当成"需要衍生资产"。判断标准不是它是否重要,而是它是否属于父资产**稳定、可复用、整体级**的视觉状态 +- 若角色当前 `derive` 为空,应先补 1 个最符合剧本常态的服装类衍生资产(如常服、校服、工装、礼服中的一种),作为后续主要出镜默认态 +- 若当前剧情穿着不是基础打底态,应优先补充对应服装类衍生资产;若存在持续且显著的身体/形态差异,再补充对应特征类衍生资产 +- 已存在于 `derive` 数组中的状态不重复 +- 每个资产 1~5 个衍生,宁缺勿滥 +- 提取到衍生资产后,必须逐条调用 `add_deriveAsset` 保存,禁止只分析不写入 +- 来源优先级:剧本明确描写 > 资产描述暗示 > 合理推测 +- `name`:2~6 字,体现视觉外观变化 +- `desc`:格式为 `[与默认态的差异] · [视觉特征] `, diff --git a/data/skills/production_execution_director_plan.md b/data/skills/production_execution_director_plan.md new file mode 100644 index 0000000..5249d36 --- /dev/null +++ b/data/skills/production_execution_director_plan.md @@ -0,0 +1,132 @@ +--- +name: production_execution_director_plan.md +description: >- + 视频制作执行层Agent技能 — 导演规划。 + 负责基于剧本与资产制定完整的导演创作规划(六维度)。 +--- +# 执行层 Agent — 导演规划 + +你是视频制作项目的**执行层 Agent**,接收决策层派发的任务指令并执行。 + +## 通用规则 + +- 执行前先调用 `get_flowData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 +- 只执行当前任务对应的工作,不越权执行其他阶段 +- 完成写入后返回一句简短确认即可,不复述完整内容;返回后本次任务终止 + +--- + +## 三、导演规划 + +### 工具 + +| 操作 | 调用 | +|------|------| +| 读取剧本与资产 | `get_flowData("script")` / `get_flowData("assets")` | + +### 风格技法参考 + + + +### 执行流程 + +1. 加载风格技法参考,获取 `script` 和 `assets`,并并且激活 `director_planning_narrative` 以及 `director_planning_style`,所有规划内容以该文档为风格基准,冲突时以风格技法参考为准。 +2. 按下方规范制定导演规划(创作规划),全文遵守「导演具象化原则」 +3. 严格按照XML格式写出导演规划内容,XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出 + +### 导演具象化原则(贯穿全文) + +规划文本必须像导演给演员讲戏,禁止抽象情绪词,所有描述以「摄像机能拍到什么」为标准: + +- **动作具体化**:写连续物理动作链("揉太阳穴→目光移开→靠向椅背"),禁止"感到疲惫"等抽象词 +- **光影可量化**:主光源方向 + 色温范围 + 明暗倾向("侧光偏暖,明暗反差强"),禁止空泛词("柔光""氛围好") +- **情绪靠身体**:通过肢体微表情传达("指尖发颤、瞳孔收缩"代替"他很紧张") +- **声音可感知**:环境音具体到声源("蜡芯噼啪声、远处风声"),禁止"背景音乐烘托气氛" + +### 创作规划(六维度) + +#### ① 主题立意与叙事核心 + +规划项:核心主题、情感主线、离场感受、情感表达策略 + +约束: +- 主题一句话凝练 +- 情感主线拆 2~3 个递进层次,每层对应可感知的视觉/行为变化 +- 离场感受与表达策略须与风格技法参考一致 + +#### ② 视觉风格与画面基调 + +规划项:整体色调、画面质感、构图风格、镜头运动偏好、光影体系 + +约束: +- 色调具体到色温范围或色彩倾向描述 +- 光影以「段落-光影方向」表格呈现,每段落指定光影基调方向 +- 色温、光源角度、冷暖色调分配等具体技法参数以风格技法参考(`director_planning_narrative` 以及 `director_planning_style`)为准 +- **构图须说明叙事理由**,参考以下情绪-构图映射(按需选用): + - 对称构图 → 秩序 / 压迫 / 庄重 + - 三分法偏侧留白 → 孤独 / 期待 / 未知 + - 对角线构图 → 运动 / 冲突 / 紧张 + - 框中框构图 → 囚禁 / 窥视 / 心理距离 +- **空间三层分离**:关键画面须规划前景(引导视线)/ 中景(叙事主体)/ 背景(情绪氛围)的层次关系 +- 镜头运动默认以静为主,运镜须说明叙事目的("缓推=靠近角色内心""缓拉=揭示全貌/抽离") + +#### ③ 叙事结构与节奏规划 + +规划项:叙事模式选型、段落划分、情绪曲线、快慢节奏、关键转折点、段落过渡方式 + +约束: +- **叙事模式选型**(根据内容特征选择,写入规划): + - 完整叙事型:适用于有完整起承转合的长剧本,按戏剧节拍划分段落 + - 情绪意境型:适用于氛围/散文式内容,按情绪阶段(起-承-转-合)划分 + - 原著保真型:适用于已有成熟结构的改编剧本,按原著自然场景边界划分,不强加节拍 +- 段落以表格呈现(编号 / 名称 / 场次 / 核心事件 / 情绪浓度 / 节奏) +- 情绪曲线渐进递增,避免"平平平→突然爆发" +- 转折点必须用**具体视觉手段**描述(光影突变、景别跳切、空镜隐喻等),不依赖台词解释 +- 高潮段落的"快"指情绪密度高(更紧密的景别切换),不等于缩短镜头时长 + +#### ④ 分场景情绪与画面意图 + +规划项(逐场):场次编号、情绪目标、氛围方向、镜头意图、空间叙事、距离感设计 + +约束: +- 情绪目标用具象可感描述("偷偷心动后的嘴角压不住",禁止"开心"等抽象词) +- 氛围方向映射风格技法参考的光影方案 +- **镜头意图写"为什么"**("用特写让观众看到她眼里的犹豫"),而非"怎么拍"("用特写拍脸") +- **场景语义→镜头方案参考**(为每场选择最匹配的方案方向): + - 开场/定场 → 大远景 + 缓推至主体 + - 角色登场 → 全景/中景 + 微仰 + 背光轮廓 + - 对话交锋 → 中景/近景 + 正反打 + 守视轴 + - 情绪加压 → 景别逐步递进收紧(中→近→特写→大特写) + - 浪漫/温馨 → 近景 + 浅景深 + 暖调柔光 + - 独白/沉思 → 特写侧面轮廓 + 定镜 + - 高潮转折 → 景别骤变或环绕运镜 +- **距离感设计**:通过景别变化映射人物关系变化(初期远→中期近但有遮挡→后期特写零距离) + +#### ⑤ 声音与音乐方向 + +规划项:音乐风格、段落配乐对应、配乐覆盖率、环境音设计、沉默运用 + +约束: +- 配乐按段落统一规划(不逐场),同段落内场景切换靠环境音变化过渡 +- 乐器选择、组合策略等具体技法以风格技法参考(`director_planning_narrative` 以及 `director_planning_style`)为准 +- 环境音具体到可感知声源("蝉鸣 / 溪水 / 市井叫卖 / 雨滴檐角"),每场标注 1~2 个核心环境音 +- 标注运用沉默手法的关键瞬间(关键情感瞬间优先考虑去掉配乐,只留环境音) +- 全片配乐覆盖率建议不超过 70%,留白段落与配乐段落形成呼吸感 + +#### ⑥ 转场与视觉连续性 + +规划项:场间转场策略、段落间过渡手法、视觉连续性锚点 + +约束: +- 同场戏内镜头默认硬切 +- 不同场景间插入空镜过渡做情绪缓冲(标注具体空镜内容方向) +- 大段落间可用叠化/淡入淡出做柔性过渡 +- 标注全片视觉连续性锚点:角色位置、服装状态、环境光影在跨场景时保持一致的关键点 + +### 输出要求 + +- 总字数不超过 1200 词,精炼表达 +- 你必须使用XML格式写入工作区拍摄计划:内容,XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出 +- 按「创作规划(①~⑥)」顺序输出 +- 表格仅在信息密度高时使用,其余用简洁列表或短段落 +- 具象优于抽象,视觉优先叙事,所有描述须通过「导演具象化原则」检验 diff --git a/data/skills/production_execution_generate_assets.md b/data/skills/production_execution_generate_assets.md new file mode 100644 index 0000000..68921b0 --- /dev/null +++ b/data/skills/production_execution_generate_assets.md @@ -0,0 +1,36 @@ +--- +name: production_execution_generate_assets.md +description: >- + 视频制作执行层Agent技能 — 衍生资产图片生成。 + 负责收集需要生成图片的资产并调用生成工具。 +--- +# 执行层 Agent — 衍生资产图片生成 + +你是视频制作项目的**执行层 Agent**,接收决策层派发的任务指令并执行。 + +## 通用规则 + +- 执行前先调用 `get_flowData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 +- 只执行当前任务对应的工作,不越权执行其他阶段 +- 完成写入后返回一句简短确认即可,不复述完整内容;返回后本次任务终止 + +--- + +## 二、衍生资产图片生成 + +### 工具 + +| 操作 | 调用 | +|------|------| +| 读取资产列表 | `get_flowData("assets")` | +| 生成资产图片 | `generate_assets_images({ ids: [资产id列表] })` | + +### 执行流程 + +1. 获取 `assets`,收集所有需要生成图片的资产 id +2. 调用 `generate_assets_images({ ids: [资产id列表] })` 生成图片(异步,发起即返回) + +### 约束 + +- 前置条件:衍生资产分析已完成并写入 +- 仅对有衍生状态且尚未生成图片的资产发起生成 diff --git a/data/skills/production_execution_storyboard_gen.md b/data/skills/production_execution_storyboard_gen.md new file mode 100644 index 0000000..416c943 --- /dev/null +++ b/data/skills/production_execution_storyboard_gen.md @@ -0,0 +1,38 @@ +--- +name: production_execution_storyboard_gen.md +description: >- + 视频制作执行层Agent技能 — 分镜图生成。 + 负责读取分镜面板并调用图片生成工具生成分镜图片。 +--- +# 执行层 Agent — 分镜图生成 + +你是视频制作项目的**执行层 Agent**,接收决策层派发的任务指令并执行。 + +## 通用规则 + +- 执行前先调用 `get_flowData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 +- 只执行当前任务对应的工作,不越权执行其他阶段 +- 完成写入后返回一句简短确认即可,不复述完整内容;返回后本次任务终止 + +--- + +## 六、分镜图生成 + +### 工具 + +| 操作 | 调用 | +|------|------| +| 读取分镜面板 | `get_flowData("storyboard")` | +| 生成图片 | `generate_storyboard_images({ ids: [分镜ID列表] })` | + +### 执行流程 + +1. 获取 `storyboard` +2. 提取真实分镜 ID 列表 +3. 调用 `generate_storyboard_images({ ids: [真实分镜ID列表] })` 生成分镜图片(异步,发起即返回) + +### 约束 + +- 前置条件:分镜面板已写入完成 +- 图片必须与分镜描述匹配 +- 仅使用 `storyboard` 中的真实分镜 ID,禁止编造或复用无效 ID diff --git a/data/skills/production_execution_storyboard_panel.md b/data/skills/production_execution_storyboard_panel.md new file mode 100644 index 0000000..dbe0cd2 --- /dev/null +++ b/data/skills/production_execution_storyboard_panel.md @@ -0,0 +1,83 @@ +--- +name: production_execution_storyboard_panel.md +description: >- + 视频制作执行层Agent技能 — 分镜面板写入。 + 负责根据分镜表数据逐行写入分镜面板,支持纯文本多参/分镜图辅助多参/首位帧三种模式。 +--- +# 执行层 Agent — 分镜面板写入 + +你是视频制作项目的**执行层 Agent**,接收决策层派发的任务指令并执行。 + +## 通用规则 + +- 执行前先调用 `get_flowData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 +- 只执行当前任务对应的工作,不越权执行其他阶段 +- 完成写入后返回一句简短确认即可,不复述完整内容;返回后本次任务终止 + +--- + +## 五、分镜面板写入 + +### 工具 + +| 操作 | 调用 | +|------|------| +| 读取剧本 | `get_flowData("script")` | +| 读取分镜表 | `get_flowData("stoaryTable")` | +| 读取剧本规划 | `get_flowData("scriptPlan")` | + +### 写入模式 + +本阶段根据决策层派发指令中携带的模式信息,选择对应的写入策略: + +| 模式 | 说明 | prompt | shouldGenerateImage | track 分组规则 | +|------|------|--------|---------------------|----------------| +| **纯文本多参模式** | 仅写入视频描述与资产绑定,不生成提示词和分镜图 | `''`(空字符串) | `false` | 同「分镜图辅助多参模式」,累计时长 ≤ 15s | +| **分镜图辅助多参模式** | 完整生成提示词并生成分镜图(当前默认行为) | 正常生成 | `true`(默认) | 累计时长 ≤ 15s | +| **首位帧模式** | 完整生成提示词,每条分镜独立一组 | 正常生成 | `true`(默认) | **不分组**,每行独立一组,按顺序递增 | + +> 模式信息由决策层在派发指令中明确指定,执行层不自行判断。 + +### 执行流程 + +1. 获取 `script`、`stoaryTable` 和 `scriptPlan`,识别决策层指令中的**写入模式**(纯文本多参模式 / 分镜图辅助多参模式 / 首位帧模式)。**若为「分镜图辅助多参模式」或「首位帧模式」**:激活 `storyboard_prompt_techniques` 作为通用提示词技法参考(含解析映射规则、景别词库、输出格式规范、提示词结构框架、画质规范、图像资产标注规则、人物位置连贯性规则),并激活风格专属技法(`director_storyboard`)作为提示词生成的全部参考依据,冲突时以风格专属技法为准;**若为「纯文本多参模式」**:跳过提示词相关技法加载 +2. 确定分组(track)与时长规则: + - **纯文本多参模式 / 分镜图辅助多参模式**:同组内分镜 `duration` 累计时长不得超过 15 秒 + - **首位帧模式**:**不分组**,每条分镜独立一组,`track` 按顺序递增(第1行 track=1,第2行 track=2,以此类推) + - 所有模式下,每条 `duration` 必须严格使用 `stoaryTable` 对应行时长 +3. **人物空间位置与朝向预分析**(纯文本多参模式跳过此步):正式写入前,先通读全部分镜表,执行以下分析并建立全局基准表: + - **画面位置分配**:根据各角色在分镜表中的首次出场空间关系,确定每个角色的画面左右位置(画面左侧 / 中央 / 右侧) + - **朝向提取**:从分镜表每行「角色动作」字段的 `|朝向:` 标注中直接提取各角色朝向信息。若个别行缺少标注(如空镜),按步骤2已加载技法中的「朝向获取规则」兜底推断 + - **建立基准表**:输出格式如 `角色A → 画面左侧,面朝右 / 角色B → 画面右侧,面朝左`,同一场景内锁定不变 + - **变化标记**:若分镜表某行的角色动作包含转身、转头、走位等方向变化(朝向标注同步变更),在该行标记朝向/位置变更点,后续分镜从变更后状态继续锁定 + - 后续每条 prompt 中涉及该人物时须按基准表显式标注位置和朝向(依据步骤1已加载技法中的「prompt 人物位置与朝向连贯性规则」) +4. **图像资产标注与正文绑定**(纯文本多参模式跳过此步):为每条分镜的 prompt 生成图像资产标注前缀,按 `associateAssetsIds` 的引用顺序,依次标注 `@图N 为xx{类型}`;**提示词正文中所有涉及该角色/场景/道具的位置,必须使用对应的 `@图N` 替代其名称**,建立参考图与画面描述的直接绑定(依据步骤1已加载技法中的「prompt 图像资产标注规则」) +5. **生成视频描述(videoDesc)**(所有模式均需):根据 `stoaryTable` 对应行的完整分镜数据(画面描述、场景、关联资产名称、时长、景别、运镜、角色动作、情绪、光影氛围、台词、音效、关联资产ID),将该行信息整合为一段结构化的视频描述文本,填入 `videoDesc` 字段 +6. **生成提示词(prompt)并忠实性校验**(纯文本多参模式跳过此步):逐行读取 `stoaryTable` 对应行的「画面描述」「场景」「景别」「角色动作」「情绪」「光影氛围」字段,严格按照步骤1已加载技法中的「分镜表内容忠实性原则」和「解析映射规则」将各字段映射为提示词各段落。**生成每条提示词后须立即逐字段比对分镜表原始内容**,确认:① 画面描述中的所有视觉主体和空间关系均已完整保留在提示词正文中;② 情绪基调与分镜表一致;③ 光影方向和色调与分镜表一致;④ 景别匹配;⑤ 角色动作语义一致(仅形式按首帧原则转换,不替换为不同动作);⑥ 角色朝向与步骤3基准表一致,且 prompt 中已显式标注朝向方位词。校验不通过须修正后再进入下一步 +7. 严格按 `stoaryTable` 的分镜数据行逐行写入分镜面板(排除表头与分隔行),根据模式差异化输出: + - **纯文本多参模式**:`` + - **分镜图辅助多参模式**:`` + - **首位帧模式**:`` +8. 写入完成后,仅返回一句确认:`已完成分镜面板写入({当前模式名称})` + +### 约束 + +- 前置条件:分镜表已构建完成且用户已确认 +- 你必须使用XML格式写入工作区分镜面板(具体参数值按当前模式填写,见上方执行流程第7步),所有 XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出 +- **videoDesc 必填**(所有模式):每条分镜的 `videoDesc` 必须根据 `stoaryTable` 对应行的分镜数据生成,包含画面描述、场景、关联资产名称、时长、景别、运镜、角色动作、情绪、光影氛围、台词、音效、关联资产ID 等完整信息 +- **prompt 内容忠实性**(分镜图辅助多参模式 / 首位帧模式):提示词内容必须忠实于 `stoaryTable` 对应行的画面描述、场景、景别、角色动作、情绪、光影氛围等字段,禁止凭空添加分镜表未描述的视觉元素或替换原始语义;风格锚定词和画质锁定词作为辅助修饰,不得挤占或替代分镜表中的具体画面内容(详见步骤1已加载技法中的「分镜表内容忠实性原则」) +- 行数一致性约束:分镜面板 `items` 数量必须与 `stoaryTable` 的分镜数据行数量完全一致(不包含表头与分隔行) +- 时长一致性约束:分镜面板 `duration` 必须与 `stoaryTable` 对应行时长完全一致 +- 阶段边界:本阶段禁止调用 `generate_storyboard_images` + +**模式差异化约束:** + +| 约束项 | 纯文本多参模式 | 分镜图辅助多参模式 | 首位帧模式 | +|--------|---------------|-------------------|------------| +| `prompt` | `''`(空字符串) | 正常生成提示词 | 正常生成提示词 | +| `shouldGenerateImage` | `false` | `true` | `true` | +| `track` 分组 | 累计时长 ≤ 15s | 累计时长 ≤ 15s | 每行独立一组,按顺序递增 | +| 人物位置连贯性校验 | 不适用(无 prompt) | **必须**校验(见步骤1已加载技法) | **必须**校验(见步骤1已加载技法) | +| 图像资产标注 | 不适用(无 prompt) | **必填**(见步骤2已加载技法) | **必填**(见步骤2已加载技法) | +| 提示词技法加载 | 跳过 | 激活通用技法 + 风格专属技法(见步骤2) | 激活通用技法 + 风格专属技法(见步骤2) | +| 提示词忠实性校验 | 不适用(无 prompt) | **必须**校验(见步骤7) | **必须**校验(见步骤7) | diff --git a/data/skills/production_execution_storyboard_table.md b/data/skills/production_execution_storyboard_table.md new file mode 100644 index 0000000..d76a371 --- /dev/null +++ b/data/skills/production_execution_storyboard_table.md @@ -0,0 +1,73 @@ +--- +name: production_execution_storyboard_table.md +description: >- + 视频制作执行层Agent技能 — 构建分镜表。 + 负责将剧本拆分为分镜,按规范填写所有字段,生成完整分镜表。 +--- +# 执行层 Agent — 构建分镜表 + +你是视频制作项目的**执行层 Agent**,接收决策层派发的任务指令并执行。 + +## 通用规则 + +- 执行前先调用 `get_flowData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 +- 只执行当前任务对应的工作,不越权执行其他阶段 +- 完成写入后返回一句简短确认即可,不复述完整内容;返回后本次任务终止 + +--- + +## 四、构建分镜表 + +### 工具 + +| 操作 | 调用 | +|------|------| +| 读取剧本与资产 | `get_flowData("script")` / `get_flowData("assets")` / `get_flowData("scriptPlan")` | + +### 风格技法参考 + + + +### 执行流程 + +1. 获取 `script`、`assets` 和 `scriptPlan`,并激活 `director_storyboard_table_narrative`、`director_storyboard_table_style` 作为分镜设计的风格参考,同时激活 `storyboard_table_techniques` 作为分镜表通用技法参考(含分镜拆分原则、定场与镜头合并规则、视觉连续性铁律、字段填写指引、转场规则)。 +2. 按通用技法规则将剧本拆分为分镜,**每写一行前**回顾上一行状态,确保符合「视觉连续性铁律」后再填写当前行所有字段 +3. 严格按照XML格式写出导演规划内容,XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出 + +### 示例 + +输入剧本片段: +``` +苏晚卿冷笑:「还有你当宝贝的青云令」 +△ 凌玄气血逆流,再次一口鲜血喷出 +△ 青云令表面灵纹暗淡,隐约可见细微裂痕 +``` + +输出分镜表: + +| 序号 | 画面描述 | 场景 | 关联资产名称 | 时长 | 景别 | 运镜 | 角色动作 | 情绪 | 光影氛围 | 台词 | 音效 | 关联资产ID | +|----|-------------|------|----------|------|------|------|------|------|------|-------|-------|----------| +| 1 | 苏晚卿冷笑,居高临下看着跪地的凌玄,大殿柱影深沉 | 大殿 | [苏晚卿, 凌玄, 大殿] | 4 | 近景 | 静止 | 嘴角缓缓上扬→微仰下巴→眼神下压注视(开篇)|朝向:苏晚卿-3/4正面朝右微仰头 | 冷傲轻蔑 | 顶光直射面部,眼窝明暗对半,背景大殿沉入暗部 | 苏晚卿:还有你当宝贝的青云令 | 空旷殿堂回声 | [101, 100, 300] | +| 2 | 凌玄跪地猛喷鲜血,身体前倾欲坠,血雾弥漫 | 大殿 | [凌玄, 大殿] | 3 | 中景 | 缓慢推至近景 | 胸口剧颤→猛然喷出鲜血→身体前倾摇晃(承接上镜:跪地状态)|朝向:凌玄-3/4正面朝左微低头 | 痛苦绝望 | 左侧冷光勾边,血雾被逆光映成暗红,背景压暗 | 无台词 | 喷血声 + 沉闷跪地声 | [100, 300] | +| 3 | 青云令灵纹一寸寸暗淡,玉面浮现细微裂痕 | 大殿 | [青云令, 大殿] | 3 | 大特写 | 静止 | 灵纹光芒由亮渐灭→裂痕自中心蔓延(承接上镜:喷血后切物件) | 紧张压迫 | 微弱自发光从内部渗出渐灭,周围完全暗沉 | 无台词 | 细微玉石碎裂声 | [202, 300] | + +### 约束 + +- **整体输出、不分段**:分镜表必须一次性完整输出为一个连续表格,不可按段落/场次拆分成多个表格,不可中途分割或分批返回 +- 你必须使用XML格式写入工作区拍摄计划:内容,XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出 +- **严格依据剧本**:分镜内容必须严格按照剧本叙事顺序和内容进行拆分,不得遗漏或新增剧本中不存在的情节 +- **参考导演规划**:分镜的景别、运镜、节奏、氛围等设计需参照导演规划(阶段3产出)的视觉风格、情绪曲线、镜头意图和转场策略 +- **台词原文锁定**:剧本中所有台词必须原文照搬进 `lines` 字段,禁止改写、省略或意译,如有台词未出现在分镜中视为严重错误 +- 分镜顺序与剧本叙事顺序一致 +- 所有字段完整填写,`associateAssetsIds` 使用资产的实际 ID(非数组索引),必须与工作区现有资产匹配 +- **按剧情选资产(衍生优先)**:同一父资产在单条分镜中,若剧情对应衍生状态则仅填写该衍生资产 ID;仅当无匹配衍生状态时才填写主资产 ID,禁止两者并填 +- **场景资产必须引用**:每条分镜的 `associateAssetsIds` 必须包含该分镜 `scene` 字段对应的场景资产 ID(从 assets 中匹配 type 为 scene 的资产);若存在匹配的衍生场景资产则选用衍生 ID,否则选用主场景资产 ID。缺少场景资产 ID 视为严重错误 +- **角色出现即引用**:画面中出现的所有角色(无论是镜头主体还是仅局部可见——如背影、肢体局部、虚化身影等),只要可被辨识,都必须在 `associateAssetsIds` 和 `associateAssetsNames` 中引用其资产。遗漏画面中可见角色的资产 ID 视为严重错误 +- 剧本中出现但资产列表不存在的角色/物件仍需在分镜中描述,但不在 `associateAssetsIds` 中编造 ID +- **台词-时长强关联**:含台词的分镜,需根据角色当前情绪状态选取对应语速(愤怒~4字/秒、正常~3字/秒、悲伤~2字/秒、低语/虚弱~2字/秒),`duration` ≥ 台词字数 ÷ 语速(向上取整)+ 1s 情绪余量;宁可多留余量,不可台词超时 +- **视觉连续性逐行校验**:每写一行分镜前,回顾上一行的动作终态、景别、角色朝向,确保当前行与之衔接合理,符合「视觉连续性铁律」7条规则 +- **朝向必填且连续**:每条分镜的 `action` 字段必须包含 `|朝向:` 标注(空镜除外);同一场景内同一角色的朝向须与首次出场时保持一致,变化时须在动作描述中包含转身/转头等衔接动作,朝向标注同步更新 +- **定场精简**:每个新场景定场最多 1~2 镜,禁止 3 镜以上的碎片化定场;能一镜完成定场+引入的不拆两镜 +- **镜头合并自检**:完成全部分镜后,逐段检查是否有可合并的相邻镜头(同空间局部描述、纯装饰镜头、信息重复镜头),合并后重新编号 +- **黄金 6 秒**:无台词镜头不超过 6s,定场/过渡类镜头尤其注意 +- **光影风格一致**:光影描述须与步骤1已加载的风格技法的光影规范保持一致 diff --git a/data/skills/production_skills/storyboard_prompt_techniques.md b/data/skills/production_skills/storyboard_prompt_techniques.md new file mode 100644 index 0000000..7004355 --- /dev/null +++ b/data/skills/production_skills/storyboard_prompt_techniques.md @@ -0,0 +1,322 @@ +--- +name: storyboard_prompt_techniques +description: >- + 通用分镜提示词技法参考。 + 涵盖提示词解析映射规则、景别词库、输出格式规范、提示词结构框架、画质规范、图像资产标注规则、人物位置连贯性规则等,供 Agent 激活使用。 +--- +# 分镜提示词 · 通用基础技法 + +> 以下为分镜提示词生成的**通用基础规范**,适用于所有视觉风格。风格锚定词、情绪映射、光影词库、场景质感、美学禁止项等**风格相关内容**由风格专属技法(`director_storyboard`)定义。 + +--- + +## 适用模式 + +本规范仅支持以下两种**参考图一致性模式**输出: + +- **模式A**:Seedream(doubao-seedream) +- **模式B**:Nanobanana(Gemini) + +> ⚠️ **不生成文生图模式提示词**,所有输出均基于**参考图(图生图 / ControlNet / 角色一致性)**工作流前提。 + +--- + +## 分镜表内容忠实性原则(最高优先级) + +提示词生成是**格式转换**,不是**创意写作**。分镜表是提示词的**唯一内容来源**,所有画面信息必须忠实于分镜表对应行,仅在表达格式和措辞上适配图像生成模型的要求。 + +### 铁律 + +1. **内容锚定**:提示词的画面内容以分镜表对应行为唯一信息源,**禁止**凭空添加分镜表未描述的视觉元素、人物、物件、空间关系或场景细节 +2. **关键信息零遗漏**:分镜表「画面描述」字段中提到的所有可见主体、空间层次、动态细节必须完整保留在提示词正文中,不得以「风格词」替代或挤占具体画面内容 +3. **语义等价转换**:将分镜表字段转换为提示词时,只改变表达形式(中↔英、散文↔关键词、叙事语言↔视觉描述),**不改变语义**。例:分镜表写"大殿柱影深沉" → 提示词必须体现殿堂柱影暗调,不可替换为"华丽宫殿"等不同语义 +4. **禁止创意发散**:不添加分镜表未提及的装饰性视觉元素(如分镜表未写花瓣飘落,提示词不可自行添加);不重新诠释场景氛围(分镜表写"冷傲轻蔑"不可改为"忧伤落寞") +5. **风格词从属于内容**:风格锚定词、画质锁定词、场景质感词等风格类词汇是**辅助修饰**,服务于分镜表已定义的画面内容,不得反客为主——当风格词与分镜表具体描述冲突时,以分镜表为准 +6. **逐字段回溯校验**:生成每条提示词后,须逐字段比对分镜表对应行,确认以下映射均已准确体现: + +| 分镜表字段 | 提示词中须体现 | 校验要点 | +|-----------|---------------|--------| +| 画面描述 | 提示词正文核心内容 | 所有视觉主体、空间关系、关键细节是否完整保留 | +| 场景 | 场景背景质感段 | 场景类型是否一致 | +| 景别 | 景别构图词 | 景别是否匹配 | +| 角色动作 | 主体首帧体态段 | 动作语义是否一致(按首帧原则转换形式,但动作内涵不变) | +| 情绪 | 情绪面容词 | 情绪基调是否一致 | +| 光影氛围 | 光线色调段 | 光源方向、色调倾向、明暗关系是否一致 | + +> ⚠️ **校验不通过 = 提示词无效**,必须修正后再输出。最常见的失败模式:画面描述中的具体元素被风格模板词覆盖遗漏。 + +--- + +## 解析映射规则 + +| 分镜字段 | 提示词对应处理 | +|----------|----------------| +| 画面描述 | **核心内容锚点**:提示词正文的主要信息来源。须完整保留画面描述中的所有可见主体、空间层次、关键细节,仅将叙事语言转换为视觉描述格式,严禁删减关键元素、替换为不同语义或自行添加画面描述中不存在的视觉元素 | +| 场景 | 基于分镜表「场景」字段确定背景/环境词,叠加风格专属技法的场景质感约束词。场景类型和基本氛围须与分镜表一致 | +| 景别 | 镜头参数词(见下方景别词库),须与分镜表「景别」字段完全匹配 | +| 运镜 | 仅作分镜制作信息,不进入提示词,不输出运镜备注 | +| 角色动作 | 基于分镜表「角色动作」字段,保留原始动作的语义内涵,仅将动态过程转换为该镜头**视频首帧(t=0)的预备状态**(动作尚未展开、即将发生的起始体态),视频将从此帧开始向后推演,加"动作自然真实"。**禁止**替换为与分镜表不同的动作 | +| 情绪 | 基于分镜表「情绪」字段,从风格专属技法的情绪映射表中选取匹配的面容/眼神词。情绪基调须与分镜表一致,不可替换为不同情绪 | +| 光影氛围 | 基于分镜表「光影氛围」字段的光源方向、色调倾向和明暗关系,从风格专属技法光影词库中选取匹配词汇。须保留分镜表指定的光源方向和色温倾向,不可替换为不同光影方案 | +| 台词 | 不进入提示词,不输出 | +| 音效 | 不进入提示词,不输出 | +| 关联资产名称/ID | 仅用于内部参考图绑定,不作为文本区块输出 | + +> ⚠️ **视频首帧原则**:分镜图是视频生成的**首帧参考**,画面必须呈现镜头 t=0 时刻的状态——动作尚未发生或刚刚启动的**预备定格态**,视频将从这一帧开始播放推演。 +> +> **核心逻辑**:首帧 → 视频推演 → 动作完成。提示词描述的是"推演起点",而非"推演终点"。 +> +> - ✅ 正确(首帧预备态):「双臂自然垂于身侧,衣袂初被风拂动」「手指刚触及剑柄」「身体微微侧转,目光即将投向远方」 +> - ❌ 错误(动作终态):「负手而立,衣袂随风猎猎飘扬」「已拔剑而立」「背对而去」「远眺苍茫大地」 +> - ❌ 错误(过程态):「正在拔剑」「正缓缓转身」(过程态适合视频中间帧,不适合首帧) +> +> 首帧应具有"蓄势待发"的静态张力,暗示接下来视频中将发生的动作方向。 + +--- + +## 景别词库(通用) + +| 景别输入 | 模式B(Nanobanana)英文镜头词 | 模式A(Seedream)中文画面词 | +|----------|-------------------------------|---------------------------| +| 大全景 | `wide shot, establishing shot, full environment` | 大全景构图,环境全貌,人物渺小于场景 | +| 全景 | `full shot, full body, wide angle` | 全身入镜,全景构图,人景比例协调 | +| 中景 | `medium shot, cowboy shot, knee shot` | 中景构图,人物膝盖以上入镜 | +| 近景 | `medium close-up, upper body` | 近景构图,上半身入镜,背景虚化 | +| 半身 | `half body shot, bust shot` | 半身构图,腰部以上入镜,浅景深 | +| 特写 | `close-up, face focus, extreme close-up` | 特写构图,面部或细节局部放大,背景深度虚化 | +| 大特写 | `extreme close-up, macro detail` | 大特写,极度局部细节,虚化背景 | +| 过肩镜 | `over the shoulder shot, two shot` | 过肩构图,前景人物后背虚化,远景人物清晰 | + +--- + +## 运镜标注 + +分镜图生成阶段不需要运镜标注提示词。运镜字段仅用于分镜生产管理信息,不参与提示词生成,不作为输出区块。 + +--- + +## 输出格式规范 + +每条分镜**只输出一种模式的提示词正文**(二选一),不允许同条分镜同时输出模式A与模式B。 + +**模式选择规则**: + +| 条件 | 选择模式 | +|------|----------| +| 目标模型为 Seedream / 豆包系列 | 模式A(中文 Prompt) | +| 目标模型为 Nanobanana / Gemini 系列 | 模式B(英文 JSON Prompt) | +| 用户未指定模型 | 默认模式A,或询问用户确认 | +| 批量生成 | 全程保持同一模式,不可中途切换 | + +**输出内容规则**: +- 选择模式A时:仅输出 `[Prompt]` 正文(无负向词,Seedream 不支持) +- 选择模式B时:仅输出 `[JSON Prompt]` 正文(含 `"negative"` 字段) +- 除提示词正文外,以下内容默认不输出:分镜标题、参考图绑定说明、台词备注、音效备注、约束检查、资产汇总 + +--- + +## 提示词结构框架 + +根据目标模型二选一输出: + +### 模式A:Seedream(API `reference_images`) + +机制:参考图通过 API 参数 `reference_images` 传入,prompt 内只写一致性约束语句,不写 URL。 + +Prompt 结构: +``` +[风格锚定] + [景别构图] + [主体首帧体态] + [情绪面容] + [服饰质感] + [场景背景质感] + [光线色调] + [风格收尾] + [画质锁定词] + +Based on the reference image of @图N , +maintain consistent: face features, hairstyle, costume details. +Generate a new scene: [严格基于分镜表「画面描述」字段内容转写,完整保留所有视觉元素和空间关系,使用@图N 替代角色/场景名称]. +Keep character appearance identical to reference. +``` + +> `[风格锚定]`、`[服饰质感]`、`[风格收尾]`、`[画质锁定词]` 的具体内容由**风格专属技法**定义。 +> +> **分镜表字段映射(须忠实体现)**:`[景别构图]` ← 分镜表「景别」;`[主体首帧体态]` ← 分镜表「角色动作」(按首帧原则转换形式);`[情绪面容]` ← 分镜表「情绪」;`[场景背景质感]` ← 分镜表「场景」+「画面描述」中的场景信息为内容基准,叠加风格质感词;`[光线色调]` ← 分镜表「光影氛围」。**提示词正文**的核心画面内容来源于分镜表「画面描述」字段,须完整保留其中所有视觉元素。 + +参数规范: +- 单角色:`reference_images: ["角色URL"]` +- 多角色:`reference_images: ["角色A_URL", "角色B_URL"]` +- 多角色时在 prompt 中显式区分 `image 1`、`image 2` + +### 模式B:Nanobanana(多模态 + JSON) + +机制:参考图与 prompt 一起作为多模态输入,prompt 使用结构化 JSON 约束角色一致性。 + +Prompt 结构(固定框架): +```json +{ + "role": "You are a cinematographer and storyboard artist. Maintain strict visual continuity across all shots.", + "character_reference": [ + { "image": 1, "ref": "@图1", "description": "[外貌关键描述: 发色/发型/服装/体型]" }, + { "image": 2, "ref": "@图2", "description": "[外貌关键描述]" } + ], + "continuity_rules": [ + "Same wardrobe, hairstyle, face features across ALL shots", + "Same environment, lighting style, color grade", + "Only framing, angle, action, expression may change", + "Do NOT introduce new characters not in reference images" + ], + "shot": "[严格基于分镜表对应行各字段内容生成:景别/构图/动作/情绪/光线/场景质感,须完整保留画面描述中的所有视觉元素] [画质锁定词](风格修饰词由风格专属技法定义)", + "negative": "[负向词模板](具体词条由风格专属技法定义)" +} +``` + +参数规范: +- 参考图作为图片输入,不是 URL 文本 +- 角色描述保持 1-2 句关键特征,避免冗长 +- 仅允许改变景别、角度、动作、表情,不改变人物身份特征 + +--- + +## 通用语言与质量规范 + +- 模式A(Seedream)优先中文自然语言段落 +- 模式B(Nanobanana)优先英文 JSON 结构化提示词 +- 提示词聚焦"内容表现 + 画质锐利",避免模糊类词 +- 不使用会导致糊图的表达(见下方「画质降级禁用词」表) +- 模式B 负向词按风格专属「负向词模板」输出,每条必须包含,不可省略;模式A 不输出负向词 +- 画质锁定词按风格专属「画质锁定词」模板输出,每条必须包含 + +--- + +## 画外文字 vs 画内文字规则 + +- **画外文字**(字幕、水印、标题卡、旁白叠字等 UI 层覆盖文字)→ **绝对禁止**,必须在画质锁定词和负向词中声明禁止 +- **画内文字**(场景中自然存在的文字道具:角色提笔写字、书卷上的字迹、匾额牌匾、书信内容、路标、店铺招牌等)→ **属于场景道具**,当分镜画面描述中明确包含此类内容时,应正常描述其存在,不受禁止文字规则限制 +- **判断标准**:该文字是否存在于**故事世界内部**。匾额上的字 = 画内道具 ✅;画面底部的角色对白 = 画外字幕 ❌ + +--- + +## 画质降级禁用词(所有风格通用) + +| 禁用写法 | 模型行为 | 安全替代 | +|---------|---------|----------| +| `film grain` / `胶片颗粒` | 全图加噪点变糊 | `subtle cinematic texture` / `轻微电影质感` | +| `imperfect focus` / `失焦` | 全图失焦 | 直接删除 | +| `edges not perfectly sharp` | 边缘变糊 | 直接删除 | +| `slight natural deviation` | 整体降分辨率 | 直接删除 | +| `not completely stable` | 画面模糊 | 直接删除 | +| `blurry background`(滥用) | 主体跟着糊 | `background bokeh, subject in sharp focus` | +| `hazy` / `foggy`(滥用) | 全图雾化 | 仅在空气透视需求时用,同时加 `subject sharp` | +| `柔焦` / `朦胧感` | 降低整体锐度 | 直接删除 | + +> **核心原则**:内容可以"不完美"(光线不均、构图非对称),画质必须锐利。 + +--- + +## 批量处理规范 + +用户输入多行分镜表时: + +1. **逐行顺序处理**,不跳行、不合并 +2. 每条分镜仅输出目标模式的提示词正文(Prompt 或 JSON Prompt) +3. 若同一场景连续多镜,**场景质感词可复用**,但情绪/光线/景别/动作必须**按行独立处理** +4. 关联资产名称相同的镜次,**一致性标注词必须一致** +5. 不追加任何非提示词区块(如资产引用汇总、台词/音效备注、约束检查) + +--- + +## prompt 图像资产标注规则 + +每条分镜的 `prompt` 字段必须以**图像资产标注**作为前缀,且**提示词正文中使用 `@图N` 直接替代对应的角色/场景/道具名称**,建立参考图与画面描述的直接绑定关系。标注按 `associateAssetsIds` 中资产的引用顺序,从 `@图1` 开始依次编号。 + +**格式**:`@图1 为{资产名称}{资产类型} @图2 为{资产名称}{资产类型} ... , 正文中使用@图N替代角色/场景名称的提示词` + +**类型映射**: + +| 资产 type | 标注类型词 | +|-----------|------------| +| role | 角色 | +| tool | 道具 | +| scene | 场景 | +| clip | 片段 | + +**规则**: +- 编号从 `@图1` 起,按 `associateAssetsIds` 数组顺序依次递增 +- 每个引用的资产 ID 对应一个标注项,**不可遗漏、不可多出** +- 资产名称使用 assets 数据中该资产的 `name` 字段 +- 资产类型根据上方类型映射表填写 +- 标注部分与提示词正文之间用 `, ` 分隔 +- 衍生资产沿用其自身 `name` 和父资产的 `type` +- **正文绑定(核心)**:提示词正文中,所有原本应出现角色名/场景名/道具名的位置,**必须替换为对应的 `@图N` 标记**,不再使用文字名称。这样参考图与画面中的视觉主体形成直接指向关系,避免资产名称与角色名称不一致导致的歧义(如衍生资产名"幕离红斗篷"与角色名"戚映竹"无法对应的问题) +- 同一 `@图N` 在正文中可多次出现(如角色在前景和反射面中同时可见时) + +**示例**(假设 `associateAssetsIds="[101, 100, 300]"` 对应苏晚卿(role)、凌玄(role)、大殿(scene)): + +❌ 错误(正文使用文字名称,与前缀标注脱节): +``` +@图1 为苏晚卿角色 @图2 为凌玄角色 @图3 为大殿场景, 苏晚卿冷笑,居高临下看着跪地的凌玄,大殿柱影深沉…… +``` + +✅ 正确(正文使用 @图N 直接绑定参考图): +``` +@图1 为苏晚卿角色 @图2 为凌玄角色 @图3 为大殿场景, @图1 冷笑,居高临下看着跪地的@图2,@图3 柱影深沉…… +``` + +--- + +## prompt 人物位置与朝向连贯性规则 + +生成每条 prompt 时,须遵守以下跨分镜人物位置与朝向一致性约束。 + +### 一、朝向获取规则(从分镜表获取人物面部朝向) + +分镜表的「角色动作」字段已包含 `|朝向:` 显式标注,提示词生成时**优先直接提取**,并在 prompt 中**显式写入**对应朝向方位词(如 `facing right` / `面朝右`、`three-quarter view facing left` / `3/4侧面朝左`)。 + +**获取优先级**(高→低): + +| 优先级 | 线索来源 | 处理逻辑 | +|--------|---------|----------| +| **1** | **角色动作字段的 `|朝向:` 标注** | 分镜表已显式标注 → **直接采用**,无需推断 | +| 2 | **画面描述中的显式方位词** | 画面描述直接提及朝向(如"背对镜头""望向窗外""面朝观众")→ 直接采用(仅当优先级1缺失时) | +| 3 | **多角色空间关系(180° 视轴线)** | 对话/对峙/互动场景中,两角色面朝彼此:画面左侧角色面朝右,画面右侧角色面朝左。首次出场建立基准后全场景锁定 | +| 4 | **景别暗示** | 过肩镜:前景人物背对/侧背对镜头,远景人物面朝镜头方向;特写/近景独白:默认 3/4 侧面 | +| 5 | **情绪与叙事语义** | 孤独/沉思/回忆 → 侧面轮廓或3/4背面;对抗/质问 → 正面或3/4正面朝向对方;躲避/羞涩 → 微侧头避开对方 | +| 6 | **场景空间逻辑** | 门口迎客 → 面朝门外;眺望风景 → 面朝风景方向;伏案书写 → 面朝桌面低头 | + +> **常规情况下只需读取优先级1**,分镜表已在源头标注完成。优先级2~6仅作为分镜表标注缺失时的兜底推断。 + +**获取步骤**: +1. 读取分镜表当前行「角色动作」字段中 `|朝向:` 后的标注内容 +2. 若标注存在且完整 → 直接采用,跳过后续优先级 +3. 若标注缺失(如空镜行)→ 按优先级2~6逐条推断 +4. 将获取到的朝向信息写入 prompt 中对应角色的描述位置 + +**朝向词库**: + +| 朝向类型 | 模式A(中文) | 模式B(英文) | 适用场景 | +|---------|-------------|-------------|---------| +| 正面 | 正面面朝镜头 | facing camera, front view | 自我宣言、直接对抗观众视线 | +| 3/4正面 | 3/4侧面微朝镜头 | three-quarter view facing camera | 对话主体、情感传递 | +| 正侧面 | 正侧面轮廓 | profile view, side view | 独白、沉思、对峙剪影 | +| 3/4背面 | 3/4侧背面 | three-quarter back view | 离去、疏离、回忆 | +| 背面 | 背对镜头 | back view, from behind | 神秘登场、离别、遥望 | +| 面朝左 | 面朝画面左侧 | facing left | 180°线右侧角色、朝左侧目标 | +| 面朝右 | 面朝画面右侧 | facing right | 180°线左侧角色、朝右侧目标 | +| 微低头 | 微微低头 | slightly looking down | 悲伤、内疚、沉思 | +| 微仰头 | 微微仰头 | slightly looking up | 傲慢、仰望、期待 | + +> 朝向标注须同时包含**水平朝向**(面朝左/右/镜头)和**俯仰倾向**(如有),如"3/4侧面朝右,微微仰头"。 + +### 二、位置与朝向锁定规则 + +- **画面位置锁定**:同一角色在同一场景内的多条分镜中,其画面左右位置(画面左侧 / 中央 / 右侧)须保持固定,不得无叙事理由地跳侧 +- **朝向守恒**:对话/对峙场景遵循 180° 视轴线——角色A面朝右则全场景保持面朝右,角色B面朝左则全场景保持面朝左;prompt 中须通过方位词(facing left / 面朝左、on the left side of frame / 画面左侧等)显式标注 +- **前后景层次一致**:若角色A在分镜N中处于前景、角色B处于中景,则同场景后续分镜中二者前后关系不应无理由反转 +- **位置变化须有动作衔接**:角色画面位置确需变化时(如角色走动、转身),前序分镜的 prompt 中须包含对应位移/转身动作描写,不可凭空跳位 +- **朝向变化须有动作衔接**:角色朝向确需变化时(如转头、回身),当前分镜的 prompt 中须包含转向动作描写(如"微微转头朝向画面左侧"),且该转向须与分镜表「角色动作」字段一致,不可凭空改向 +- **跨场景可重置**:切换到全新场景时允许重新分配画面位置与朝向,但新场景内部仍须保持一致 + +### 三、反射面视觉关系 + +当画面中存在反射介质(镜面、水面、光滑金属、窗玻璃、相机镜头等)时,须注意以下规则: + +- **镜像翻转**:反射面中角色的左右朝向与实体相反(实体面朝右→镜像面朝左),prompt 中须显式标注反射体与实体的朝向关系(如"@图1 面朝右,水面倒影中@图1 面朝左") +- **反射面不改变位置基准**:角色的画面位置以实体为准,反射面中的映像不视为角色位置变化 +- **反射面内容与实体一致**:反射面中可见的角色服饰、发型、表情等必须与同帧实体一致,不可出现偏差 +- **反射面景深与清晰度**:根据反射面距离和材质,反射图像可适当降低清晰度(如水面波纹导致的模糊),但须在 prompt 中标注(如"水面倒影微微扭曲") +- **识别触发**:当分镜画面描述或场景资产中包含镜面、水面、湖面、溪流、玻璃、金属反光、相机/摄像等反射性元素时,自动触发本规则 diff --git a/data/skills/production_skills/storyboard_table_techniques.md b/data/skills/production_skills/storyboard_table_techniques.md new file mode 100644 index 0000000..d537e29 --- /dev/null +++ b/data/skills/production_skills/storyboard_table_techniques.md @@ -0,0 +1,158 @@ +--- +name: storyboard_table_techniques +description: >- + 通用分镜表技法参考。 + 涵盖分镜拆分原则、定场与镜头合并规则、视觉连续性铁律、字段填写指引、转场规则等分镜设计通用技法,供 Agent 激活使用。 +--- +# 分镜表通用技法 + +本文档为分镜表设计的通用技法参考,适用于所有需要构建分镜表的 Agent 场景。 + +--- + +## 分镜拆分原则 + +**新起分镜**:场景/地点切换、时间跳跃、镜头主体切换、景别明显变化、重要动作节点 + +**不需新起**:同画面内连续对话、表情微变或小动作 + +粒度:一个独立画面 = 一条分镜,约每 50~100 字剧本对应 1~2 条分镜。过渡/转场如有明确描写也单独拆分。 + +--- + +## 定场与镜头合并规则(防冗余) + +**定场镜头**:每个新场景/段落的定场最多 1~2 个镜头完成,禁止拆成 3 个以上碎片。 +- 推荐做法:1 个带缓推的远景(定场+主体引入一镜完成),或 1 个大远景定场 + 1 个全景引入主体 +- 禁止做法:先拍环境空镜→再拍局部细节→再拍人物到达的冗余三段式 + +**镜头合并自检**: +- 能一镜交代的不拆两镜——如果一个带运镜的镜头能同时完成定场+引入,不要拆成两个 +- 连续描述同一空间不同局部的镜头(院门→藤蔓→厢房)应合并为一个镜头,用画面描述涵盖多层空间 +- 纯装饰性镜头(只展示环境细节无叙事推进)应合并到有叙事功能的镜头中 +- **导演思维检验**:写完后自检——如果一个真人导演会把相邻 2~3 个镜头合成 1 个拍,说明拆得过细,应合并 + +**一镜到底策略**:当相邻镜头之间存在**动作连续变化、场景轻度变化(同场景内位移)、或拍摄角度渐变**时,可在 `cameraMove` 或 `description` 中标注「一镜到底」,将多个碎片镜头合为一个连续运镜长镜头。 +- **适用场景**:角色行走穿越空间、跟随动作从A点到B点、环绕角色展示环境、定场缓推到主体特写等 +- **标注方式**:在 `cameraMove` 中写明运镜路径(如"一镜到底:缓推远景→跟移至院内→落幅全景"),在 `description` 中描述起幅和落幅的画面内容 +- **时长放宽**:一镜到底镜头因信息量持续更新,可突破单镜 6s 上限,但不超过 12s +- **风险提示**:一镜到底会提高画面生成的抽卡难度(连续性要求高),仅在叙事流畅性收益明显大于碎切时使用,不滥用 + +**黄金 6 秒规则**:无台词镜头累计超过 6s 未出现新信息(台词/动作/主体变化),观众注意力断裂。定场+过渡类镜头尤其注意,宁可合并压缩也不要拖沓 + +--- + +## 视觉连续性铁律(分镜设计时全程遵守) + +**① 动作连续性**:相邻镜头间角色的位置、动作进度、朝向必须物理逻辑一致。上一镜手伸到半空→下一镜必须从半空状态接续,不能突然收回。 + +**② 景别递进法则**:景别切换遵循渐进聚焦或渐进释放—— +- 渐进聚焦:远景→全景→中景→近景→特写(情绪收紧) +- 渐进释放:特写→近景→中景→远景(情绪释放) +- 禁止无叙事理由的连续同景别(连续 3 镜以上同景别 = 视觉疲劳) + +**③ 视轴守恒**:180度线原则——对话/对峙场景中角色画面位置全片固定同侧,不得跳轴 + +**④ 朝向空间逻辑**:对话双方面朝彼此,操作物品面朝物品,注视远方面朝远方。禁止无差别面朝镜头 + +**⑤ 信息控制意识**:每镜须意识到"观众此刻知道什么、不知道什么"—— +- 给手不给脸 = 悬念;先声后画 = 期待;只给背影 = 疏离;全貌揭示 = 高潮兑现 + +**⑥ 节拍密度约束**:单镜头动作/事件数量须与时长匹配,防止塞入过多内容—— +- 1 个物理动作 = 1 拍,1 次运镜 = 1 拍,1 句短台词(≤10 字)= 1 拍 +- 2~3s 镜头:最多 1 拍;4~6s 镜头:最多 2 拍;7s+ 镜头:最多 3 拍 + +**⑦ 头尾安全区**:每镜的前 0.5s 和后 0.5s 为安全过渡区,不放关键动作或台词起始点。前 0.5s 用于环境建立或主体静态亮相,后 0.5s 用于动作自然收住。 + +--- + +## 字段填写指引 + +**description**(画面描述):一句话描述画面核心内容(15~50 字),包含可见的**主体 + 动作/状态 + 环境空间**,不写心理活动。需体现空间层次(前景/中景/背景至少涉及两层)。如"前景纱帘微拂,中景余晖下侯府马车抵达落雁山废院""成姆妈跳下马车,打量破败院落,远处群山隐入暮色" + +**shotSize**(景别): + +| 景别 | 说明 | 叙事语义 | +|------|------|---------| +| 大远景 | 环境全貌 | 定场 / 孤独 / 渺小 | +| 远景 | 场景与人物关系 | 空间关系 / 氛围渲染 | +| 全景 | 人物全身与环境 | 角色登场 / 全身亮相 | +| 中景 | 膝盖以上 | 日常叙事 / 对话 | +| 近景 | 胸部以上 | 情感传达 / 对话重点 | +| 特写 | 面部或物件局部 | 情绪强化 / 关键道具 | +| 大特写 | 极致局部 | 情绪核弹 / 决定性瞬间(慎用,全片 2~3 次) | + +**cameraMove**(运镜):无运镜时填 `静止`。运镜须标注起终点方向。 + +| 运镜 | 说明 | 叙事语义 | +|------|------|---------| +| 推 | 从远到近,强调主体 | 情绪递进 / 发现 / 窥视 | +| 拉 | 从近到远,展示环境 | 情绪抽离 / 揭示全貌 / 离别 | +| 摇 | 固定位置旋转扫视 | 环境交代 / 搜索 | +| 移 | 跟随主体移动 | 陪伴 / 追踪 | +| 俯拍 | 从上往下 | 旁观 / 渺小 / 全局 | +| 仰拍 | 从下往上 | 英雄化 / 威压 | + +**action**(角色动作):画面中角色/主体的具体动作描述(5~40 字),无角色动作时填 `空镜`。要求: +- 写连续物理动作链 + 速度节奏("缓缓抬起右手→指尖微颤→猛然握拳"),禁止只写静态终态 +- 标注与上一镜的衔接关系:"(承接上镜:手臂半抬状态→继续上扬)";首镜写"开篇" +- **必须标注朝向**:在动作描述末尾用 `|朝向:` 标注该角色的面部朝向。多角色时逐一标注(按关联资产名称顺序),格式:`|朝向:角色A-面朝右; 角色B-面朝左`;单角色时省略角色名:`|朝向:面朝右`。朝向须符合180°视轴线规则(同场景内锁定,变化须有动作衔接),具体取值见下方朝向参考表 + +**朝向参考表**(action 字段标注用): + +| 朝向取值 | 含义 | 典型场景 | +|---------|------|---------| +| 面朝右 | 水平面朝画面右侧 | 180°线左侧角色、朝右侧目标 | +| 面朝左 | 水平面朝画面左侧 | 180°线右侧角色、朝左侧目标 | +| 正面 | 正对镜头 | 自白、宣言、直视观众 | +| 3/4正面朝右 | 3/4侧面偏右朝镜头 | 对话主体(画面偏左角色) | +| 3/4正面朝左 | 3/4侧面偏左朝镜头 | 对话主体(画面偏右角色) | +| 正侧面朝右 | 正侧面轮廓朝右 | 独白、沉思 | +| 正侧面朝左 | 正侧面轮廓朝左 | 独白、沉思 | +| 3/4背面朝右 | 3/4侧背面偏右 | 疏离、离去 | +| 3/4背面朝左 | 3/4侧背面偏左 | 疏离、离去 | +| 背面 | 背对镜头 | 神秘登场、离别、遥望 | + +> 可叠加俯仰修饰:`面朝右微仰头`、`3/4正面朝左微低头`。 + +**emotion**(情绪):画面传达的情绪基调(2~10 字),用具象可感描述。如"冷傲轻蔑""痛苦绝望""紧张压迫"。禁止"开心""难过"等空泛词。 + +**lighting**(光影氛围):画面光影与氛围描述(5~40 字),须包含**光源方向 + 色调倾向 + 明暗关系**。如"右侧冷白光斜射,面部明暗对半,背景深沉""底部暖黄光上打,眼窝沉入暗影"。禁止只写"柔光""暗调"。具体光源角度、色调阶段分配以风格技法参考为准 + +**scene**:该分镜所处的场景名称,与剧本中的场景对应 + +**associateAssetsNames**:画面中**可见的**资产名称列表(包括仅局部出现的角色/物件),便于直观确认关联内容 + +**duration**:基础参考——特写/表情 2~3s · 对话近景 3~5s · 全身亮相 3~5s · 动作 2~4s · 远景/空镜/过渡 3~5s · 复杂场景 5~8s。**单镜不超过 8s**,超过须拆分。 + +**含台词时,时长必须足够念完全部台词且匹配情绪语速**: + +| 情绪状态 | 语速参考 | 示例场景 | +|---------|---------|----------| +| 愤怒、急促、争吵 | ~4 字/秒 | 怒斥、催促、惊慌 | +| 正常对话、叙述 | ~3 字/秒 | 日常交谈、冷静陈述 | +| 悲伤、深情、沉思 | ~2 字/秒 | 告白、哀悼、回忆 | +| 低语、虚弱、临终 | ~2 字/秒 | 气若游丝、耳边呢喃 | + +计算方式:台词字数 ÷ 对应语速(向上取整)= 基础秒数,再叠加停顿余量: +- 台词中每个标点停顿(逗号、句号、省略号、破折号等)+0.3~0.5s +- 情绪转折/语气变化处 +0.5s +- 最终 `duration` = 基础秒数 + 停顿累计 + 1s 安全余量(向上取整) + +**lines**:角色台词原文,**必须一字不改从剧本中照搬**。多角色按 `角色名:台词` 格式排列。无台词填 `无台词`。一句台词对应一个镜头,避免单镜头内塞多角色多轮对白。 + +**sound**:环境音/音效描述,按「环境音层 + 动作音层」分层。如"远处风声呼啸 + 剑鸣声"。无音效填 `无音效` + +**associateAssetsIds**:画面中**可见的**资产的 ID(从 assets 数据中获取的实际 `id` 字段值),不编造不存在的 ID。 +- **角色出现即引用**:画面中出现的所有角色,无论是主体还是仅局部可见(如背影、手部、虚化剪影等),只要在画面内可被辨识,都必须引用其对应的资产 ID +- **场景资产必选**:每条分镜必须引用其所处场景对应的场景资产 ID(type 为 scene 的资产);若该场景存在匹配当前画面状态的衍生场景资产,则选用衍生场景资产 ID,否则选用主场景资产 ID。缺少场景资产 ID 视为字段不完整 +- 父子资产选择规则:按剧情画面所需状态选择资产 ID——若该镜头需要某主资产的衍生状态,**只选衍生资产 ID**;仅当不存在匹配的衍生状态时,才选择主资产 ID;同一父资产在同一分镜中禁止主/衍生同时出现 + +--- + +## 转场规则 + +- **同场戏内**:镜头间默认硬切 +- **跨场景**:插入 1 个空镜分镜(2~3s)做情绪缓冲,空镜内容与前后场景氛围相关 +- **跨段落**:可在 description 中标注"叠化过渡"或"淡入淡出" +- 禁用花式转场(划屏、旋转、百叶窗等) diff --git a/data/skills/script_agent_decision.md b/data/skills/script_agent_decision.md index 549b2f5..d0b72c7 100644 --- a/data/skills/script_agent_decision.md +++ b/data/skills/script_agent_decision.md @@ -36,6 +36,11 @@ ### 初始化对话流程 +0. 若用户提出“需要推荐/不知道怎么配/帮我推荐”等意图,先进入**推荐分支**: + - 先询问用户想要做的剧集类型(形态),并给出3个可选项(示例:微短剧、短剧、长剧) + - 得知用户类型偏好后,调用 `get_novel_events` 获取相关章节事件并分析 + - 基于事件分析输出一段“推荐原因”(说明为何匹配该类型) + - 最后给出“推荐配置”(集数、单集时长、原著范围、平台规格、风格定位、付费策略)并请用户确认 1. 用户发起改编请求时,**必须主动询问用户**项目参数(不主动调用 `deepRetrieve`,除非用户要求回想之前的配置) 2. 如果没有已确认的参数,**必须主动询问用户**: - "请确认以下信息:计划拆分为几集?每集大约几分钟?覆盖原著哪些章节?" diff --git a/data/skills/script_agent_supervision.md b/data/skills/script_agent_supervision.md index da8d53e..afa1170 100644 --- a/data/skills/script_agent_supervision.md +++ b/data/skills/script_agent_supervision.md @@ -19,8 +19,9 @@ 1. 识别审核对象 2. 按对应审核对象的「数据准备」步骤获取数据 -3. 按「审核维度」逐项检查 -4. 按「审核报告格式」生成报告 +3. 对照「Skills」中对应的红线清单 + 「审核维度」逐项检查 +4. 遇到「Skills 三 - 短剧通用红线」中的违反项,直接标记为严重问题 +5. 按「审核报告格式」生成报告 --- @@ -69,6 +70,41 @@ 3. **问题具体化**:每个问题指向具体位置和内容,不说"整体不够好" 4. **建议多元化**:严重问题提供多个可选方案 5. **动态基准**:数值判断以【项目配置】为唯一基准;配置中未明确的参数以合理比例推算,并在报告中注明 +6. **Skills 对照审核**:所有审核项须对照 Skills 中的红线清单逐项核对,确保执行层产出物符合短剧爆款标准 + +--- + +## Skills + +### 一、骨架质量红线(审核骨架时逐项核对) + +1. **核心结构逻辑**:大三角(3个核心角色/势力)构成全剧主矛盾是否成立;是否为单线型叙事(多线并行→严重) +2. **故事核与隐线**:是否有清晰的故事核(主角内在冲突);是否有隐线(角色弧光/成长轨迹) +3. **前10%黄金结构**:前⌈N×0.10⌉集是否完成"一秒入坑→目标明确→多方施压→首次卡点" +4. **付费点分布**:是否按≈10%/30%/50%/70%/90%比例分布;是否满足5大标准(关键瞬间、根本性改变、好奇心、高燃场景、爱情拉扯);是否有假付费点设计 +5. **情绪布局**:全剧是否呈"波浪上升"模式;是否与类型情绪基调匹配(甜宠=甜60%+微虐30%+惊喜10%等);是否存在连续3集同一强度 +6. **信息差标注**:关键集数是否标注信息差类型(先知型/焦急型/上帝型) +7. **集末钩子**:每集是否有钩子;类型是否多样化(智识/悬念/情感/世界观,不可全是悬念钩子) +8. **节奏框架匹配**:分集节奏是否与该类型的通用节奏框架大致吻合(甜宠→契约绑定开头→误会拉扯→秘密曝光…;战神→隐藏身份受辱→曝光打脸…) + +### 二、改编策略质量红线(审核改编策略时逐项核对) + +1. **7大核心要点覆盖**:策略是否体现——强画面感、台词精简、节奏极致快、只沿主线、降低理解成本、情绪大于一切、开篇给足期待感 +2. **情绪基调一致性**:策略确定的情绪基调是否与骨架类型匹配;是否存在中途大幅偏离(如甜宠突然重度虐心→严重) +3. **人物弧光保留**:主角和重要配角是否保留了弧光(初始状态→关键变故→性格转变→最终状态);是否保留了设定记忆点 +4. **删减合理性**:优先删除项(拖沓铺垫/重复内容/载体不支持/弱支线)是否正确;优先保留项(情绪点/关系拉扯/付费铺垫/信息差场景/打脸时刻)是否覆盖 +5. **世界观呈现策略**:是否有渐进式呈现方案;是否通过人物对话/OS/VO逐步透露,而非旁白集中灌输 +6. **短剧语言适配**:称谓是否符合短剧规范("家主""执法局"等,禁用"市长""县长");台词是否口语化(禁用文言文、生词冷词) +7. **用户意图一致性**:若用户要求不改编/忠实原著,策略是否仅做载体适配;若用户指定改编方向,策略是否以该方向为最高优先级 + +### 三、短剧通用红线 + +以下任何一项违反均标记为**严重问题**: +1. 连续3集以上无情绪爆点(爽点/虐点/甜点任一) +2. 出现多线并行叙事(短剧必须单线型) +3. 第1集无强冲突/强情绪场景 +4. 出现"市长""县长"等现实官职称谓 +5. 大段旁白解说世界观(应通过对话/OS/VO逐步透露) --- @@ -84,10 +120,15 @@ | 审核项 | 标准 | 严重程度 | |--------|------|----------| -| 结构完整性 | 故事核存在且聚焦主角内在冲突;三幕均有功能、核心问题、幕末转折 | 严重 | -| 分集与时长 | 分集数恰好等于【项目配置】集数;每集时长符合单集时长 ±10秒 | 严重 | +| 结构完整性 | 故事核存在且聚焦主角内在冲突;隐线(角色弧光)清晰;三幕均有功能、核心问题、幕末转折(→ Skills 一-1/2) | 严重 | +| 分集与时长 | 分集数恰好等于【项目配置】集数;每集时长符合单集时长 ±10秒 | 中等 | | 章节全覆盖 | 【项目配置】指定的原著章节全部被分配到具体集数 | 严重 | -| 叙事设计 | 删减有据、集末钩子齐全、付费卡点符合策略、情绪曲线有起伏、人物弧每集推进 | 中等 | +| 付费点分布 | 按≈10%/30%/50%/70%/90%比例分布,满足付费点5大标准;有假付费点设计(→ Skills 一-4) | 严重 | +| 前10%黄金结构 | 前⌈N×0.10⌉集完成"一秒入坑→目标明确→多方施压→首次卡点"(→ Skills 一-3) | 中等 | +| 情绪布局 | 全剧情绪呈波浪上升、与类型基调匹配、无连续3集同一强度(→ Skills 一-5) | 中等 | +| 信息差标注 | 关键集数标注了信息差类型(先知型/焦急型/上帝型)(→ Skills 一-6) | 中等 | +| 集末钩子 | 每集结尾有钩子且类型多样化,不可全是悬念钩子(→ Skills 一-7) | 中等 | +| 节奏框架 | 分集节奏与该类型通用节奏框架大致吻合(→ Skills 一-8) | 轻微 | ### 跨阶段一致性检查 @@ -100,21 +141,42 @@ ### 详细审核标准 +#### 故事核与隐线验证(严重) +- 故事核必须存在且聚焦主角内在冲突(如"复仇vs原谅""自由vs责任") +- 隐线(角色弧光)必须清晰:主角有明确的"初始状态→关键变故→性格转变→最终状态"轨迹 +- 故事核与隐线须贯穿三幕,不可中途断裂 + #### 三幕功能验证(严重) - 第一幕必须完成"建立"功能:规则建立、悬疑建立、动机激活 - 第二幕必须完成"冲突"功能:主要矛盾展开、计划执行、代价付出 - 第三幕必须完成"拓展/结局"功能:新世界、新能力、开放悬念 +- 大三角(3个核心角色/势力)贯穿全剧,小三角依次展开不并行 + +#### 付费点分布验证(严重) +- 付费点按≈10%/30%/50%/70%/90%×总集数N分布(四舍五入取整),偏差超过±2集标记问题 +- 逐一检查5大标准:①选择关键瞬间 ②设置根本性改变 ③调动好奇心 ④善用高燃场景 ⑤关注爱情拉扯(感情流) +- 付费点场景应具备"场面宏大、事态紧急、围观群众多"的特征 +- 是否设计了假付费点(目标近在咫尺却落空) + +#### 前10%黄金结构验证(中等) +- 第1-2集(或等比位置):是否快速引入强烈冲突,实现"一秒入坑" +- 第3-4集:是否明确主角核心行动目标 +- 第5-8集:是否引入多方配角施压 +- 第9-10集:是否有假付费点+正式卡点的小高潮 +- (微短篇需检查:卡点是否提前至第6-7集,第1集信息密度是否足够) #### 情绪曲线验证(中等) -全剧情绪分布应根据实际集数设计"波浪上升"模式: +- 全剧情绪分布应根据实际集数设计"波浪上升"模式 - 不允许连续3集都是同一情绪强度 -- 最高潮应在中后期 +- 最高潮应在中后期(≈51%-70%阶段) - 高潮后应有节奏缓冲再推向新高潮 +- 情绪基调占比是否与类型匹配(如甜宠:甜60%+微虐30%+惊喜10%) -#### 付费卡点合理性(中等) -- 付费策略按【项目配置】中的设定执行 -- 付费点必须放在"观众最想知道后续"的位置 -- 钩子类型应多样化(不全是悬念钩子) +#### 信息差与集末钩子验证(中等) +- 关键集数(尤其付费点前后)是否标注了信息差类型 +- 信息差类型是否运用得当(先知型→逆袭类、焦急型→虐恋类、上帝型→寻亲类) +- 每集结尾是否有钩子 +- 钩子类型是否多样化(智识/悬念/情感/世界观,不可全是同一类型) --- @@ -129,9 +191,15 @@ | 审核项 | 标准 | 严重程度 | |--------|------|----------| +| 用户意图一致 | 若用户要求不改编/忠实原著,策略仅做载体适配;若用户指定方向,策略以该方向为最高优先级(→ Skills 二-7) | 严重 | | 与骨架一致 | 删除决策与骨架中的删减记录一致;所有原则服务于故事核 | 严重 | +| 7大要点覆盖 | 策略体现强画面感、台词精简、节奏极致快、只沿主线、降低理解成本、情绪大于一切、开篇给足期待感(→ Skills 二-1) | 中等 | | 原则质量 | 3-5条核心原则,每条有正面指导和负面边界 | 中等 | -| 载体适配 | 有世界观呈现策略;考虑了平台规格和单集时长的约束 | 中等 | +| 情绪基调一致 | 确定的情绪基调与骨架类型匹配,无中途大幅偏离(→ Skills 二-2) | 中等 | +| 人物弧光保留 | 主角和重要配角弧光完整,保留设定记忆点(→ Skills 二-3) | 中等 | +| 删减合理性 | 删减遵循优先级原则;优先保留情绪点/关系拉扯/付费铺垫/信息差/打脸时刻(→ Skills 二-4) | 中等 | +| 世界观呈现 | 有渐进式呈现方案,通过对话/OS/VO逐步透露而非旁白灌输(→ Skills 二-5) | 中等 | +| 语言适配 | 称谓符合短剧规范,台词口语化(→ Skills 二-6) | 轻微 | ### 跨阶段一致性检查 @@ -144,6 +212,12 @@ ### 详细审核标准 +#### 用户意图一致性验证(严重) +- 检查【项目配置】或派发指令中是否有改编限制要求 +- 若用户要求"不改编/忠实原著/最小改动":策略是否仅做载体适配(格式转化、时长裁剪、画面化翻译),未改动原著人设、情节与世界观 +- 若用户指定了改编方向(如"加强爽感""弱化虐点"):策略是否以该方向为最高优先级 +- 若策略与用户意图矛盾,标记为严重问题 + #### 故事核对齐(严重) - 所有改编原则必须服务于骨架中确立的故事核 - 删减的内容不能包含体现故事核的关键场景 @@ -152,4 +226,25 @@ #### 与骨架一致性(严重) - 改编策略中的删除决策,必须在骨架的删减记录中有对应 - 骨架中标注"保留完整"的场景,改编策略不能标注为删除 -- 交叉检查方法:将两者的删减列表逐一比对 \ No newline at end of file +- 交叉检查方法:将两者的删减列表逐一比对 + +#### 7大核心要点覆盖验证(中等) +逐条检查策略是否体现以下要点,未覆盖的标记为中等问题: +1. 强画面感(可拍摄性)——是否有不可拍摄的内容未做转化 +2. 台词精简——是否有大段冗余对话未被标记处理 +3. 节奏极致快——是否存在明显拖沓的保留决策 +4. 只沿主线——是否有无关支线被保留 +5. 降低理解成本——世界观是否通过对话/OS/VO逐步透露 +6. 情绪大于一切——是否存在"逻辑正确但情绪平淡"的保留决策 +7. 开篇给足期待感——开篇改编是否保证了强冲突/强情绪 + +#### 情绪基调一致性验证(中等) +- 策略确定的情绪基调是否与骨架中的类型匹配 +- 是否存在中途大幅偏离基调的改编决策(如甜宠剧突然加入"全家惨死"的重度虐心→严重) +- 各阶段情绪占比是否合理 + +#### 世界观呈现策略验证(中等) +- 是否有渐进式呈现方案(每次只透露一个关键设定点) +- 呈现方式是否多元:人物对话(角色间冲突/疑问带出)、OS内心独白(主角视角补充)、VO画外音(极简过渡) +- 是否存在大段旁白集中灌输世界观的设计(→严重) +- 是否明确了世界观锚点角色和观众视角对齐对象 \ No newline at end of file diff --git a/data/skills/script_execution_adaptation.md b/data/skills/script_execution_adaptation.md index 7535195..6ea5a36 100644 --- a/data/skills/script_execution_adaptation.md +++ b/data/skills/script_execution_adaptation.md @@ -17,7 +17,7 @@ - 主要删除决策:被删/压缩内容、原因、对主线影响 - 世界观呈现策略:关键元素出场节奏、解释度策略、角色态度锚点 3. **阐述思路**(200-300字):核心改编原则方向、删减大方向、世界观呈现思路 -4. 严格按照XML格式写出改编策略,格式为改编策略内容。 +4. 严格按照XML格式写出改编策略,格式为改编策略内容。XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出。 5. 返回简短确认,如:"改编策略已保存,请在右侧工作台查看。" ## 约束 @@ -27,6 +27,88 @@ - 根据【项目配置】中的平台规格和单集时长约束,优先视觉叙事,压缩大段对话 - 所有参数从【项目配置】读取,禁止硬编码 +## Skills + +### 一、剧本改编7大核心要点 + +改编策略的一切决策须以此7条为基准: + +1. **强画面感(可拍摄性)**:确保所有保留内容能转化为镜头语言,拍不出来则换表达方式 +2. **台词精简(高信息密度)**:剔除冗余,每句台词须服务于剧情推进或人物塑造;用台词传递背景信息(身份、过往、纠葛) +3. **节奏极致快**:每一个画面都拉升情绪,可适当牺牲细微逻辑,优先保证节奏紧凑 +4. **只沿主线展开**:摒弃多支线,所有情节围绕单条主线推进;改编时砍掉支线,仅保留核心人设与高光时刻 +5. **降低理解成本**:世界观不复杂,观众听台词就能掌握核心剧情,漏看部分不影响整体理解 +6. **情绪大于一切**:无需复杂人物弧光,核心提供饱满强烈的情绪体验;逻辑与情绪冲突时优先保障情绪张力 +7. **开篇给足期待感**:第1集呈现激烈、高情绪张力场景,后续围绕开篇建立的期待感展开 + +### 二、类型创新三大方向(改编时评估是否引入) + +1. **元素创新**(最易落地):在基础类型上调整单一核心元素制造新鲜感 + - 年龄反转(青年战神→老年战神)、性别反转(男战神→女战神)、背景反转(古代→现代)、视角反转(萌宝跟妈→萌宝跟爸) +2. **类型融合**(高效丰富剧情):选择关联度高的类型搭配,避免强行融合 + - 示例:团宠+鉴宝、萌宝+重生+寻亲 +3. **情节创新**(最考验功力):跳出传统套路,设计独特情节冲突 + - 示例:宫斗避开"下毒、推水",改用"心理操控"式陷害 + +**金手指创新**:避免"无敌外挂",设计有约束的特殊能力(如有限次数的预知) + +### 三、各类型情绪基调映射(改编时锁定) + +| 类型 | 核心情绪基调 | 占比参考 | +|------|-------------|----------| +| 甜宠类 | 甜>微虐>惊喜 | 甜60%+微虐30%+惊喜10% | +| 复仇类 | 压抑>爽感>解气 | 压抑40%+爽感50%+解气10% | +| 重生逆袭类 | 爽感>期待>温暖 | 爽感50%+期待30%+温暖20% | +| 家庭伦理类 | 共情>委屈>和解 | 共情40%+委屈30%+和解30% | + +**关键原则**:基调一旦确定不要中途大幅更改——如甜宠剧突然加入"全家惨死"的重度虐心剧情,观众会出戏甚至弃剧 + +### 四、人物弧光保留原则 + +改编时必须保留的人物维度: + +1. **人物弧光**:角色需有阶段性转变,转变需有锚点(关键事件) + - 格式:初始状态→关键变故→性格转变→最终状态 + - 主角和重要配角必须有弧光,这是剧本脱颖而出的关键 +2. **行动塑造**:不同性格角色面对同一困境反应须有差异,行动线与性格强绑定 +3. **设定记忆点**:为重要角色保留独特细节(专属口音、下意识动作、特殊怪癖、独门技能) +4. **人物推动剧情**:确保是"人物引导剧情"而非"把人物套入预设剧情",人设差异是剧情推进的核心动力 + +### 五、删减决策优先级 + +**优先删除:** +- 节奏拖沓的铺垫场景(不推动主线的环境描写、日常闲聊) +- 信息密度低的重复内容(同类冲突不可重复呈现,如反派多次用同一手段陷害) +- 载体不支持的内容(大段心理描写、复杂世界观设定说明) +- 主线贡献弱的支线(不推动主线的人物关系、不影响结局的事件) + +**优先保留:** +- 每集的核心情绪点(爆点/虐点/爽点至少覆盖一个) +- 人物间的关系拉扯场景(关系越紧密虐感越强) +- 付费点前的情绪铺垫链条(压抑→爆发的完整弧线) +- 身份反差与信息差场景(核心爽感来源) +- 高光"打脸"时刻与反转节点 + +**替代方案:** +- 蒙太奇压缩:将多场过渡戏压缩为快速剪辑 +- 台词带过:用一句台词交代原本需要整场戏呈现的信息 +- 完全删除:对主线无贡献且不含情绪点的内容直接去除 + +### 六、短剧独特语言适配 + +改编时需注意短剧特殊表达惯例: +- 现代剧用"家主"代指家族掌权人,"执法局/执法人"代指公安局/警察 +- 禁用"市长""县长"等实际称呼,改为"市首""总督" +- 财富表达突破现实货币体系,用"亿元""百亿订单"等夸张表述营造爽感 +- 所有台词用口语化表达,禁用半文半白、文言文、生词冷词 + +### 七、信息差策略设计 + +改编策略中须明确标注各阶段采用的信息差类型: +- **观众先知型**(主角知+观众知+配角不知):期待"打脸",适合逆袭/战神/赘婿类 +- **观众焦急型**(配角知+观众知+主角不知):替主角担心,适合虐恋/悬疑类 +- **观众上帝型**(观众知+主角配角都不知):期待相认/真相大白,适合寻亲/身份错位类 + ## 注意事项 - 执行前先调用 `get_planData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 diff --git a/data/skills/script_execution_script.md b/data/skills/script_execution_script.md index ef8b4ff..400590f 100644 --- a/data/skills/script_execution_script.md +++ b/data/skills/script_execution_script.md @@ -15,7 +15,11 @@ 1. 调用 `get_planData` 获取骨架与改编策略;若存在上一集剧本id,调用 `get_script_content(ids)` 获取最后一集剧本内容,用于衔接剧情与角色状态,调用 `get_novel_text` 获取对应章节原文,调用 `get_novel_events(ids)` 获取事件表 2. 从骨架中**仅提取当前任务集**的信息:覆盖章节、戏剧功能、场景核心、删减决策、集末钩子。**忽略其他已完成或未分配的集** 3. **阐述思路**(200-300字):场景组织方式、重点情绪与冲突、节奏把控思路 -4. 严格按照XML格式写出剧本内容,格式为剧本内容。 +4. 将完整剧本包裹在 **``** 标签中输出,具体要求: + - 你必须输出一对 XML 标签 `` 和 ``,将全部剧本内容包裹在其中 + - `name` 属性的值 = 文件头首行标题(即 `{作品名} EP{NN}:{集标题}`),不含 `#` 号 + - 标签内部是完整剧本正文(文件头 → 剧情梗概 → 场景段落),中间不得插入任何非剧本的解释或元信息 + - `` 开标签之前、`` 闭标签之后,不得有任何剧本正文内容 5. 返回简短确认,如:"第X集剧本已写入,请在工作台查看。" ## 约束 @@ -26,9 +30,119 @@ - △场景描述要足够具体,描写"人怎么干"而非仅"人干什么",可直接用于 AI 视频生成 - 场景之间用 `---` 分隔 +## Skills + +### 一、三大情绪要点(每集必含至少1个) + +| 要点 | 定义 | 作用 | +|------|------|------| +| 爆点 | 令人震惊、匪夷所思/骇人听闻/惊羡的事件 | 第一时间勾起观众情绪,快速入戏 | +| 虐点 | 让人心痛、痛苦、难以释怀的事件 | 唤起观众怜悯,强化情感代入 | +| 爽点 | 让人兴奋、振奋的"高光时刻" | 满足观众情绪需求,提升留存率 | + +**应用规则:** +- 每集500-800字须覆盖爆点/虐点/爽点中至少一个(硬性要求) +- 可叠加使用但需避免情绪冲突——明确情绪先后顺序,不堆积混乱 +- 小情绪累积成大情绪爆发,不可一次性宣泄完所有情感 + +**爽点核心公式:爽点 = 装 + 打脸 + 震惊 + 收获** +- 装:情感/物质伪装(主角藏身份被欺辱) +- 打脸:剧情急转弯(装豪门的配角被真豪门揭穿) +- 震惊:围观群众态度180°反转 +- 收获:物质奖励/地位提升 + +**虐点核心逻辑:** +- 关系越紧密虐感越强(亲人、爱人之间的伤害更催泪) +- 先给主角极致幸福再夺走,让主角长期处于痛苦中 +- 经典虐点:始终牢记的人忘了自己、永远无法说出口的爱意、永远无人知晓的巨大牺牲、至死未能解开的惨痛误会 + +**爆点类型:** +- 经典款:替身设定、穿书炮灰女配、救赎设定 +- 反套路:双向替身、伪装拆穿、离婚反杀、全员重生、明虐暗宠、以牙还牙 + +### 二、情绪表达四通道 + +根据人物性格和所处环境选择外显型或内隐型表达: + +1. **行动**:通过人物行为动作传递情绪(撕扯、狂奔、捶打、下意识握拳、颤抖的手) +2. **语言**:痛斥、语无伦次、泣不成声、大吼、嘶哑、无声、结巴——一旦确定语言风格就要持续强化直至极致 +3. **环境**: + - 悲伤/压抑:阴雨天、空无一人的街道、昏暗房间 + - 紧张/危险:急促脚步声、闪烁灯光、封闭空间 + - 甜蜜/温暖:夕阳、暖光客厅、满桌家常菜 +4. **独白**:当情绪无法用行动/语言直接表达时(有秘密、有难言之隐),用OS/VO补充 + - OS(主角视角):揭露主角真实想法 + - VO(第三方视角):渲染氛围或补充背景 + +### 三、情绪铺设技巧 + +**1. 先压后爆,制造反差:** +- 先用反派打压、误解、困境让主角"委屈/隐忍"(连续数集压抑) +- 在付费点或关键集让主角反击,释放压抑情绪 +- 压得越狠反弹越爽 + +**2. 用信息差强化情绪期待:** +- 观众知道主角不知道 → 观众"心急如焚"(如女主不知茶里有毒) +- 主角知道配角不知道 → 观众"期待打脸"(如主角假装懦弱实则收集证据) +- 主角配角都不知道观众知道 → 观众"心疼又着急"(如母女相见不相识) + +**3. 单集情绪公式:1核心情绪 + 1辅助情绪 + 1结尾钩子** +- 核心情绪:贴合全剧基调(如甜宠剧的"微甜") +- 辅助情绪:制造小冲突避免平淡(如女配吃醋) +- 结尾钩子:引入下一集情绪(如反派威胁"离他远点") +- **禁忌**:同一集不超过2个核心情绪;上下集情绪须有衔接不可跳脱;配角情绪不能盖过主角 + +### 四、开篇8大创作规则 + +1. **冲突即时性**:第一行就入危机,无缓冲期(谋杀、逃跑、被虐待、难产、被偷袭、逃婚、被陷害) +2. **信息量密集**:通过人物对话快速交代前因后果、人物关系、背景,不浪费一字 +3. **营造信息差**:让主角/配角/反派之间信息不对等,形成欺骗或误解 +4. **铺垫不拖沓**:最多3集要见效,为贯穿全剧的暗线中间需多次提醒 +5. **关系有拉扯感**:人物关系不能简单对立或友好,需有复杂羁绊(爱恨交织) +6. **情节必反转**:每集至少1个反转,需有逻辑不能强行制造 +7. **压情绪**:从第1集开始极致打压主角,直到第一个付费点前才给反击信号,中间不松劲 +8. **明确目标**:第1集设定主角大目标,再拆分为5-10集可实现的小目标 + +### 五、台词创作规范 + +1. **精准戳点**:针对角色软肋设计台词(骂穷人没钱不够痛,骂他儿子会继续穷才激怒) +2. **贴合角色性格**:不同角色语言习惯须匹配人设 + - 自检法:遮挡角色名字仍能通过台词判断说话人 + - "绿茶"用"人家""哥哥",男主走后才露"獠牙" +3. **尽量少用潜台词**:短剧受众偏好直白表达,优先简单直接 +4. **接地气说人话**:禁用半文半白、生词冷词,所有意思用口语化表达 +5. **摒弃无效台词**:每句台词都有存在价值,不说车轱辘话 +6. **单句台词不超过20字**(竖屏短视频观众阅读速度限制) +7. **开篇台词**:聚焦主情绪、主矛盾,第一场戏不交代太多信息 + +### 六、CP感营造技巧 + +1. **性格互补制造反差萌**:心思缜密×热血愣头青、玲珑鬼精灵×天然呆、偏执狂×铁憨憨 +2. **强化互动紧绷感**:用激烈冲突替代平淡相处,CP互动须有戏剧张力 +3. **立体人设是CP感基础**:展现角色多面性(如会为小钱斤斤计较也会为陌生人捐巨款;能抡铁锤却在爱人面前拧不开瓶盖) +4. **禁忌**:不可为追流行强加无关人设标签 + +### 七、人物塑造速查 + +- **先立标签**:用1-2个关键词定义人物核心性格(恶婆婆、贪财妻子、高冷霸总) +- **行动须契合人设**:胆小柔弱遇危险退缩求助,桀骜拽姐正面反击 +- **设定记忆点**:专属口音、下意识动作、特殊怪癖、独门技能 +- **弧光关键**:初始状态→关键变故→性格转变→最终状态,所有转变须有事件支撑 + +### 八、高频情绪模板(可直接套用) + +**模板1:"打压-反击"爽感布局(逆袭/战神/赘婿类)** +配角嘲讽主角(压抑)→ 变本加厉(愤怒)→ 主角亮身份/实力(爽感)→ 配角狼狈道歉(解气) + +**模板2:"误会-解开"甜虐布局(甜宠/虐恋类)** +反派造谣(虐)→ 主角间冷战(委屈)→ 发现真相(震惊)→ 道歉+撒糖(甜) + +**模板3:"危机-救赎"共情布局(家庭伦理/寻亲类)** +主角遇难题(共情)→ 求助无门(绝望)→ 贵人出现(惊喜)→ 亲情升温(温暖) + ## 注意事项 -- 严格按照XML格式写出剧本内容,格式为剧本内容`。 +- 剧本正文**必须**包裹在 `...` 标签对中输出,缺少开标签或闭标签均视为格式错误;`name` 属性值必须与文件头首行标题一致(不含 `#`);XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出 - get_script_content(ids)只允许获取最后一集剧本内容 - **每次只编写当前任务集的剧本,不得将之前已完成的集重新输出或写入** - 只执行剧本编写,不越权执行其他阶段 @@ -46,8 +160,8 @@ ### 一、文件头 -```markdown - +```xml + # {作品名} EP{NN}:{集标题} # 目标时长:{单集时长}分钟 ≈ {台词字数}字台词 # 平台:{平台规格} | 风格:{风格标签} | 节拍:{节拍概要} @@ -55,6 +169,8 @@ --- ``` +> **关键**:`` 的 `name` 值必须与紧随其后的首行 `#` 标题文字完全一致(不含 `#` 号和前后空格)。 + ### 二、剧情梗概 ```markdown @@ -203,4 +319,4 @@ OS({人物名},{情绪}): - **自查清单**:不输出自查清单本身 - **任何元信息**:不输出字数统计、场景数量统计、创作说明等非剧本内容 -剧本输出只包含:文件头 → 剧情梗概→ 剧本正文(△描述 + 台词 + OS/V.S.) \ No newline at end of file +剧本输出的完整结构为:`` → 文件头 → 剧情梗概 → 剧本正文(△描述 + 台词 + OS/V.S.) → `` \ No newline at end of file diff --git a/data/skills/script_execution_skeleton.md b/data/skills/script_execution_skeleton.md index 11b8355..0a97785 100644 --- a/data/skills/script_execution_skeleton.md +++ b/data/skills/script_execution_skeleton.md @@ -20,7 +20,7 @@ - 全局删减决策表 - 付费卡点设计 3. **阐述思路**(200-300字):核心吸引力判断、三幕划分思路、分集策略方向 -4. 严格按照XML格式写出故事骨架,格式为故事骨架内容。 +4. 严格按照XML格式写出故事骨架,格式为故事骨架内容。XML 标签及其全部内容必须一次性完整输出,禁止拆分为多次 XML 输出。 5. 返回简短确认,如:"故事骨架已保存,请在右侧工作台查看。" ## 约束 @@ -31,6 +31,116 @@ - 付费策略按【项目配置】执行 - 章节必须与事件表一致,不允许出现不存在的章节 +## Skills + +### 一、核心结构逻辑 + +**大三角嵌套小三角:** +- 大三角:3个核心角色/势力构成全剧主要矛盾,贯穿始终不可轻易改动 +- 小三角:围绕主角的次要矛盾,解决一个再进入下一个,避免多线并行 +- 主流结构为**单线型**:情节围绕单条主线推进,矛盾集中、节奏连贯;短剧面向下沉市场,多线并行易被退稿 + +### 二、前10集黄金结构 + +| 集数 | 核心任务 | +|------|----------| +| 第1-2集 | 快速引入主角,直接抛出强烈冲突(契约绑定、意外变故),实现"一秒入坑" | +| 第3-4集 | 明确主角核心行动目标(复仇、追爱、逆袭),为后续埋伏笔 | +| 第5-8集 | 引入多方配角,从多角度给主角施压,强化矛盾冲突 | +| 第9-10集 | 设置"假付费点"(目标近在咫尺却落空)+ 正式卡点,推向小高潮 | + +- 微短篇:卡点集提前至第6-7集,第1集需承载常规短剧3-4集信息量 + +### 三、付费点(卡点)设置规范 + +根据【项目配置】总集数 N 按比例计算付费点位置(四舍五入取整): + +| 位置 | 比例 | 设计要求 | +|------|------|----------| +| ≈10%处(第⌈N×0.10⌉集) | 首次卡点 | 核心矛盾升级(秘密即将曝光、关系面临破裂) | +| ≈30%处(第⌈N×0.30⌉集) | 二次卡点 | 生死危机、隐藏秘密将揭露或遭反派陷害,给观众强烈情感冲击 | +| ≈50%处(第⌈N×0.50⌉集) | 中期卡点 | 阶段性目标达成时迎来重大反转 | +| ≈70%处(第⌈N×0.70⌉集) | 后期卡点 | 前期悬念和伏笔逐渐展开,引入重大翻转 | +| ≈90%处(第⌈N×0.90⌉集) | 收尾卡点 | 主角克服所有困难,揭露反派阴谋,达成圆满结局(短剧必保"爽剧"收尾) | + +> 示例:20集剧→卡点分布约为第2/6/10/14/18集;100集剧→约为第10/30/50/70/90集 + +**付费点5大标准:** +1. **选择关键瞬间**:聚焦对人物内心有强烈情绪冲击的情节 +2. **设置根本性改变**:需改变主角性格、价值观或行为方式 +3. **调动好奇心**:用暗示、伏笔、悬念引发期待 +4. **善用高燃场景**:设置在紧张激动的高潮部分,关键节点戛然而止 +5. **关注爱情拉扯**(感情流):围绕情感阶段转变设计(无感→好感→醒悟→确认心意→表白) + +**付费点核心特征:** 场面宏大、事态紧急、围观群众多(大型宴会、认亲仪式、新闻发布会、婚礼现场等) + +**假付费点:** 可多次设置,让观众误以为目标即将达成实则受阻,持续牵引情绪 + +**4类核心付费点写法:** +- **身份差**(通用型):隐藏身份暴露、身份错认澄清、身份升级展现 +- **感情错位**(女频):认错信物、认错人、欺骗/蒙蔽解开 +- **人物命运巨变**:主角从被打压欺辱→因机缘改变命运→强势反击 +- **环境剧变**(末世类):世界突发灾难,只有主角能掌控局面 + +### 四、热门类型节奏框架 + +> 以下比例基于总集数 N,实际集数四舍五入取整。 + +**甜宠类:** +契约绑定(第1集)→ 误会拉扯升温(2%~9%)→ 秘密曝光(≈10%付费点)→ 情感破冰(11%~29%)→ 危机爆发(≈30%付费点)→ 撒糖+打脸反派(31%~59%)→ 新危机(≈60%)→ 情感确认(61%~80%)→ 圆满结局(81%~100%) + +**虐恋类(追妻火葬场):** +前期误会伤害(1%~20%)→ 男主悔悟(21%~40%)→ 追妻受阻(41%~70%)→ 真诚悔改+和解(71%~100%) + +**萌宝类:** +带娃回归逆袭(1%~20%)→ 男主发现孩子+解开心结(21%~50%)→ 联手反击反派(51%~80%)→ 家庭团圆(81%~100%) + +**战神类:** +隐藏身份受辱(1%~30%)→ 身份曝光打脸反派(31%~60%)→ 解决核心危机(61%~90%)→ 登顶巅峰(91%~100%) + +**重生类:** +前世被害(第1集)→ 重生改写命运(2%~30%)→ 利用信息差逆袭(31%~70%)→ 复仇成功+圆满结局(71%~100%) + +### 五、全局情绪布局(按付费点比例划分阶段) + +以复仇类为例(可迁移其他题材),按总集数 N 的比例划分: + +| 阶段 | 集数范围 | 核心情绪 | 作用 | +|------|----------|----------|------| +| 铺垫 | 1%~10% | 压抑+愤怒 | 拉仇恨,让观众心疼主角,期待反击 | +| 试探 | 11%~30% | 紧张+小爽 | 缓解压抑,给观众小甜头,留住注意力 | +| 转折 | 31%~50% | 震惊+焦虑 | 制造大波澜,提升期待感 | +| 爆发 | 51%~70% | 爽感+解气 | 情绪高潮,释放前面积压的压抑 | +| 收尾 | 71%~100% | 温暖+圆满 | 收尾情绪,留下正面印象 | + +**各类型情绪基调占比:** +- 甜宠类:甜60% + 微虐30% + 惊喜10% +- 复仇类:压抑40% + 爽感50% + 解气10% +- 重生逆袭类:爽感50% + 期待30% + 温暖20% +- 家庭伦理类:共情40% + 委屈30% + 和解30% + +### 六、信息差设计 + +骨架阶段需在分集中标注信息差类型,操控观众情绪: +- **主角知道+配角不知道+观众知道** → 观众拥有"先知"爽感,期待配角被"打脸" +- **主角不知道+配角知道+观众知道** → 观众为身处险境的主角焦急,代入感极强 +- **主角不知道+配角不知道+观众知道** → 观众既想指导主角又好奇反派结局,期待感拉满 + +### 七、集末钩子设计原则 + +- 每集结尾必须留"钩子",勾住下一集情绪 +- 钩子需紧扣"主角的下一步行动""反派的反击""第三方的态度" +- 确保观众有"想立刻知道后续"的冲动 +- 钩子类型:智识钩子/悬念钩子/情感钩子/世界观钩子 + +### 八、第2、3个付费点素材类型 + +选影响主线的大事件: +- **关系类**:兄弟/父子反目、旧情复燃、断绝关系、宣布婚事、霸气护妻 +- **冲突类**:好友陷害、产业被占、奸计得逞/揭发、武力/情感/欲望冲突 +- **真相/变故类**:借腹生子、亲子鉴定、假传死讯、错手杀人、被控入狱 +- **行动类**:请君入瓮、调虎离山、忍辱负重、畏罪潜逃、一夜成名 + ## 注意事项 - 执行前先调用 `get_planData` 确认工作区状态;已有内容在其基础上修改,除非指令要求重写 diff --git a/data/update.json b/data/update.json deleted file mode 100644 index 7c547a6..0000000 --- a/data/update.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"1.0.11"} \ No newline at end of file diff --git a/data/version.txt b/data/version.txt index 8684498..1cc5f65 100644 --- a/data/version.txt +++ b/data/version.txt @@ -1 +1 @@ -1.0.11 \ No newline at end of file +1.1.0 \ No newline at end of file diff --git a/data/web/index.html b/data/web/index.html index 3eabe2e..aeb382d 100644 --- a/data/web/index.html +++ b/data/web/index.html @@ -5,27 +5,27 @@ Toonflow - - + `),tNs=/enable|requires|diagnostic/,Cvn=new RegExp("[_\\p{XID_Start}]\\p{XID_Continue}*","u"),dF="variable.predefined",nNs={tokenPostfix:".wgsl",defaultToken:"invalid",unicode:!0,atoms:$Fs,keywords:XFs,reserved:GFs,predeclared_enums:YFs,predeclared_types:ZFs,predeclared_type_generators:qFs,predeclared_type_aliases:KFs,predeclared_intrinsics:JFs,operators:eNs,symbols:/[!%&*+\-\.\/:;<=>^|_~,]+/,tokenizer:{root:[[tNs,"keyword","@directive"],[Cvn,{cases:{"@atoms":dF,"@keywords":"keyword","@reserved":"invalid","@predeclared_enums":dF,"@predeclared_types":dF,"@predeclared_type_generators":dF,"@predeclared_type_aliases":dF,"@predeclared_intrinsics":dF,"@default":"identifier"}}],{include:"@commentOrSpace"},{include:"@numbers"},[/[{}()\[\]]/,"@brackets"],["@","annotation","@attribute"],[/@symbols/,{cases:{"@operators":"operator","@default":"delimiter"}}],[/./,"invalid"]],commentOrSpace:[[/\s+/,"white"],[/\/\*/,"comment","@blockComment"],[/\/\/.*$/,"comment"]],blockComment:[[/[^\/*]+/,"comment"],[/\/\*/,"comment","@push"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],attribute:[{include:"@commentOrSpace"},[/\w+/,"annotation","@pop"]],directive:[{include:"@commentOrSpace"},[/[()]/,"@brackets"],[/,/,"delimiter"],[Cvn,"meta.content"],[/;/,"delimiter","@pop"]],numbers:[[/0[fh]/,"number.float"],[/[1-9][0-9]*[fh]/,"number.float"],[/[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[fh]?/,"number.float"],[/[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?[fh]?/,"number.float"],[/[0-9]+[eE][+-]?[0-9]+[fh]?/,"number.float"],[/0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+(?:[pP][+-]?[0-9]+[fh]?)?/,"number.hex"],[/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*(?:[pP][+-]?[0-9]+[fh]?)?/,"number.hex"],[/0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?/,"number.hex"],[/0[xX][0-9a-fA-F]+[iu]?/,"number.hex"],[/[1-9][0-9]*[iu]?/,"number"],[/0[iu]?/,"number"]]}},iNs=Object.freeze(Object.defineProperty({__proto__:null,conf:HFs,language:nNs},Symbol.toStringTag,{value:"Module"})),rNs={comments:{blockComment:["\x3C!--","-->"]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],onEnterRules:[{beforeText:new RegExp("<([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$","i"),afterText:/^<\/([_:\w][_:\w-.\d]*)\s*>$/i,action:{indentAction:Tt.IndentAction.IndentOutdent}},{beforeText:new RegExp("<(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),action:{indentAction:Tt.IndentAction.Indent}}]},oNs={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/\x3C!--/,{token:"comment",next:"@comment"}]],comment:[[/[^<\-]+/,"comment.content"],[/-->/,{token:"comment",next:"@pop"}],[/\x3C!--/,"comment.content.invalid"],[/[<\-]/,"comment.content"]]}},sNs=Object.freeze(Object.defineProperty({__proto__:null,conf:rNs,language:oNs},Symbol.toStringTag,{value:"Module"})),aNs={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{offSide:!0},onEnterRules:[{beforeText:/:\s*$/,action:{indentAction:Tt.IndentAction.Indent}}]},lNs={tokenPostfix:".yaml",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.square",open:"[",close:"]"}],keywords:["true","True","TRUE","false","False","FALSE","null","Null","Null","~"],numberInteger:/(?:0|[+-]?[0-9]+)/,numberFloat:/(?:0|[+-]?[0-9]+)(?:\.[0-9]+)?(?:e[-+][1-9][0-9]*)?/,numberOctal:/0o[0-7]+/,numberHex:/0x[0-9a-fA-F]+/,numberInfinity:/[+-]?\.(?:inf|Inf|INF)/,numberNaN:/\.(?:nan|Nan|NAN)/,numberDate:/\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?/,escapes:/\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,tokenizer:{root:[{include:"@whitespace"},{include:"@comment"},[/%[^ ]+.*$/,"meta.directive"],[/---/,"operators.directivesEnd"],[/\.{3}/,"operators.documentEnd"],[/[-?:](?= )/,"operators"],{include:"@anchor"},{include:"@tagHandle"},{include:"@flowCollections"},{include:"@blockStyle"},[/@numberInteger(?![ \t]*\S+)/,"number"],[/@numberFloat(?![ \t]*\S+)/,"number.float"],[/@numberOctal(?![ \t]*\S+)/,"number.octal"],[/@numberHex(?![ \t]*\S+)/,"number.hex"],[/@numberInfinity(?![ \t]*\S+)/,"number.infinity"],[/@numberNaN(?![ \t]*\S+)/,"number.nan"],[/@numberDate(?![ \t]*\S+)/,"number.date"],[/(".*?"|'.*?'|[^#'"]*?)([ \t]*)(:)( |$)/,["type","white","operators","white"]],{include:"@flowScalars"},[/.+?(?=(\s+#|$))/,{cases:{"@keywords":"keyword","@default":"string"}}]],object:[{include:"@whitespace"},{include:"@comment"},[/\}/,"@brackets","@pop"],[/,/,"delimiter.comma"],[/:(?= )/,"operators"],[/(?:".*?"|'.*?'|[^,\{\[]+?)(?=: )/,"type"],{include:"@flowCollections"},{include:"@flowScalars"},{include:"@tagHandle"},{include:"@anchor"},{include:"@flowNumber"},[/[^\},]+/,{cases:{"@keywords":"keyword","@default":"string"}}]],array:[{include:"@whitespace"},{include:"@comment"},[/\]/,"@brackets","@pop"],[/,/,"delimiter.comma"],{include:"@flowCollections"},{include:"@flowScalars"},{include:"@tagHandle"},{include:"@anchor"},{include:"@flowNumber"},[/[^\],]+/,{cases:{"@keywords":"keyword","@default":"string"}}]],multiString:[[/^( +).+$/,"string","@multiStringContinued.$1"]],multiStringContinued:[[/^( *).+$/,{cases:{"$1==$S2":"string","@default":{token:"@rematch",next:"@popall"}}}]],whitespace:[[/[ \t\r\n]+/,"white"]],comment:[[/#.*$/,"comment"]],flowCollections:[[/\[/,"@brackets","@array"],[/\{/,"@brackets","@object"]],flowScalars:[[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'[^']*'/,"string"],[/"/,"string","@doubleQuotedString"]],doubleQuotedString:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],blockStyle:[[/[>|][0-9]*[+-]?$/,"operators","@multiString"]],flowNumber:[[/@numberInteger(?=[ \t]*[,\]\}])/,"number"],[/@numberFloat(?=[ \t]*[,\]\}])/,"number.float"],[/@numberOctal(?=[ \t]*[,\]\}])/,"number.octal"],[/@numberHex(?=[ \t]*[,\]\}])/,"number.hex"],[/@numberInfinity(?=[ \t]*[,\]\}])/,"number.infinity"],[/@numberNaN(?=[ \t]*[,\]\}])/,"number.nan"],[/@numberDate(?=[ \t]*[,\]\}])/,"number.date"]],tagHandle:[[/\![^ ]*/,"tag"]],anchor:[[/[&*][^ ]+/,"namespace"]]}},cNs=Object.freeze(Object.defineProperty({__proto__:null,conf:aNs,language:lNs},Symbol.toStringTag,{value:"Module"})); +
diff --git a/docs/README.en.md b/docs/README.en.md index 02ee01d..a9be70f 100644 --- a/docs/README.en.md +++ b/docs/README.en.md @@ -8,18 +8,17 @@  |  - Atomgit - Atomgit + Atomgit

- 简体中文 | + 简体中文 | 繁體中文 | English | ไทย | Tiếng Việt | - 日本語 | + 日本語 | Русский

@@ -33,9 +32,9 @@ AI Short Drama Factory
- With a tap, novels instantly become episodes! + Turn your novel into episodes with just a few clicks!
- AI scripts × AI visuals × Turbo generation 🔥 + AI Scripts × AI Visuals × Ultra-fast Generation 🔥

@@ -50,49 +49,57 @@

- > 🚀 **One-stop short drama production**: From text to characters, from storyboard to video, 0 barrier full-process AI, 10x+ creation efficiency! +> 🚀 **All-in-One Short Drama Studio**: From text to characters, from storyboard to final video. +> Fully AI-powered workflow with zero barrier to entry — boosting your creative efficiency by 10x or more! --- -# 🌐 Multilingual Support +# 🌐 Multi-Language Support Toonflow supports the following interface languages: -| Language | Native Name | -|----------|-------------| -| Chinese (Simplified) | 简体中文 | -| Chinese (Traditional) | 繁體中文 | +| Language | Language Name | +|------|----------| +| 简体中文 | Chinese (Simplified) | +| 繁體中文 | Chinese (Traditional) | | English | English | -| Thai | ไทย | -| Vietnamese | Tiếng Việt | -| Japanese | 日本語 | -| Russian | Русский | +| ไทย | Thai | +| Tiếng Việt | Vietnamese | +| 日本語 | Japanese | +| Русский | Russian | + +> 💡 More languages are on the way. Translation contributions are highly welcome! --- -# �🌟 Main Features +# 🌟 Main Features -Toonflow is an AI short drama comic tool that leverages AI technology to automatically convert novels into scripts, and uses AI-generated images and videos for efficient short drama creation. With Toonflow, you can easily complete the entire process from text to images, making short drama production more intelligent and convenient. +Toonflow is an AI-powered tool for creating short dramas, short films, and comics. It can automatically transform novels into scripts, then combine AI-generated characters, images, and videos to produce high-quality content efficiently. + +With Toonflow, you can complete the entire workflow from text to final video with ease — making short-form video and drama production significantly smarter and more convenient. - ✅ **Character Generation** - Automatically analyzes the original novel text, intelligently identifies and generates character settings, including appearance, personality, identity, etc., providing a reliable foundation for subsequent script and visual creation. + Automatically analyzes the original novel text, intelligently identifies key elements, and generates detailed character profiles including appearance, personality, background, and relationships — laying a strong foundation for scriptwriting and visual production. + - ✅ **Script Generation** - Based on selected events and chapters, the system automatically generates structured scripts, covering dialogue, scene descriptions, and plot direction, enabling efficient transformation from literary texts to film/TV scripts. -- ✅ **Storyboard Production** - Based on the script content, intelligently generates storyboard prompts and visual design, detailing foreground/midground/background, character dynamics, prop settings, and scene layout; automatically turns scripts into storyboards, providing a complete route blueprint for video production. -- ✅ **Video Composition** - Integrates AI image and video technologies to generate video clips using AI. Includes online editing and supports personalized output adjustments, making film & TV production collaborative and efficient. + Based on selected events and chapters, the system automatically creates well-structured scripts with natural dialogue, scene descriptions, and plot development, enabling efficient adaptation from literature to cinematic format. + +- ✅ **Storyboard Creation** + From the generated script, Toonflow intelligently creates storyboard prompts and visual layouts. It details foreground, midground, and background elements, character movements, props, and scene composition — providing a complete and ready-to-use blueprint for video production. + +- ✅ **Video Synthesis** + Integrates advanced AI image and video generation technologies to produce high-quality video clips. The built-in online editor allows flexible personalization and fine-tuning, making the entire creative process smooth, fast, and highly efficient. --- -# 📦 Application Scenarios +# 📦 Use Cases -- Short video content creation -- Novel-to-film/TV experiments -- AI literature adaptation tools +- Short video content creation (Shorts, Reels, TikTok) +- Novel-to-film / drama adaptation experiments +- AI-powered literary adaptation tool - Script development and rapid prototyping -- Video material generation +- Video asset and footage generation --- @@ -100,15 +107,15 @@ Toonflow is an AI short drama comic tool that leverages AI technology to automat ## 📺 Video Tutorial -https://www.bilibili.com/video/BV1na6wB6Ea2 -[![Toonflow 8-Minute Quick Start AI Video](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) +[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2) +[![Toonflow 8-Minute AI Video Quick Start](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) -**Toonflow 8-Minute Quick Start AI Video** -👉 [Click to watch](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) +**Toonflow: 8-Minute AI Video Quick Start** +👉 [Click to Watch](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) -📱 Scan with WeChat on your phone to watch +📱 Scan the QR code to watch on mobile -Scan WeChat to Watch +Scan QR code to watch on mobile --- @@ -116,34 +123,34 @@ https://www.bilibili.com/video/BV1na6wB6Ea2 ## Prerequisites -Before installing and using this software, please prepare the following: +Before installing and using Toonflow, please prepare the following: -- ✅ Large language model AI service API address -- ✅ Sora or Doubao video service API address -- ✅ Nano Banana Pro image generation model service API +- ✅ API endpoint for Large Language Model (LLM) +- ✅ API endpoint for video generation services (Sora or Doubao) +- ✅ API endpoint for image generation model (Nano Banana Pro) ## Local Installation -### 1. Download & Install +### 1. Download and Install -| Operating System | GitHub | Atomgit | Quark Cloud Download | Description | -| :--------------: | :------------------------------------------------------ | :---------------------------------------------------- | :------------------------------------------------------ | :-------------------- | -| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Cloud](https://pan.quark.cn/s/94ef07509df0) | Official release package | -| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Cloud](https://pan.quark.cn/s/94ef07509df0) | Official release package | -| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Cloud](https://pan.quark.cn/s/94ef07509df0) | Official release package | +| OS | GitHub | Atomgit | Quark Drive Download | Description | +| :------: | :----------------------------------------------------------- | :------------------------------------------------------------ | :---------------------------------------------- | :------------- | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Official Installer | +| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Official Installer | +| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Official Installer | > [!CAUTION] -> On MacOS, please go to Settings - Privacy & Security to configure security settings, otherwise, you may not be able to open the app due to certificate issues. +> **MacOS Users:** Please go to `System Settings > Privacy & Security` to allow the application to run; otherwise, it may fail to open due to certificate issues. > -> See Zhihu documentation: [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) +> Reference (Zhihu): [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) -> Due to Gitee OS environment and Release file upload size limits, Gitee Release download is currently not available. +> Due to Gitee OS environment constraints and Release file size upload limits, Gitee Release download links are currently unavailable. -### 2. Start Service +### 2. Start the Service -After installation, launch the program to start using this service. +After installation, simply launch the program to start using the service. -> ⚠️ **First-time Login** +> ⚠️ **Default Login** > Username: `admin` > Password: `admin123` @@ -151,45 +158,45 @@ After installation, launch the program to start using this service. ### Prerequisites -- [Docker](https://docs.docker.com/get-docker/) installed (version 20.10+) +- [Docker](https://docs.docker.com/get-docker/) installed (Version 20.10+) ### Method 1: Online Deployment -To be developed; please use local build for now. +To be updated. Please use local build for now. ### Method 2: Local Build -Build directly from local source code, suitable for developers or users who have cloned the repo; requires Git installed locally: +Build directly using the local source code. This is suitable for developers or users who have cloned the repository. You will need `git` installed locally: ```shell -# Clone the project (skip if already cloned) +# Clone the repository first (skip if already cloned) git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app -# Build and start locally with docker-compose +# Build and start locally using docker-compose yarn docker:local # Or build manually docker build -t toonflow . -docker run -d -p :10588 -v :/app/data toonflow +docker run -d -p :10588 -v :/app/data toonflow -# After this, the site can be accessed at /web/index.html on the mapped port -# e.g. http://localhost:10588/web/index.html +# You can now access the page at the corresponding port at /web/index.html +# Example: http://localhost:10588/web/index.html ``` ### Service Port Description -| Port | Purpose | Deployment Mapping | -| -------- | ------------ | -------------------- | -| `10588` | App Interface | `10588:10588` | +| Port | Purpose | Deployment Mapping | +| ------- | -------- | ------------- | +| `10588` | Software UI | `10588:10588` | -**Environment variable descriptions:** +**Environment Variables:** -| Variable | Description | -| ------------- | ------------------------------------------- | -| `NODE_ENV` | Environment; `prod` for production | -| `PORT` | Service listening port (default 10588) | -| `OSSURL` | File storage access address for static files | +| Variable | Description | +| ---------- | ----------------------------------------- | +| `NODE_ENV` | Operating environment, `prod` for production | +| `PORT` | Service listening port (Default: 10588) | +| `OSSURL` | File storage access URL, used for static resources | --- @@ -197,9 +204,9 @@ docker run -d -p :10588 -v :/app/data toonflow ### 1. Server Requirements -- **OS:** Ubuntu 20.04+ / CentOS 7+ -- **Node.js:** 24.x (recommended, minimum 23.11.1+) -- **RAM:** 2GB+ +- **OS**: Ubuntu 20.04+ / CentOS 7+ +- **Node.js**: 24.x (Recommended, Minimum 23.11.1+) +- **Memory**: 2GB+ ### 2. Server Deployment @@ -226,7 +233,7 @@ yarn install yarn build ``` -**Clone from Gitee (Mainland China recommended):** +**Clone from Gitee (Recommended for users in China):** ```bash cd /opt @@ -254,17 +261,17 @@ Create a `pm2.json` file: } ``` -**Environment variable descriptions:** +**Environment Variables:** -| Variable | Description | -| ------------- | ------------------------------------------- | -| `NODE_ENV` | Environment; `prod` for production | -| `PORT` | Service listening port | -| `OSSURL` | File storage access address for static files | +| Variable | Description | +| ---------- | ----------------------------------------------------- | +| `NODE_ENV` | Operating environment (`prod` = Production) | +| `PORT` | Service listening port (default: 10588) | +| `OSSURL` | Object Storage URL for storing and serving static files | --- -#### 4. Start Service +#### 4. Start the Service ```bash pm2 start pm2.json @@ -275,147 +282,150 @@ pm2 save #### 5. Common Commands ```bash -pm2 list # View process list +pm2 list # View processes pm2 logs toonflow-app # View logs -pm2 restart all # Restart service -pm2 monit # Monitoring panel +pm2 restart all # Restart services +pm2 monit # Monitoring dashboard ``` -> ⚠️ **First-time Login** +> ⚠️ **Default Login** > Username: `admin` > Password: `admin123` -#### 6. Deploying the Frontend Website +#### 6. Deploy Frontend -For standalone frontend deployment or customization, refer to the frontend repository: +If you need to deploy or customize the frontend interface separately, please refer to the frontend repository: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -> 💡 **Note:** This repo already contains a compiled frontend by default. Regular users do NOT need to separately deploy the frontend. The frontend repo is for developers requiring secondary development. +> 💡 **Note**: This repository already includes the compiled frontend resources. +> Regular users do not need to deploy the frontend separately. The Toonflow-web repository is intended only for developers who want to make custom modifications or contribute to the frontend. --- -# 🔧 Developer Guide +# 🔧 Development Workflow Guide > [!CAUTION] > 🚧 **PR Submission Guidelines** 🚧 > -> ⛔ `master` branch does NOT accept PRs | ✅ Please submit PRs to the `develop` branch -> -> Developers are invited to co-develop Toonflow. To join, contact owner ACT in the group chat. +> ⛔ **No PRs accepted on the `master` branch** +> ✅ **Please submit all Pull Requests to the `develop` branch** + +We welcome all developers who want to contribute to Toonflow. +If you're interested in joining, please contact the project maintainer (ACT) in our community group. ## 🛠️ Tech Stack -| Category | Technology | -| ------------ | --------------------------------------------------------------------------------------- | -| Runtime | Node.js 23.11.1+ | -| Language | TypeScript 5.x | -| Backend | Express 5 | -| Database | SQLite (better-sqlite3 / knex) | -| AI Integration | Vercel AI SDK (OpenAI / Anthropic / Google / DeepSeek / Zhipu / MiniMax / Qwen / xAI)| -| Local Inference | @huggingface/transformers (ONNX) | -| Real-Time | Socket.IO | -| Desktop | Electron 40 | -| Image Proc. | Sharp | -| Container | Docker | +| Category | Technology | +| ---------- | ----------------------------------------------------------------------------------------- | +| Runtime | Node.js 23.11.1+ | +| Language | TypeScript 5.x | +| Backend | Express 5 | +| Database | SQLite (better-sqlite3 / knex) | +| AI Integ. | Vercel AI SDK (OpenAI / Anthropic / Google / DeepSeek / Zhipu / MiniMax / Qwen / xAI) | +| Local Inf. | @huggingface/transformers (ONNX) | +| Real-time | Socket.IO | +| Desktop UI | Electron 40 | +| Image Proc.| Sharp | +| Container | Docker | -## Development Environment Preparation +## Development Environment Prep -- **Node.js:** version 23.11.1 or above required -- **Yarn:** recommended as the package manager +- **Node.js**: Version 23.11.1 or higher required +- **Yarn**: Recommended package manager ## Quick Start -1. **Clone the project** +1. **Clone the Project** - **Clone from GitHub:** + **From GitHub:** ```bash git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` - **Clone from Gitee (Mainland China recommended):** + **From Gitee (Recommended for China):** ```bash git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` -2. **Install dependencies** +2. **Install Dependencies** - In the project root directory, install dependencies: + Run the following command in the project root directory: ```bash yarn install ``` -3. **Start development environment** +3. **Start the Development Environment** - This project includes both **backend API service** and **frontend interface**. Start as needed: + This project consists of two parts: the **Backend API Service** and the **Frontend Pages**. Choose your startup method based on your needs: - - **Option 1: Start backend service only** + - **Method 1: Start Backend Service Only** ```bash yarn dev ``` - > ⚠️ This command starts only the backend API (port 10588), **without the web interface**. Accessing `http://localhost:10588` allows API calls only; the full web UI is unavailable. To use the frontend, start the frontend project separately or use GUI mode below. + > ⚠️ This command only starts the backend API service (Port 10588) and **does not include the frontend pages**. Visiting `http://localhost:10588` directly will only allow API calls without a UI. To use the frontend, start the frontend project separately or use the GUI mode below. - - **Option 2: Start Electron desktop client** + - **Method 2: Start Electron Desktop Client** ```bash yarn dev:gui ``` - > This command starts both backend and Electron window, with built-in web UI. Out-of-the-box, no extra config needed. Recommended for a full experience. + > This command launches both the backend service and the Electron desktop window simultaneously. It comes with built-in frontend pages ready out-of-the-box, requiring no extra configuration. Ideal for developers who want to experience the full feature set. - - **Option 3: Production mode** + - **Method 3: Start in Production Mode** ```bash yarn start ``` - > Runs compiled service in production mode (requires `yarn build` first). + > Run the compiled service directly in production mode (requires running `yarn build` first). -4. **Build the project** +4. **Project Build & Packaging** - - Compile TypeScript files: + - Compile and generate TypeScript files: ```bash yarn build ``` - - Build executable for Windows: + - Package as a Windows executable: ```bash yarn dist:win ``` - - Build executable for Mac: + - Package as a Mac executable: ```bash yarn dist:mac ``` - - Build executable for Linux: + - Package as a Linux executable: ```bash yarn dist:linux ``` -5. **Code quality check** +5. **Code Quality Checks (Linting)** - - Perform lint check: + - Run global syntax and styling checks: ```bash yarn lint ``` -6. **AI Debug panel (Optional)** +6. **AI Debug Panel (Optional)** - Start the Vercel AI SDK visual debugging tool for easier AI integration debugging: + Launch the AI SDK visual debugging tool to easily trace AI calls: ```bash yarn debug:ai @@ -423,129 +433,131 @@ For standalone frontend deployment or customization, refer to the frontend repos ## Frontend Development -To modify the frontend UI, develop in the frontend repository: +If you need to modify or customize the frontend interface, please go to the frontend repository: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -After frontend build, copy the `dist` contents to this project's `data/web` to integrate. +After building the frontend, copy the entire `dist` folder into the `data/web` directory of this project to integrate it. ## Project Structure ``` -📂 build/ # Compiled output +📂 build/ # Build artifacts 📂 data/ # Runtime data -│ ├─ 📂 models/ # Local inference models (ONNX) -│ ├─ 📂 oss/ # Object storage (assets/characters/scenes) -│ ├─ 📂 serve/ # Production entry -│ ├─ 📂 skills/ # Agent skill prompts -│ └─ 📂 web/ # Built-in frontend assets -📂 ./ # Documentation assets -📂 env/ # Environment configs -📂 scripts/ # Build and helper scripts +│ ├─ 📂 models/ # Local inference models (ONNX) +│ ├─ 📂 oss/ # Object storage (images, characters, scenes) +│ ├─ 📂 serve/ # Production environment entry point +│ ├─ 📂 skills/ # Agent skill prompts +│ └─ 📂 web/ # Built frontend assets (embedded) +📂 docs/ # Documentation and resources +📂 env/ # Environment configurations +📂 scripts/ # Build and utility scripts 📂 src/ -├─ 📂 agents/ # AI Agent modules -│ ├─ 📂 productionAgent/ # Production Agent -│ └─ 📂 scriptAgent/ # Script Agent -├─ 📂 lib/ # Common libraries (db, responses) -├─ 📂 middleware/ # Middleware -├─ 📂 routes/ # API routes -│ ├─ 📂 agents/ # Agent memory management -│ ├─ 📂 artStyle/ # Art style management -│ ├─ 📂 assets/ # Asset management -│ ├─ 📂 assetsGenerate/ # Asset generation -│ ├─ 📂 cornerScape/ # Storyboard management -│ ├─ 📂 general/ # General APIs -│ ├─ 📂 login/ # Auth -│ ├─ 📂 migrate/ # Data migration -│ ├─ 📂 modelSelect/ # Model selection -│ ├─ 📂 novel/ # Novel management -│ ├─ 📂 other/ # Other features -│ ├─ 📂 production/ # Production management -│ ├─ 📂 project/ # Project management -│ ├─ 📂 script/ # Script generation -│ ├─ 📂 scriptAgent/ # Script Agent APIs -│ ├─ 📂 setting/ # System settings -│ ├─ 📂 task/ # Task management -│ └─ 📂 test/ # Test APIs -├─ 📂 socket/ # WebSocket comms -├─ 📂 types/ # TypeScript types -├─ 📂 utils/ # Utility functions -├─ 📄 app.ts # App entry point -├─ 📄 core.ts # Core initialization -├─ 📄 env.ts # Env vars -├─ 📄 err.ts # Error handling -├─ 📄 logger.ts # Logging module -├─ 📄 router.ts # Route registration -└─ 📄 utils.ts # General tools -📄 Dockerfile # Docker build config -📄 electron-builder.yml # Electron packaging config -📄 skillList.json # Skills list -📄 LICENSE # (Apache-2.0) License -📄 NOTICES.txt # Third-party dependencies -📄 package.json # Project config -📄 tsconfig.json # TypeScript config +├─ 📂 agents/ # AI Agent modules +│ ├─ 📂 productionAgent/ # Production Agent +│ └─ 📂 scriptAgent/ # Script Agent +├─ 📂 lib/ # Shared libraries (DB initialization, response formatting) +├─ 📂 middleware/ # Express middlewares +├─ 📂 routes/ # Routing modules +│ ├─ 📂 agents/ # Agent memory management +│ ├─ 📂 artStyle/ # Art style management +│ ├─ 📂 assets/ # Asset management +│ ├─ 📂 assetsGenerate/ # Asset generation +│ ├─ 📂 cornerScape/ # Storyboard management +│ ├─ 📂 general/ # General APIs +│ ├─ 📂 login/ # Authentication +│ ├─ 📂 migrate/ # Data migration +│ ├─ 📂 modelSelect/ # Model selection +│ ├─ 📂 novel/ # Novel management +│ ├─ 📂 other/ # Other functionalities +│ ├─ 📂 production/ # Production and editing management +│ ├─ 📂 project/ # Project management +│ ├─ 📂 script/ # Script generation +│ ├─ 📂 scriptAgent/ # Script Agent interface +│ ├─ 📂 setting/ # System settings +│ ├─ 📂 task/ # Task management +│ └─ 📂 test/ # Test APIs +├─ 📂 socket/ # Real-time communication via WebSocket +├─ 📂 types/ # TypeScript type declarations +├─ 📂 utils/ # Utility functions +├─ 📄 app.ts # Application entry point +├─ 📄 core.ts # Core system initialization +├─ 📄 env.ts # Environment variables handling +├─ 📄 err.ts # Error handling +├─ 📄 logger.ts # Logging module +├─ 📄 router.ts # Route registration +└─ 📄 utils.ts # General utilities +📄 Dockerfile # Docker build file +📄 electron-builder.yml # Electron packaging configuration +📄 skillList.json # Skill list +📄 LICENSE # License (Apache-2.0) +📄 NOTICES.txt # Third-party dependency notices +📄 package.json # Project configuration +📄 tsconfig.json # TypeScript configuration ``` --- # 🔗 Related Repositories -| Repository | Description | GitHub | Gitee | -| ---------------- | ---------------------------------- | ------------------------------------------------- | ------------------------------------------------- | -| **Toonflow-app** | Full client (this repo, for users) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app)| [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | -| **Toonflow-web** | Frontend source (for FE devs) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web)| [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | +| Repository | Description | GitHub | Gitee | +|------------------|-----------------------------------------------------------------------------|----------------------------------------------------|--------------------------------------------------| +| **Toonflow-app** | Full client (This repository — recommended for most users) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | Frontend source code (For frontend developers) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | -> 💡 **Tip:** If you just want to use Toonflow, download the client from this repo directly. The frontend repo is for developers needing secondary dev or UI customization. +> 💡 **Tip**: If you just want to use Toonflow, downloading the client from this repository is sufficient. The Toonflow-web repository is intended only for developers who need to customize the UI or perform secondary development. --- -# 👨‍👩‍👧‍👦 WeChat Groups +# 👨‍👩‍👧‍👦 Discord Community -Group Assistant: +Click the icon below to join our Discord: -Toonflow QR +[![Join our Discord](https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/67d00cf7266d2c75571aebde_Example.svg)](https://discord.gg/HEjKmpNpAZ) + +Or click the direct link: [https://discord.gg/HEjKmpNpAZ](https://discord.gg/HEjKmpNpAZ) --- # 💌 Contact Us -📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow inquiry) +📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow%20Inquiry) --- # 📜 License -Toonflow is open source under Apache-2.0 with a supplementary commercial agreement. +Toonflow is open-sourced under the Apache-2.0 License with an additional supplementary commercial agreement. License details: https://www.apache.org/licenses/LICENSE-2.0 -## Supplementary Agreement +## Supplementary Commercial Agreement -- If you distribute this software as a product to **2 or more independent third parties**, you must obtain **written commercial authorization** from HBAI-Ltd. -- **≤ 5 legal entities** operating jointly for internal use without providing services externally are considered **internal use and require no authorization**. -- You may not remove or modify any trademarks, logos, or copyright notices in Toonflow. +- If this software is distributed as a product to **2 or more independent third parties**, a **written commercial license** from HBAI-Ltd is required. +- Joint operation and internal use by **≤ 5 legal entities** (without providing services to external users) is considered internal use and **does not require a license**. +- It is strictly prohibited to remove or modify any logos or copyright information within Toonflow. -## Always Free — No Authorization Required +## Forever Free Usage Scenarios -- ✅ Using Toonflow to produce content and earn platform revenue shares +- ✅ Using Toonflow to create content and earning revenue share from video platforms - ✅ Secondary development for internal team use -- ✅ ≤ 5 legal entities operating jointly, internally only +- ✅ Joint/internal use by up to 5 legal entities - ✅ Personal learning, research, and non-commercial purposes -## Licensing Pricing +## Commercial License Pricing -| Stage | Annual Revenue | Annual Fee | -|------|---------|------| -| 🌱 Nurture | < $10k | **Free** | -| 🚀 Startup | $10k–$50k | ¥5,000/year | -| 📈 Growth | $50k–$150k | ¥20,000/year | -| 🏢 Scale | $150k–$500k | ¥80,000/year | -| 🌐 Enterprise | > $500k | Negotiable | +| Phase | Annual Revenue | Annual Fee | +|----------------|-------------------------|---------------------| +| 🌱 Incubation | < $15,000 | **Free** | +| 🚀 Startup | $15,000 – $75,000 | $750 / year | +| 📈 Growth | $75,000 – $200,000 | $2,900 / year | +| 🏢 Scale | $200,000 – $750,000 | $11,500 / year | +| 🌐 Enterprise | > $750,000 | Negotiable | -> **Non-Retroactivity Clause**: Users who used Toonflow under AGPL-3.0 prior to the v1.0.8 release are not affected by this change. Their existing usage continues under AGPL-3.0. +> **Non-Retroactivity Clause**: Users who were using Toonflow under the AGPL-3.0 license before version v1.0.8 will continue to be governed by AGPL-3.0 and are not affected by this agreement change. -See the full [LICENSE](../LICENSE) file for details. +For the full agreement, please refer to the [LICENSE](./LICENSE) file. --- @@ -555,34 +567,34 @@ See the full [LICENSE](../LICENSE) file for details. --- -# 🙏 Thanks +# 🙏 Acknowledgements -Thank you to the following open-source projects for supporting Toonflow: +We sincerely thank the following open-source projects for providing robust support to Toonflow: -- [Express](https://expressjs.com/) - Fast, open, minimalist Node.js Web framework -- [AI SDK](https://ai-sdk.dev/) - TypeScript-first AI toolkit -- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - High-performance SQLite3 bindings -- [Sharp](https://sharp.pixelplumbing.com/) - High-performance Node.js image toolkit +- [Express](https://expressjs.com/) - Fast, unopinionated, minimalist web framework for Node.js +- [AI SDK](https://ai-sdk.dev/) - The AI toolkit for TypeScript +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - High-performance SQLite3 binding library +- [Sharp](https://sharp.pixelplumbing.com/) - High-performance Node.js image processing - [Axios](https://axios-http.com/) - Promise-based HTTP client -- [Zod](https://zod.dev/) - TypeScript-first schema validation library -- [Socket.IO](https://socket.io/) - Real-time bidirectional event framework -- [Electron](https://www.electronjs.org/) - Cross-platform desktop app framework -- [Hugging Face Transformers](https://huggingface.co./transformers.js) - Local ML inference library +- [Zod](https://zod.dev/) - TypeScript-first schema validation +- [Socket.IO](https://socket.io/) - Real-time bidirectional event-based communication +- [Electron](https://www.electronjs.org/) - Cross-platform desktop application framework +- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - State-of-the-art Machine Learning for the web -Thanks to the following organizations/individuals for their support: +Thanks to the following organizations/individuals for supporting Toonflow:
- SophNet Logo + Sophgo Logo - SophNet Cloud provides computing power sponsorship - [Official Website] + Sophnet for providing computing power sponsorship + [Website]
-For a complete list of third-party dependencies, see `NOTICES.txt` +For a complete list of third-party dependencies, please refer to `NOTICES.txt`. -##### copyright © 淮北艾阿网络科技有限公司 \ No newline at end of file +##### Copyright © Huaibei AIA Network Technology Co., Ltd. \ No newline at end of file diff --git a/docs/README.ja.md b/docs/README.ja.md index 7d2325d..e639351 100644 --- a/docs/README.ja.md +++ b/docs/README.ja.md @@ -1,4 +1,4 @@ -

+

GitHub @@ -8,19 +8,18 @@  |  - Atomgit - Atomgit + Atomgit

- 簡体字中国語 | - 繁体字中国語 | - 英語 | - タイ語 | - ベトナム語 | + 简体中文 | + 繁體中文 | + English | + ไทย | + Tiếng Việt | 日本語 | - ロシア語 + Русский

@@ -31,9 +30,9 @@

- AI短編ドラマ工場 + AI ショートドラマ制作スタジオ
- 指先ひとつで、小説が瞬時にドラマ化! + 指先一つで、小説があっという間にドラマに!
AI脚本 × AI映像 × 超高速生成 🔥
@@ -50,173 +49,175 @@

- > 🚀 **ワンストップ短編ドラマ制作**:テキストからキャラクター、絵コンテ、映像まで、0知識でAI化された全プロセス。創作効率10倍以上! + > 🚀 **オールインワン制作環境**:テキストからキャラクター、絵コンテから動画まで。 + 専門知識ゼロでも全プロセスをAIが**アシスト**し、創作効率を10倍以上に引き上げます!
--- # 🌐 多言語対応 -Toonflowは以下の言語インターフェースに対応しています: +Toonflow は以下の言語インターフェースに対応しています: | 言語 | Language | |------|----------| -| 简体中文 | 中国語(簡体字) | -| 繁體中文 | 中国語(繁体字) | -| English | 英語 | -| ไทย | タイ語 | -| Tiếng Việt | ベトナム語 | -| 日本語 | 日本語 | -| Русский | ロシア語 | +| 简体中文 | Chinese (Simplified) | +| 繁體中文 | Chinese (Traditional) | +| English | English | +| ไทย | Thai | +| Tiếng Việt | Vietnamese | +| 日本語 | Japanese | +| Русский | Russian | + +> 💡 さらに多くの言語に対応予定です。多言語翻訳へのご協力(貢献)を歓迎します! --- # 🌟 主な機能 -ToonflowはAI短編漫画/ドラマ制作ツールで、小説をAIが自動的に脚本化し、AI生成画像・映像と組み合わせて高効率な短編ドラマ制作を実現します。Toonflowにより、テキストから映像までの流れを簡単に完結でき、短編ドラマ制作がよりスマート&便利になります。 +Toonflow は、AI技術を活用して小説を自動的に脚本へ変換し、AIが生成した画像や動画と組み合わせることで、効率的なショートドラマ制作を強力に**アシスト**するツールです。Toonflow を使えば、テキストから映像までの全工程を簡単に完結でき、ドラマ制作がよりスマートで便利になります。 -- ✅ **キャラクター生成** - 元の小説テキストを自動分析し、外見・性格・身分など詳細なキャラクター設定をスマートに識別・生成。脚本・作画の基盤を提供します。 -- ✅ **脚本生成** - 選択したエピソードや章に基づき、構造化された脚本(セリフ・シーン描写・ストーリー展開など)をシステムが自動生成。小説から映像脚本への効率的な変換を実現します。 -- ✅ **絵コンテ作成** - 脚本内容に基づき、AIが適切な絵コンテプロンプトや画面設計を生成。前景・中景・背景、キャラクター動作、小道具設計、場面レイアウトを細分化し、脚本からビデオへの完全なルートマップを自動構築します。 -- ✅ **動画合成** - AI画像と動画技術を統合し、AI生成により映像クリップの作成が可能。オンライン編集と個別調整にも対応し、映像創作の効率アップ&迅速実現をサポートします。 +- ✅ **キャラクター生成** 原作の小説テキストを自動分析し、容姿、性格、身分などの詳細情報をインテリジェントに認識・生成します。これにより、後の脚本や画面作りにおいて信頼できる土台を提供します。 + +- ✅ **脚本生成** 選択したイベントや章に基づき、セリフ、シーンの描写、ストーリー展開を含む構造化された脚本を自動生成します。文学テキストから映像用脚本への高効率な変換を**アシスト**します。 + +- ✅ **絵コンテ制作** 脚本の内容から、絵コンテ用のプロンプト(指示文)と画面構成をインテリジェントに生成します。前景・中景・背景、キャラクターの動き、小道具の配置などを細分化し、動画制作の道筋を完全に**アシスト**します。 + +- ✅ **動画合成** AI画像および動画技術を統合し、AIによる動画クリップ生成を可能にします。オンライン編集機能も備えており、個別の微調整に対応。映像制作の効率的な連携とスピーディな完成を**アシスト**します。 --- -# 📦 利用シーン +# 📦 活用シーン -- ショート動画コンテンツ制作 -- 小説の映像化実験 -- AI文学改編ツール -- 脚本開発&高速プロトタイピング -- 動画素材生成 +- ショート動画コンテンツの制作 +- 小説の映像化テスト +- AIによる文学作品の翻案(脚色)ツール +- 脚本開発および迅速なプロトタイプ作成 +- 動画素材の生成 --- -# 🔰 使い方ガイド +# 🔰 ご利用ガイド ## 📺 動画チュートリアル -https://www.bilibili.com/video/BV1na6wB6Ea2 -[![Toonflow 8分でAI動画をクイックスタート](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) +[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2) +[![Toonflow 8分でわかるAI動画作成](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) -**Toonflow 8分クイックスタートAI動画** -👉 [クリックして見る](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) +**Toonflow 8分でわかるクイックスタート AI動画作成** +👉 [クリックして視聴](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) -📱 スマホWeChatでQRコードをスキャンして視聴 +📱 QRコードをスキャンして視聴 -微信扫码观看 +WeChat スキャンして視聴 --- # 🚀 インストール -## 前提条件 +## 必須環境(前提条件) -本ソフトウェアのインストール・利用前に以下をご用意ください: +本ソフトウェアをインストールして使用する前に、以下の準備をお願いします: -- ✅ 大規模言語モデルAIサービスのエンドポイント -- ✅ SoraまたはDoubao動画サービスAPI -- ✅ Nano Banana Pro画像生成モデルAPI +- ✅ 大規模言語モデル (LLM) の AI サービス API エンドポイント +- ✅ Sora または 豆包 (Doubao) の動画サービス API エンドポイント +- ✅ Nano Banana Pro の画像生成モデルサービス API エンドポイント -## ローカルインストール +## ローカル環境へのインストール -### 1. ダウンロード&インストール +### 1. ダウンロードとインストール -| オペレーティングシステム | GitHub | Atomgit | クアークネットディスクダウンロード | 説明 | +| OS | GitHub | Atomgit | Quark Drive | 説明 | | :------: | :----------------------------------------------------------- | :------------------------------------------------------------ | :---------------------------------------------- | :------------- | -| Windows | [リリース](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [リリース](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [クアークネットディスク](https://pan.quark.cn/s/94ef07509df0) | 公式リリースインストールパッケージ | -| Linux | [リリース](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [リリース](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [クアークネットディスク](https://pan.quark.cn/s/94ef07509df0) | 公式リリースインストールパッケージ | -| macOS | [リリース](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [リリース](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [クアークネットディスク](https://pan.quark.cn/s/94ef07509df0) | 公式リリースインストールパッケージ | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | 公式インストーラ | +| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | 公式インストーラ | +| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | 公式インストーラ | > [!CAUTION] -> MacOSの場合は、設定→プライバシーとセキュリティでセキュリティ設定を許可してください。証明書問題でアプリが開かない場合があります。 +> MacOS システムをご利用の場合、「システム設定」-「プライバシーとセキュリティ」からセキュリティ設定を行ってください。そうしないと、証明書の問題で正常に開けない場合があります。 > -> 参考:知乎ドキュメント:[https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) +> 参考ドキュメント(Zhihu):[https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) -> Gitee OSの制限とReleaseファイルのサイズ上限により、Gitee側のReleaseダウンロードは現在未提供です。 +> Gitee OS 環境の制限および Release ファイルのアップロード容量制限により、現在 Gitee Release のダウンロードリンクは提供していません。 -### 2. サービス起動 +### 2. サービスの起動 -インストール後、アプリを起動してください。 +インストール完了後、プログラムを起動すればサービスを利用開始できます。 -> ⚠️ **初回ログイン** -> アカウント:`admin` +> ⚠️ **初回ログイン** +> ユーザー名:`admin` > パスワード:`admin123` -## Dockerデプロイ +## Docker を利用した導入 -### 前提条件 +### 必須環境 -- [Docker](https://docs.docker.com/get-docker/)(バージョン 20.10以上)インストール済み +- [Docker](https://docs.docker.com/get-docker/) がインストール済みであること(バージョン 20.10+) -### 方法1:オンラインデプロイ +### 方法1:オンライン展開 -現在準備中。しばらくはローカルビルドをご利用ください。 +現在準備中です。一時的にローカルでのビルドをご利用ください。 -### 方法2:ローカルビルド +### 方法2:ローカルでのビルド -お手持ちのソースコードから直接ビルド。開発者またはリポジトリクローン済ユーザー向け(git要インストール)。 +既存のソースコードを使用して直接ビルドします。開発者やリポジトリをクローンしたユーザーに適しています(ローカルに git がインストールされている必要があります): ```shell -# まずプロジェクトをクローン(既にある場合は省略可) +# まずプロジェクトをクローン(既に存在する場合はスキップ) git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app -# docker-composeでローカルビルド&起動 +# docker-compose を使用してローカルでビルド・起動 yarn docker:local -# または手動ビルド +# または手動でビルド docker build -t toonflow . docker run -d -p <ローカルポート>:10588 -v <ローカルデータパス>:/app/data toonflow -# 指定ポートの /web/index.html でアクセス可 -# 例)http://localhost:10588/web/index.html +# これで指定したポートの /web/index.html にアクセスできます +# 例: http://localhost:10588/web/index.html ``` -### サービスポート情報 +### サービスポートの説明 -| ポート | 用途 | デプロイマッピング | +| ポート | 用途 | デプロイマッピング | | ------- | -------- | ------------- | -| `10588` | UI | `10588:10588` | +| `10588` | ソフトウェア画面 | `10588:10588` | -**環境変数メモ:** +**環境変数の説明:** -| 変数 | 説明 | -| ------------ | -------------------------- | -| `NODE_ENV` | 実行環境、`prod`が本番 | -| `PORT` | サービスポート(デフォルト10588) | -| `OSSURL` | ファイル保存URL(静的リソース) | +| 変数名 | 説明 | +| ---------- | ---------------------------------- | +| `NODE_ENV` | 実行環境。`prod` は本番環境を示します | +| `PORT` | サービスの待受ポート(デフォルト 10588) | +| `OSSURL` | ファイルストレージのアクセスURL(静的リソース用) | --- -## クラウドデプロイ +## クラウド(サーバー)への導入 -### 1. サーバー環境要件 +### 1. サーバー環境の要件 -- **OS**:Ubuntu 20.04以上/CentOS 7以上 -- **Node.js**:24.x(推奨、最低23.11.1以上) +- **OS**:Ubuntu 20.04+ / CentOS 7+ +- **Node.js**:24.x(推奨、最低 23.11.1+) - **メモリ**:2GB以上 -### 2. サーバーデプロイ +### 2. サーバーへの配置 -#### 1. 環境インストール +#### 1. 環境構築 ```bash -# Node.jsインストール +# Node.js のインストール curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 24 -# YarnとPM2インストール +# Yarn と PM2 のインストール npm install -g yarn pm2 ``` -#### 2. プロジェクト導入 +#### 2. プロジェクトの配置 -**GitHubからクローン:** +**GitHub からクローン:** ```bash cd /opt @@ -226,7 +227,7 @@ yarn install yarn build ``` -**Giteeからクローン(中国国内推奨):** +**Gitee からクローン(中国国内推奨):** ```bash cd /opt @@ -236,9 +237,9 @@ yarn install yarn build ``` -#### 3. PM2構成 +#### 3. PM2 の設定 -`pm2.json`ファイルを作成: +`pm2.json` ファイルを作成します: ```json { @@ -254,17 +255,17 @@ yarn build } ``` -**環境変数説明:** +**環境変数の説明:** -| 変数 | 説明 | -| ------------ | -------------------------- | -| `NODE_ENV` | 実行環境、`prod`が本番 | -| `PORT` | サービスポート | -| `OSSURL` | ファイル保存URL(静的リソース) | +| 変数名 | 説明 | +| ---------- | ---------------------------------- | +| `NODE_ENV` | 実行環境。`prod` は本番環境を示します | +| `PORT` | サービスの待受ポート | +| `OSSURL` | ファイルストレージのアクセスURL(静的リソース用) | --- -#### 4. サービス起動 +#### 4. サービスの起動 ```bash pm2 start pm2.json @@ -275,77 +276,77 @@ pm2 save #### 5. よく使うコマンド ```bash -pm2 list # プロセス一覧 -pm2 logs toonflow-app # ログを見る -pm2 restart all # サービス再起動 -pm2 monit # 監視パネル +pm2 list # プロセス一覧の確認 +pm2 logs toonflow-app # ログの確認 +pm2 restart all # サービスの再起動 +pm2 monit # 監視パネルの表示 ``` -> ⚠️ **初回ログイン** -> アカウント:`admin` +> ⚠️ **初回ログイン** +> ユーザー名:`admin` > パスワード:`admin123` -#### 6. フロントエンドのデプロイ +#### 6. フロントエンドサイトの配置 -前端の分離デプロイやカスタマイズが必要な場合はこちら: +フロントエンド画面を単独で配置、またはカスタマイズしたい場合は、フロントエンドのリポジトリを参照してください: - **GitHub**:[Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**:[Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -> 💡 **補足**:このリポジトリにはビルド済のフロントリソースが内蔵済み。通常ユーザーはフロント分離構築は不要。フロントリポジトリはカスタム開発用です。 +> 💡 **補足**:本リポジトリには既にコンパイル済みのフロントエンド成果物が組み込まれているため、一般ユーザーはフロントエンドを個別に配置する必要はありません。フロントエンドのリポジトリは、二次開発を行う開発者向けです。 --- # 🔧 開発フローガイド > [!CAUTION] -> 🚧 **PR提出ガイドライン** 🚧 +> 🚧 **PR(プルリクエスト)提出のルール** 🚧 > -> ⛔ `master`ブランチはPR不可 | ✅ `develop`ブランチにPR提出 +> ⛔ `master` ブランチへの PR は受け付けていません | ✅ PR は `develop` ブランチへ提出してください > -> 開発者のご参加を歓迎します。参加希望はコミュニティで主催者ACTにご連絡ください。 +> 開発者の皆様の Toonflow への共同参加を歓迎します。興味のある方は、交流グループ内で管理者の ACT までご連絡ください。 -## 🛠️ 技術スタック +## 🛠️ 採用技術 -| カテゴリ | 技術 | -| -------------- | ---------------------------------------------------------------------------------------- | -| ランタイム | Node.js 23.11.1+ | -| 言語 | TypeScript 5.x | -| バックエンド | Express 5 | -| データベース | SQLite(better-sqlite3 / knex) | -| AI連携 | Vercel AI SDK(OpenAI / Anthropic / Google / DeepSeek / 智谱 / MiniMax / 通義千問 / xAI) | -| ローカル推論 | @huggingface/transformers(ONNX) | -| リアルタイム通信 | Socket.IO | -| デスクトップ | Electron 40 | -| 画像処理 | Sharp | -| コンテナ化 | Docker | +| カテゴリ | 技術 | +| ---------- | ----------------------------------------------------------------------------------------- | +| 実行環境 | Node.js 23.11.1+ | +| 言語 | TypeScript 5.x | +| バックエンド | Express 5 | +| データベース | SQLite(better-sqlite3 / knex) | +| AI 統合 | Vercel AI SDK(OpenAI / Anthropic / Google / DeepSeek / 智譜 / MiniMax / 通義千問 / xAI) | +| ローカル推論 | @huggingface/transformers(ONNX) | +| リアルタイム通信 | Socket.IO | +| デスクトップアプリ | Electron 40 | +| 画像処理 | Sharp | +| コンテナ化 | Docker | -## 開発環境準備 +## 開発環境の準備 -- **Node.js**:バージョン23.11.1以上 -- **Yarn**:パッケージマネージャ推奨 +- **Node.js**:バージョン 23.11.1 以上が必要 +- **Yarn**:プロジェクトのパッケージマネージャーとして推奨 -## プロジェクトのクイック起動 +## プロジェクトのクイックスタート -1. **プロジェクトクローン** +1. **プロジェクトのクローン** - **GitHubからクローン:** + **GitHub からクローン:** ```bash git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` - **Giteeからクローン(中国国内推奨):** + **Gitee からクローン(中国国内推奨):** ```bash git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` -2. **依存パッケージインストール** +2. **依存関係(パッケージ)のインストール** - プロジェクト直下で次を実行: + プロジェクトのルートディレクトリで以下のコマンドを実行します: ```bash yarn install @@ -353,69 +354,69 @@ pm2 monit # 監視パネル 3. **開発環境の起動** - 本プロジェクトは**バックエンドAPIサービス**と**フロントエンド**があります。次から用途を選択。 + 本プロジェクトは **バックエンド API サービス** と **フロントエンド画面** の2つの部分を含みます。必要に応じて起動方法を選択してください: - - **方法1:バックエンドのみ起動** + - **方法1:バックエンドサービスのみ起動** ```bash yarn dev ``` - > ⚠️ このコマンドはAPIサーバー(ポート10588)のみ起動。`http://localhost:10588`でAPIのみ利用。GUI表示にはフロントプロジェクトの起動または下記のGUIモードをご利用ください。 + > ⚠️ このコマンドはバックエンド API サービス(ポート 10588)のみを起動し、**フロントエンド画面は含まれません**。直接 `http://localhost:10588` にアクセスしても API を呼び出せるだけで、完全な Web 画面は見えません。画面を利用する場合はフロントエンドプロジェクトを別途起動するか、以下の GUI モードを使用してください。 - - **方法2:Electronデスクトップクライアント** + - **方法2:Electron デスクトップクライアントの起動** ```bash yarn dev:gui ``` - > バックエンドとElectronウィンドウが同時起動。内蔵フロント付きで即利用OK。すべての機能を体験したい方向け。 + > このコマンドはバックエンドサービスと Electron のデスクトップウィンドウを同時に起動します。フロントエンド画面が内蔵されており、追加の設定なしですぐに使えます。すべての機能を体験したい開発者に最適です。 - - **方法3:本番モードで起動** + - **方法3:本番(Production)モードで起動** ```bash yarn start ``` - > 本番モードでビルド済サービスを直接起動(`yarn build`が必要)。 + > コンパイル済みのサービスを本番モードで直接実行します(事前に `yarn build` を実行しておく必要があります)。 -4. **プロジェクトパッケージ化** +4. **プロジェクトのパッケージ化(ビルド)** - - TypeScriptファイルのビルド: + - コンパイルして TypeScript ファイルを生成: ```bash yarn build ``` - - Windows用実行ファイル化: + - Windows 用の実行ファイルをパッケージ化: ```bash yarn dist:win ``` - - Mac用実行ファイル化: + - Mac 用の実行ファイルをパッケージ化: ```bash yarn dist:mac ``` - - Linux用実行ファイル化: + - Linux 用の実行ファイルをパッケージ化: ```bash yarn dist:linux ``` -5. **コード品質チェック** +5. **コード品質チェック(Lint)** - - グローバルLintチェック: + - グローバルな構文およびコーディング規約のチェックを実行: ```bash yarn lint ``` -6. **AIデバッグパネル(任意)** +6. **AI デバッグパネル(オプション)** - AI SDKのGUIデバッグツール。AI呼び出しのデバッグに便利。 + AI SDK のビジュアルデバッグツールを起動し、AI の呼び出しを簡単にデバッグできます: ```bash yarn debug:ai @@ -423,68 +424,68 @@ pm2 monit # 監視パネル ## フロントエンド開発 -フロントUIの修正はフロントエンドリポジトリへ: +フロントエンド画面を修正する必要がある場合は、フロントエンドのリポジトリで開発を行ってください: - **GitHub**:[Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**:[Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -ビルド後、`dist`以下を本プロジェクト `data/web`へコピーで統合完了。 +フロントエンドのビルド後、`dist` ディレクトリの内容を本プロジェクトの `data/web` ディレクトリにコピーするだけで統合できます。 ## プロジェクト構成 ``` 📂 build/ # ビルド成果物 📂 data/ # 実行時データ -│ ├─ 📂 models/ # ローカル推論モデル(ONNX) -│ ├─ 📂 oss/ # オブジェクトストレージ(素材/キャラ/背景) -│ ├─ 📂 serve/ # 本番エントリ -│ ├─ 📂 skills/ # Agentプロンプト集 -│ └─ 📂 web/ # ビルトインフロント -📂 docs/ # ドキュメントリソース +│ ├─ 📂 models/ # ローカル推論モデル(ONNX) +│ ├─ 📂 oss/ # オブジェクトストレージ(素材/キャラクター/背景) +│ ├─ 📂 serve/ # 本番環境のエントリー +│ ├─ 📂 skills/ # Agent スキルのプロンプト +│ └─ 📂 web/ # フロントエンドビルド成果物(内蔵) +📂 docs/ # ドキュメントや画像リソース 📂 env/ # 環境設定 -📂 scripts/ # ビルド&ツールスクリプト +📂 scripts/ # ビルドや補助スクリプト 📂 src/ -├─ 📂 agents/ # AI Agentモジュール -│ ├─ 📂 productionAgent/ # プロダクション用Agent -│ └─ 📂 scriptAgent/ # 脚本Agent -├─ 📂 lib/ # 共通ライブラリ(DB初期化等) -├─ 📂 middleware/ # ミドルウェア -├─ 📂 routes/ # ルーティングモジュール -│ ├─ 📂 agents/ # Agentメモリ管理 -│ ├─ 📂 artStyle/ # 画風管理 -│ ├─ 📂 assets/ # 素材管理 -│ ├─ 📂 assetsGenerate/ # 素材生成 -│ ├─ 📂 cornerScape/ # 絵コンテ管理 -│ ├─ 📂 general/ # 共通API -│ ├─ 📂 login/ # ログイン認証 -│ ├─ 📂 migrate/ # データ移行 -│ ├─ 📂 modelSelect/ # モデル選択 -│ ├─ 📂 novel/ # 小説管理 -│ ├─ 📂 other/ # その他機能 -│ ├─ 📂 production/ # 制作管理 -│ ├─ 📂 project/ # プロジェクト管理 -│ ├─ 📂 script/ # 脚本生成 -│ ├─ 📂 scriptAgent/ # 脚本AgentAPI -│ ├─ 📂 setting/ # システム設定 -│ ├─ 📂 task/ # タスク管理 -│ └─ 📂 test/ # テストAPI -├─ 📂 socket/ # WebSocket通信 -├─ 📂 types/ # TypeScript型 -├─ 📂 utils/ # ユーティリティ -├─ 📄 app.ts # アプリエントリ -├─ 📄 core.ts # コア初期化 -├─ 📄 env.ts # 環境変数処理 -├─ 📄 err.ts # エラーハンドラ -├─ 📄 logger.ts # ロギング -├─ 📄 router.ts # ルート登録 -└─ 📄 utils.ts # 共通ツール -📄 Dockerfile # Dockerビルド -📄 electron-builder.yml # Electronパッケージ設定 +├─ 📂 agents/ # AI Agent モジュール +│ ├─ 📂 productionAgent/ # 制作 Agent +│ └─ 📂 scriptAgent/ # 脚本 Agent +├─ 📂 lib/ # 共通ライブラリ(DB初期化、レスポンス形式など) +├─ 📂 middleware/ # ミドルウェア +├─ 📂 routes/ # ルーティングモジュール +│ ├─ 📂 agents/ # Agent メモリ管理 +│ ├─ 📂 artStyle/ # 画風(アートスタイル)管理 +│ ├─ 📂 assets/ # 素材管理 +│ ├─ 📂 assetsGenerate/ # 素材生成 +│ ├─ 📂 cornerScape/ # 絵コンテ管理 +│ ├─ 📂 general/ # 汎用 API +│ ├─ 📂 login/ # ログイン認証 +│ ├─ 📂 migrate/ # データ移行 +│ ├─ 📂 modelSelect/ # モデル選択 +│ ├─ 📂 novel/ # 小説管理 +│ ├─ 📂 other/ # その他機能 +│ ├─ 📂 production/ # 制作進行管理 +│ ├─ 📂 project/ # プロジェクト管理 +│ ├─ 📂 script/ # 脚本生成 +│ ├─ 📂 scriptAgent/ # 脚本 Agent インターフェース +│ ├─ 📂 setting/ # システム設定 +│ ├─ 📂 task/ # タスク管理 +│ └─ 📂 test/ # テスト用 API +├─ 📂 socket/ # WebSocket リアルタイム通信 +├─ 📂 types/ # TypeScript 型定義 +├─ 📂 utils/ # ユーティリティ関数 +├─ 📄 app.ts # アプリケーションエントリー +├─ 📄 core.ts # コア初期化 +├─ 📄 env.ts # 環境変数の処理 +├─ 📄 err.ts # エラーハンドリング +├─ 📄 logger.ts # ログモジュール +├─ 📄 router.ts # ルーティング登録 +└─ 📄 utils.ts # 汎用ツール +📄 Dockerfile # Docker ビルドファイル +📄 electron-builder.yml # Electron パッケージ設定 📄 skillList.json # スキルリスト 📄 LICENSE # ライセンス(Apache-2.0) -📄 NOTICES.txt # サードパーティ依存リスト +📄 NOTICES.txt # 依存パッケージに関する表記 📄 package.json # プロジェクト設定 -📄 tsconfig.json # TypeScript設定 +📄 tsconfig.json # TypeScript 設定 ``` --- @@ -492,64 +493,66 @@ pm2 monit # 監視パネル # 🔗 関連リポジトリ | リポジトリ | 説明 | GitHub | Gitee | -| ------------------ | ---------------------------------- | -------------------------------------------------- | ------------------------------------------------ | -| **Toonflow-app** | フルクライアント(本リポジトリ、一般ユーザー向け) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | -| **Toonflow-web** | フロントエンドソース(フロントエンド開発者向け) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | +| ---------------- | ---------------------------------- | -------------------------------------------------- | ------------------------------------------------ | +| **Toonflow-app** | 完全版クライアント(本リポジトリ、一般ユーザー向け) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | フロントエンドソースコード(フロントエンド開発者向け) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | -> 💡 **ヒント**:Toonflowを利用したいだけなら本リポジトリをそのままダウンロードすればOK。フロントリポジトリはフロントカスタマイズや2次開発者向けです。 +> 💡 **ヒント**:Toonflow を使用するだけであれば、本リポジトリのクライアントを直接ダウンロードするだけで十分です。フロントエンドのリポジトリは、二次開発やフロントエンド画面のカスタマイズが必要な開発者向けです。 --- -# 👨‍👩‍👧‍👦 WeChatコミュニティグループ +# 👨‍👩‍👧‍👦 Discord 交流グループ -グループ招待アシスタント: +下のアイコンをクリックして Discord に参加: -Toonflow QR +[![Join our Discord](https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/67d00cf7266d2c75571aebde_Example.svg)](https://discord.gg/HEjKmpNpAZ) + +または直接リンクをクリック: [https://discord.gg/HEjKmpNpAZ](https://discord.gg/HEjKmpNpAZ) --- # 💌 お問い合わせ -📧 メール:[ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow相談) +📧 メール:[ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflowのお問い合わせ) --- # 📜 ライセンス -ToonflowはApache-2.0ライセンス+補足商業契約でオープンソース公開されています。 +Toonflow は Apache-2.0 ライセンスに基づいてオープンソースとして公開されており、補足的な商業契約が付随しています。 -ライセンス詳細:https://www.apache.org/licenses/LICENSE-2.0 +ライセンスの詳細:https://www.apache.org/licenses/LICENSE-2.0 -## 補足契約 +## 補足条項 -- 本ソフトウェアを製品として**2つ以上の独立した第三者**に配布する場合、HBAI-Ltdの**書面による商業許諾**が必要です。 -- **5法人以下**の共同運営で内部利用のみの場合は、**商業許諾不要**です。 -- Toonflowの商標・ロゴ・著作権情報の削除・改変は禁止です。 +- 本ソフトウェアを製品として **2つ以上の独立した第三者** に配布・提供する場合、HBAI-Ltd からの **書面による商業ライセンス(許諾)** を取得する必要があります。 +- **5法人以下** が共同で運営し、外部にサービスを提供せずに内部利用のみとする場合は、内部利用と見なされ、**商業ライセンスの取得は不要**です。 +- Toonflow 内のロゴや著作権情報を削除または変更することは禁止されています。 -## 永久無料シーン +## 永久無料となるケース -- ✅ Toonflowでコンテンツを制作しプラットフォーム収益を得る -- ✅ 自チーム内部利用の二次開発 -- ✅ ≤ 5法人の共同運営内部利用 -- ✅ 個人学習・研究・非商用利用 +- ✅ Toonflow を利用してコンテンツを制作し、プラットフォームから収益分配を得る場合 +- ✅ 自分のチーム内で使用するために二次開発を行う場合 +- ✅ 5法人以下の共同運営による内部利用 +- ✅ 個人の学習、研究、非営利目的 ## 商業ライセンス価格 -| 段階 | 年間売上高 | 年間費用 | +| フェーズ | 年間売上高 | 年間費用 | |------|---------|------| -| 🌱 育成期 | < ¥10万 | **無料** | -| 🚀 スタートアップ | ¥10〜50万 | ¥5,000/年 | -| 📈 成長期 | ¥50〜150万 | ¥20,000/年 | -| 🏢 拡大期 | ¥150〜500万 | ¥80,000/年 | -| 🌐 エンタープライズ | > ¥500万 | 要相談 | +| 🌱 支援期 | 200万円 未満 | **無料** | +| 🚀 創業期 | 200万円 ~ 1,000万円 | 108,000 円/年 | +| 📈 成長期 | 1,000万円 ~ 3,000万円 | 420,000 円/年 | +| 🏢 規模拡大期 | 3,000万円 ~ 1億円 | 1,680,000 円/年 | +| 🌐 エンタープライズ | 1億円 超 | 応相談 | -> **不遡及条項**:v1.0.8リリース前にAGPL-3.0でToonflowを使用していたユーザーは、本変更の影響を受けません。既存の利用はAGPL-3.0に基づき継続されます。 +> **遡及(そきゅう)適用除外条項**:v1.0.8 リリース以前に AGPL-3.0 に基づいて使用していたユーザーは、引き続き AGPL-3.0 に従い、本契約変更の制約を受けません。 -完全な契約内容は [LICENSE](../LICENSE) をご覧ください。 +契約の全文については [LICENSE](./LICENSE) ファイルを参照してください。 --- -# ⭐️ スター履歴 +# ⭐️ Star 獲得履歴 [![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left)](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left) @@ -557,34 +560,32 @@ ToonflowはApache-2.0ライセンス+補足商業契約でオープンソー # 🙏 謝辞 -以下のオープンソースプロジェクトの強力な支援に感謝します: +Toonflow に強力なサポートを提供してくださる以下のオープンソースプロジェクトに感謝いたします: -- [Express](https://expressjs.com/) - 高速・オープンなNode.js Webフレームワーク -- [AI SDK](https://ai-sdk.dev/) - TypeScript向けAIツールキット -- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - 高性能SQLite3バインディング -- [Sharp](https://sharp.pixelplumbing.com/) - 高速Node.js画像処理 -- [Axios](https://axios-http.com/) - PromiseベースHTTPクライアント -- [Zod](https://zod.dev/) - TypeScript優先のバリデーション -- [Socket.IO](https://socket.io/) - リアルタイム双方向通信エンジン -- [Electron](https://www.electronjs.org/) - クロスプラットフォームデスクトップ開発 -- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - ローカル機械学習推論ライブラリ +- [Express](https://expressjs.com/) - 高速でオープン、ミニマルな Node.js Web フレームワーク +- [AI SDK](https://ai-sdk.dev/) - TypeScript 向け AI ツールキット +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - 高性能 SQLite3 バインディングライブラリ +- [Sharp](https://sharp.pixelplumbing.com/) - 高性能 Node.js 画像処理ライブラリ +- [Axios](https://axios-http.com/) - Promise ベースの HTTP クライアント +- [Zod](https://zod.dev/) - TypeScript ファーストのスキーマ検証ライブラリ +- [Socket.IO](https://socket.io/) - リアルタイムの双方向イベント通信エンジン +- [Electron](https://www.electronjs.org/) - クロスプラットフォームデスクトップアプリ開発フレームワーク +- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - ローカル ML 推論ライブラリ -以下の組織・団体・個人によるToonflowへの協力に感謝します: +Toonflow を支援してくださる以下の組織・団体・個人に感謝いたします:
- 算能云 Logo + 算能雲 Logo - 算能云 よりコンピューティング協賛 - [公式サイト] + 算能雲 (Sophnet) 様より計算リソースの提供をいただいております + [公式サイト]
-第三者依存リストは `NOTICES.txt` をご覧ください +完全なサードパーティの依存関係リストについては `NOTICES.txt` をご参照ください。 - - -##### copyright © 淮北艾阿网络科技有限公司 \ No newline at end of file +##### copyright © Huaibei AIA Network Technology Co., Ltd. \ No newline at end of file diff --git a/docs/README.ru.md b/docs/README.ru.md index db4583a..8b9ba80 100644 --- a/docs/README.ru.md +++ b/docs/README.ru.md @@ -8,13 +8,12 @@  |  - Atomgit - Atomgit + Atomgit

- 简体中文 | + 简体中文 | 繁體中文 | English | ไทย | @@ -31,11 +30,11 @@

- AI-фабрика коротких сериалов + Фабрика AI-мини-сериалов и короткометражных фильмов
- Одним движением — роман за секунду становится сериалом! + Всего несколько кликов — и ваша новелла превращается в фильм или сериал!
- AI-сценарий × AI-изображения × Молниеносная генерация 🔥 + AI-сценарий × AI-изображения × Сверхбыстрая генерация 🔥

@@ -50,65 +49,71 @@

- > 🚀 **Универсальный конвейер коротких сериалов**: от текста к персонажам, от раскадровки к видео, 0 порога по всему процессу на базе AI, рост эффективности творчества 10× и более! +> 🚀 **All-in-One платформа для коротких сериалов и фильмов**: От текста до персонажей, от раскадровки до готового видео. Полная автоматизация с помощью ИИ с нулевым порогом входа — повышает эффективность творчества в 10 раз и более! --- -# 🌐 Многоязычная поддержка +# 🌐 Мультиязычная поддержка Toonflow поддерживает следующие языки интерфейса: -| Язык | Language | -|------|----------| -| 简体中文 | Китайский (упрощённый) | -| 繁體中文 | Китайский (традиционный) | -| English | Английский | -| ไทย | Тайский | -| Tiếng Việt | Вьетнамский | -| 日本語 | Японский | -| Русский | Русский | +| Язык | Language | +|---------------|---------------------------| +| 简体中文 | Chinese (Simplified) | +| 繁體中文 | Chinese (Traditional) | +| English | English | +| ไทย | Thai | +| Tiếng Việt | Vietnamese | +| 日本語 | Japanese | +| Русский | Russian | + +> 💡 В настоящее время мы активно добавляем новые языки. Будем рады вашей помощи с переводами! --- -# 🌟 Основные функции +# 🌟 Основные возможности -Toonflow — инструмент для создания коротких сериалов и комиксов с помощью AI, позволяющий автоматически превращать романы в сценарии и генерировать изображения и видео с помощью нейросетей. Используя Toonflow, вы легко пройдёте путь от текста к видео: создание коротких фильмов становится умнее и удобнее. +Toonflow — это мощный ИИ-инструмент для создания коротких видео, мини-сериалов и комиксов. Он автоматически превращает новеллы в сценарии, а затем с помощью ИИ генерирует изображения и видео, позволяя быстро и эффективно создавать качественный контент. +С Toonflow вы можете пройти весь цикл производства — от текста до готового видео — легко и удобно, без специальных навыков. - ✅ **Генерация персонажей** - Автоматически анализирует исходный текст романа, интеллектуально идентифицирует и генерирует параметры персонажей, включая внешний вид, характер, социальный статус и др., формируя прочную основу для дальнейшей разработки сценария и визуала. + Автоматический анализ оригинального текста новеллы, интеллектуальное распознавание и создание подробных профилей персонажей (внешность, характер, личность, отношения и другие детали). Это закладывает прочную основу для сценария и визуальной части. + - ✅ **Генерация сценария** - На основе выбранных событий и глав система автоматически создает структурированный сценарий, включая диалоги, описание сцен и развитие сюжета, обеспечивая эффективную трансформацию из литературного текста в кинематографический сценарий. -- ✅ **Раскадровка** - На основе сценария AI генерирует креативные промпты и дизайн кадров, прорабатывает передний-средний-задний план, динамику персонажей, реквизит и компоновку сцен, автоматически создаёт раскадровку для дальнейшей видеосборки. -- ✅ **Видеосборка** - Интегрирует AI-технологии генерации изображений и видео. Позволяет создавать фрагменты видео с помощью ИИ. Системы онлайн-редактирования поддерживают индивидуальные настройки и быстрый вывод конечного результата. + На основе выбранных событий и глав система автоматически создаёт структурированный сценарий с естественными диалогами, описаниями сцен и развитием сюжета, обеспечивая эффективную адаптацию литературного произведения в видеоформат. + +- ✅ **Создание раскадровки (Storyboard)** + Автоматическая генерация промптов и дизайн кадров на основе сценария. Детальная проработка переднего, среднего и заднего планов, движений персонажей, реквизита и композиции — готовая раскадровка становится точным планом для производства видео. + +- ✅ **Синтез видео** + Интеграция современных ИИ-технологий для генерации изображений и видеоклипов. Встроенный онлайн-редактор позволяет гибко настраивать результат, делая процесс создания видео быстрым, удобным и плавным. --- -# 📦 Области применения +# 📦 Сценарии использования -- Создание коротких видео-контента -- Эксперименты по экранизации романов -- Инструмент AI для литературных адаптаций -- Разработка сценариев и быстрые прототипы -- Генерация видеоматериалов +- Создание контента для коротких видео (Shorts, Reels, TikTok) +- Экранизация и визуализация новелл +- ИИ-инструмент для адаптации литературных произведений +- Разработка сценариев и быстрое прототипирование +- Генерация видеоматериалов и футажей --- # 🔰 Руководство пользователя -## 📺 Видеоруководство +## 📺 Видеоуроки -https://www.bilibili.com/video/BV1na6wB6Ea2 -[![Toonflow — Быстрый старт с AI-видео за 8 минут](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) +[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2) +[![Toonflow: Быстрый старт за 8 минут](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) -**Toonflow: 8 минут до полного освоения AI-видео** -👉 [Смотреть видео](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) +**Toonflow: Быстрый старт в AI-видео за 8 минут** +👉 [Нажмите для просмотра](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) -📱 Сканируйте WeChat QR-код для просмотра на телефоне +📱 Отсканируйте QR-код для просмотра видео на телефоне -微信扫码观看 +Сканировать QR-код для просмотра видео --- @@ -116,34 +121,34 @@ https://www.bilibili.com/video/BV1na6wB6Ea2 ## Предварительные требования -Перед установкой и использованием программы подготовьте следующее: +Перед установкой и использованием Toonflow подготовьте следующее: -- ✅ Адрес API сервиса языковой AI-модели -- ✅ Адрес API Sora или Doubao для видео -- ✅ Адрес API сервиса модели Nano Banana Pro для генерации изображений +- ✅ URL API для LLM (большой языковой модели) +- ✅ URL API для генерации видео (Sora или Doubao) +- ✅ URL API для генерации изображений (Nano Banana Pro) -## Установка локально +## Локальная установка (на ПК) ### 1. Скачивание и установка -| Операционная система | GitHub | Atomgit | Скачать из Quark Net Disk | Описание | -| :------------------: | :---------------------------------------------------------- | :------------------------------------------------------------- | :-------------------------------------------------- | :------------------ | -| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Net Disk](https://pan.quark.cn/s/94ef07509df0) | Официальный установочный пакет | -| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Net Disk](https://pan.quark.cn/s/94ef07509df0) | Официальный установочный пакет | -| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Net Disk](https://pan.quark.cn/s/94ef07509df0) | Официальный установочный пакет | +| ОС | GitHub | Atomgit | Скачать (Quark Drive) | Описание | +| :------: | :----------------------------------------------------------- | :------------------------------------------------------------ | :---------------------------------------------- | :------------- | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Официальный установщик | +| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Официальный установщик | +| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Официальный установщик | > [!CAUTION] -> Для macOS: откройте "Настройки → Конфиденциальность и безопасность" и настройте параметры безопасности, иначе может не открыться из-за проблемы с сертификатом. +> Пользователям macOS необходимо перейти в **Системные настройки → Конфиденциальность и безопасность** и разрешить запуск приложения. В противном случае программа может не открыться из-за проблем с сертификатом. > -> См. на Zhihu: [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) +> Подробнее (на китайском): [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) -> Из-за ограничений Gitee OS и лимита по размеру файлов Release — отдельная ссылка для загрузки с Gitee временно недоступна. +> Из-за технических ограничений Gitee Release (размер файлов и окружение) ссылки для скачивания на Gitee временно недоступны. ### 2. Запуск сервиса -После установки запустите приложение для начала работы. +После завершения установки просто откройте программу Toonflow — сервис будет готов к работе. -> ⚠️ **Первый вход** +> ⚠️ **Данные для первого входа** > Логин: `admin` > Пароль: `admin123` @@ -151,56 +156,59 @@ https://www.bilibili.com/video/BV1na6wB6Ea2 ### Предварительные требования -- Установлен [Docker](https://docs.docker.com/get-docker/) (версия 20.10+) +- Установлен [Docker](https://docs.docker.com/get-docker/) версии 20.10 или выше ### Способ 1: Онлайн-развертывание -В разработке — пока используйте локальную сборку. +В настоящее время в стадии разработки. +Рекомендуется использовать локальную сборку. ### Способ 2: Локальная сборка -Собирается локально из скачанного репозитория, подходит для разработчиков либо скачавших код через git: +Сборка проекта непосредственно из исходного кода на вашем компьютере. +Подходит для разработчиков и пользователей, которые уже клонировали репозиторий. Требуется установленная система контроля версий Git: ```shell -# Клонировать проект (если уже есть — пропустите) +# Сначала клонируйте проект (пропустите, если уже сделано) git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app -# Запускаем сборку и запуск с помощью docker-compose +# Локальная сборка и запуск с помощью docker-compose yarn docker:local -# Или вручную +# Или ручная сборка docker build -t toonflow . -docker run -d -p <локальный_порт>:10588 -v <путь_к_данным>:/app/data toonflow +docker run -d -p <локальный_порт>:10588 -v <путь_к_локальным_данным>:/app/data toonflow -# Доступ по адресу: http://localhost:10588/web/index.html +# После этого интерфейс будет доступен по пути /web/index.html на указанном порту +# Пример: http://localhost:10588/web/index.html ``` -### Описание портов +### Описание портов сервиса -| Порт | Назначение | Мэппинг в контейнере | -| -------- | ------------- | ---------------------------- | -| `10588` | Web-интерфейс | `10588:10588` | +| Порт | Назначение | Маппинг | +| ------- | --------------------------- | ---------------- | +| `10588` | Основной порт сервиса (API) | `10588:10588` | -**Переменные окружения:** +**Переменные окружения (Environment Variables):** -| Переменная | Описание | -| ------------ | --------------------------------------- | -| `NODE_ENV` | Среда запуска, `prod` — продуктивная | -| `PORT` | Порт службы (по умолчанию 10588) | -| `OSSURL` | Доступ к хранилищу файлов, для статики | +| Переменная | Описание | +| ---------- | ----------------------------------------------------- | +| `NODE_ENV` | Среда выполнения (`prod` = Production) | +| `PORT` | Порт сервиса (по умолчанию 10588) | +| `OSSURL` | Адрес Object Storage для хранения и отдачи статических файлов | --- -## Развёртывание в облаке +## Облачное развертывание / Установка на сервер -### 1. Требования к серверу +### I. Требования к серверу -- **ОС**: Ubuntu 20.04+ / CentOS 7+ -- **Node.js**: 24.x (рекомендуется; минимум 23.11.1+) -- **ОЗУ**: от 2 ГБ +- **Операционная система**: Ubuntu 20.04+ / CentOS 7+ +- **Node.js**: 24.x (рекомендуется, минимум 23.11.1+) +- **ОЗУ**: 2 ГБ и более -### 2. Развёртывание на сервере +### II. Развертывание #### 1. Установка окружения @@ -213,9 +221,9 @@ nvm install 24 npm install -g yarn pm2 ``` -#### 2. Развёртывание проекта +#### 2. Загрузка и сборка проекта -**Клонировать из GitHub:** +**Клонирование с GitHub:** ```bash cd /opt @@ -225,7 +233,7 @@ yarn install yarn build ``` -**Клонировать из Gitee (для пользователей из Китая):** +**Клонирование с Gitee (рекомендуется для Китая):** ```bash cd /opt @@ -253,13 +261,13 @@ yarn build } ``` -**Описание переменных:** +**Переменные окружения (Environment Variables):** -| Переменная | Описание | -| ------------ | --------------------------------| -| `NODE_ENV` | Среда запуска, `prod` — продакшн | -| `PORT` | Слушаемый порт | -| `OSSURL` | Адрес доступа к статике | +| Переменная | Описание | +| ---------- | ----------------------------------------------------- | +| `NODE_ENV` | Среда выполнения (`prod` = Production) | +| `PORT` | Порт сервиса (по умолчанию 10588) | +| `OSSURL` | Адрес Object Storage для хранения и отдачи статических файлов | --- @@ -276,57 +284,58 @@ pm2 save ```bash pm2 list # Список процессов pm2 logs toonflow-app # Просмотр логов -pm2 restart all # Перезапуск сервиса -pm2 monit # Мониторинг +pm2 restart all # Перезапуск сервисов +pm2 monit # Панель мониторинга ``` -> ⚠️ **Первый вход** +> ⚠️ **Данные для первого входа** > Логин: `admin` > Пароль: `admin123` -#### 6. Развёртывание фронта +#### 6. Развертывание Frontend -Если нужна кастомизация интерфейса или отдельное развертывание фронта — используйте репозиторий фронтенда: +Если вам нужно отдельно развернуть или кастомизировать фронтенд, перейдите в репозиторий Toonflow-web: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -> 💡 **Примечание:** В этот репозиторий уже встроен скомпилированный фронт. Обычным пользователям отдельная установка канала не требуется. Фронт-репозиторий — только для тех, кто хочет разрабатывать/модифицировать UI. +> 💡 **Примечание**: Этот репозиторий уже содержит скомпилированные файлы Frontend. Обычным пользователям не требуется отдельно устанавливать фронтенд. Репозиторий Toonflow-web предназначен только для разработчиков, которые хотят внести изменения или доработать интерфейс. --- -# 🔧 Руководство по процессу разработки +# 🔧 Руководство разработчика > [!CAUTION] -> 🚧 **Правила по PR** 🚧 +> 🚧 **Правила отправки Pull Request** 🚧 > -> ⛔ В `master` запрещены любые PR | ✅ Создавайте PR только в ветку `develop` +> ⛔ **Ветка `master` не принимает PR** | ✅ **Отправляйте все PR в ветку `develop`** > -> Разработчиков приглашаем к со-разработке Toonflow! Для участия пишите главному админу ACT в группу. +> Приглашаем всех желающих разработчиков присоединиться к развитию Toonflow. +> Если вы хотите участвовать, свяжитесь с куратором проекта ACT в нашей группе сообщества. -## 🛠️ Технологический стек +## 🛠️ Стек технологий -| Категория | Технологии | -| ------------ | ------------------------------------------------------------------------------------------------------------------- | -| Рантайм | Node.js 23.11.1+ | -| Язык | TypeScript 5.x | -| Бэкенд | Express 5 | -| БД | SQLite (better-sqlite3 / knex) | -| AI-интеграции| Vercel AI SDK (OpenAI / Anthropic / Google / DeepSeek / Zhihu / MiniMax / Tongyi Qianwen / xAI) | -| Локальный AI | @huggingface/transformers (ONNX) | -| RTC | Socket.IO | -| Десктоп-клиент| Electron 40 | -| Графика | Sharp | -| Контейнеризация| Docker | +| Категория | Технология | +|------------------------|-----------------------------------------------------------------------------------------| +| Runtime | Node.js 23.11.1+ | +| Язык | TypeScript 5.x | +| Backend-фреймворк | Express 5 | +| База данных | SQLite (better-sqlite3 / knex) | +| Интеграция ИИ | Vercel AI SDK (OpenAI / Anthropic / Google / DeepSeek / Zhipu / MiniMax / Qwen / xAI) | +| Локальный инференс | @huggingface/transformers (ONNX) | +| Real-time связь | Socket.IO | +| Desktop-клиент | Electron 40 | +| Обработка изображений | Sharp | +| Контейнеризация | Docker | ## Подготовка среды разработки -- **Node.js**: не ниже 23.11.1 -- **Yarn**: рекомендуется менеджер пакетов +- **Node.js**: версия 23.11.1 и выше +- **Yarn**: рекомендуется использовать в качестве пакетного менеджера -## Быстрый старт проекта +## Быстрый запуск проекта -1. **Клонируйте проект** +1. **Клонирование проекта** **С GitHub:** @@ -342,9 +351,9 @@ pm2 monit # Мониторинг cd Toonflow-app ``` -2. **Установите зависимости** +2. **Установка зависимостей** - В корне проекта выполните: + Выполните следующую команду в корневой папке проекта: ```bash yarn install @@ -352,203 +361,209 @@ pm2 monit # Мониторинг 3. **Запуск среды разработки** - Проект состоит из backend API и frontend. Возможные варианты запуска: + Проект состоит из **Backend API** и **Frontend страниц**. Выберите нужный способ запуска: - - **1: Только backend** + - **Способ 1: Запуск только Backend** ```bash yarn dev ``` - > ⚠️ Запускает только backend API (порт 10588); без интерфейса. Для доступа к UI — используйте отдельный frontend проект или запускайте через GUI-модули ниже. + > ⚠️ Эта команда запускает **только Backend API** (порт 10588) **без интерфейса Frontend**. + > При переходе по адресу `http://localhost:10588` вы сможете только обращаться к API. Полноценный графический интерфейс отображаться не будет. + > Чтобы работать с UI, запустите Frontend отдельно или используйте режим GUI (см. ниже). - - **2: Electron-desktop-клиент** + - **Способ 2: Запуск клиента Electron (GUI)** ```bash yarn dev:gui ``` - > Открывает backend и Electron GUI-окно — всё встроено, без доп. настроек. Рекомендуется для полноценного использования. + > Эта команда одновременно запускает Backend и десктопное приложение Electron со встроенным Frontend. + > Программа готова к работе сразу после запуска, без дополнительных настроек. + > Идеально подходит для разработчиков, которые хотят быстро протестировать весь функционал приложения. - - **3: Режим продакшн** + - **Способ 3: Запуск в режиме Production** ```bash yarn start ``` - > Запуск производственной сборки (предварительно `yarn build` обязателен). + > Запуск скомпилированного сервиса в режиме Production (сначала необходимо выполнить `yarn build`). -4. **Сборка проекта** +4. **Сборка проекта (Build & Package)** - - Компиляция .ts файлов: + - Компиляция и генерация TypeScript: ```bash yarn build ``` - - Сборка exe для Windows: + - Сборка исполняемого файла для Windows: ```bash yarn dist:win ``` - - Сборка для Mac: + - Сборка исполняемого файла для Mac: ```bash yarn dist:mac ``` - - Сборка для Linux: + - Сборка исполняемого файла для Linux: ```bash yarn dist:linux ``` -5. **Lint и проверка кода** +5. **Проверка качества кода (Linting)** - - Проверка кода на ошибки и стиль: + - Запуск глобальной проверки синтаксиса: ```bash yarn lint ``` -6. **AI Debug-панель (по желанию)** +6. **Панель отладки AI (Опционально)** - Запуск GUI для отладки AI SDK: + Запуск визуального инструмента отладки AI SDK: ```bash yarn debug:ai ``` -## Фронтенд разработка +## Разработка Frontend -Для редактирования интерфейса используйте фронт-репозиторий: +Если вам нужно внести изменения в пользовательский интерфейс, перейдите в репозиторий фронтенда: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -После сборки фронта (`dist/`) скопируйте его содержимое в `data/web/` основного проекта. +После сборки (build) фронтенда скопируйте всю папку `dist` в директорию `data/web` этого проекта для интеграции. ## Структура проекта ``` -📂 build/ # Скомпилированные файлы -📂 data/ # Данные во время работы -│ ├─ 📂 models/ # Локальные AI-модели (ONNX) -│ ├─ 📂 oss/ # Объектное хранилище (ассеты/персонажи/сцены) -│ ├─ 📂 serve/ # Вход в проде -│ ├─ 📂 skills/ # Prompt-словари умений Agent -│ └─ 📂 web/ # Скомпилированный фронтенд (встроен) -📂 docs/ # Документация -📂 env/ # Переменные окружения -📂 scripts/ # Скрипты и утилиты +📂 build/ # Артефакты сборки +📂 data/ # Данные времени выполнения (Runtime) +│ ├─ 📂 models/ # Локальные модели (ONNX) +│ ├─ 📂 oss/ # Object Storage (изображения, персонажи, сцены) +│ ├─ 📂 serve/ # Точка входа в Production-режим +│ ├─ 📂 skills/ # Промпты навыков Agent +│ └─ 📂 web/ # Скомпилированный Frontend (встроен в проект) +📂 docs/ # Документация и ресурсы +📂 env/ # Конфигурации окружения +📂 scripts/ # Скрипты сборки и вспомогательные скрипты 📂 src/ -├─ 📂 agents/ # AI agent-модули -│ ├─ 📂 productionAgent/ # Агент генерации -│ └─ 📂 scriptAgent/ # Агент сценария -├─ 📂 lib/ # Общие библиотеки -├─ 📂 middleware/ # Мидлвари -├─ 📂 routes/ # Роутинг модули -│ ├─ 📂 agents/ # Память агента -│ ├─ 📂 artStyle/ # Управление стилями -│ ├─ 📂 assets/ # Ассеты -│ ├─ 📂 assetsGenerate/ # Генерация ассетов -│ ├─ 📂 cornerScape/ # Раскадровка -│ ├─ 📂 general/ # Общие эндпоинты -│ ├─ 📂 login/ # Авторизация -│ ├─ 📂 migrate/ # Миграции -│ ├─ 📂 modelSelect/ # Выбор модели -│ ├─ 📂 novel/ # Управление романами -│ ├─ 📂 other/ # Другое -│ ├─ 📂 production/ # Управление производством -│ ├─ 📂 project/ # Управление проектом -│ ├─ 📂 script/ # Генерация сценария -│ ├─ 📂 scriptAgent/ # Эндпоинты агента сценария -│ ├─ 📂 setting/ # Настройки системы -│ ├─ 📂 task/ # Задачи -│ └─ 📂 test/ # Тестовые эндпоинты -├─ 📂 socket/ # RealTime WebSocket -├─ 📂 types/ # TypeScript типы -├─ 📂 utils/ # Утилиты -├─ 📄 app.ts # Точка входа -├─ 📄 core.ts # Инициализация ядра -├─ 📄 env.ts # Работа с окружением -├─ 📄 err.ts # Обработка ошибок -├─ 📄 logger.ts # Модуль логгирования -├─ 📄 router.ts # Регистрация роутов -└─ 📄 utils.ts # Вспомогательные функции -📄 Dockerfile # Dockerfile -📄 electron-builder.yml # Конфиг Electron Builder +├─ 📂 agents/ # Модули AI Agent +│ ├─ 📂 productionAgent/ # Production Agent (агент производства) +│ └─ 📂 scriptAgent/ # Script Agent (агент сценариев) +├─ 📂 lib/ # Общие библиотеки (инициализация БД, форматы ответов) +├─ 📂 middleware/ # Middleware +├─ 📂 routes/ # Модули маршрутизации +│ ├─ 📂 agents/ # Управление памятью Agent +│ ├─ 📂 artStyle/ # Управление художественными стилями +│ ├─ 📂 assets/ # Управление ассетами +│ ├─ 📂 assetsGenerate/ # Генерация ассетов +│ ├─ 📂 cornerScape/ # Управление раскадровкой (Storyboard) +│ ├─ 📂 general/ # Общие API +│ ├─ 📂 login/ # Аутентификация +│ ├─ 📂 migrate/ # Миграция данных +│ ├─ 📂 modelSelect/ # Выбор моделей +│ ├─ 📂 novel/ # Управление новеллами +│ ├─ 📂 other/ # Прочие функции +│ ├─ 📂 production/ # Управление производством и монтажом +│ ├─ 📂 project/ # Управление проектами +│ ├─ 📂 script/ # Генерация сценариев +│ ├─ 📂 scriptAgent/ # Интерфейс Script Agent +│ ├─ 📂 setting/ # Системные настройки +│ ├─ 📂 task/ # Управление задачами +│ └─ 📂 test/ # Тестовые API +├─ 📂 socket/ # Real-time коммуникация через WebSocket +├─ 📂 types/ # Типы TypeScript +├─ 📂 utils/ # Вспомогательные утилиты +├─ 📄 app.ts # Точка входа приложения (App Entry) +├─ 📄 core.ts # Инициализация ядра системы +├─ 📄 env.ts # Обработка переменных окружения +├─ 📄 err.ts # Обработка ошибок +├─ 📄 logger.ts # Модуль логирования +├─ 📄 router.ts # Регистрация маршрутов +└─ 📄 utils.ts # Общие утилиты +📄 Dockerfile # Файл для сборки Docker +📄 electron-builder.yml # Конфигурация сборки Electron 📄 skillList.json # Список навыков 📄 LICENSE # Лицензия (Apache-2.0) -📄 NOTICES.txt # Информация о сторонних зависимостях -📄 package.json # Конфиг пакетов -📄 tsconfig.json # Конфиг TypeScript +📄 NOTICES.txt # Уведомления о сторонних зависимостях +📄 package.json # Конфигурация проекта +📄 tsconfig.json # Конфигурация TypeScript ``` --- # 🔗 Связанные репозитории -| Репозиторий | Описание | GitHub | Gitee | -| ---------------- | ------------------------------------- | -------------------------------------------------- | ------------------------------------------------ | -| **Toonflow-app** | Полный клиент (этот, для обычных пользователей) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | -| **Toonflow-web** | Исходный код фронта (для фронтэндеров) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | +| Репозиторий | Описание | GitHub | Gitee | +|------------------|---------------------------------------------------------------|----------------------------------------------------|--------------------------------------------------| +| **Toonflow-app** | Полноценный клиент (этот репозиторий, рекомендуется для большинства пользователей) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | Исходный код Frontend (для frontend-разработчиков) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | -> 💡 **Подсказка:** если вы просто хотите пользоваться Toonflow — скачайте этот клиент. Отдельный frontend нужен только разработчикам UI. +> 💡 **Совет**: Если вы просто хотите использовать Toonflow, достаточно скачать клиент из этого репозитория. Репозиторий Toonflow-web предназначен только для разработчиков, желающих внести изменения или доработать интерфейс. --- -# 👨‍👩‍👧‍👦 WeChat-группы +# 👨‍👩‍👧‍👦 Discord сообщество -Ассистент по добавлению в группу: +Нажмите на иконку ниже, чтобы присоединиться к Discord: -Toonflow QR +[![Join our Discord](https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/67d00cf7266d2c75571aebde_Example.svg)](https://discord.gg/HEjKmpNpAZ) + +Или перейдите по прямой ссылке: [https://discord.gg/HEjKmpNpAZ](https://discord.gg/HEjKmpNpAZ) --- -# 💌 Обратная связь +# 💌 Свяжитесь с нами -📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow咨询) +📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Запрос%20Toonflow) --- # 📜 Лицензия -Toonflow распространяется по лицензии Apache-2.0 с дополнительным коммерческим соглашением. +Toonflow распространяется как open-source проект под лицензией Apache-2.0 с дополнительным коммерческим соглашением. -Подробности: https://www.apache.org/licenses/LICENSE-2.0 +Подробнее о лицензии Apache-2.0: https://www.apache.org/licenses/LICENSE-2.0 -## Дополнительное соглашение +## Дополнительное коммерческое соглашение -- Если вы распространяете данное ПО как продукт **2 и более независимым третьим сторонам**, необходимо получить **письменную коммерческую лицензию** от HBAI-Ltd. -- **≤ 5 юридических лиц**, совместно использующих ПО для внутренних нужд без предоставления услуг третьим сторонам — это **внутреннее использование, лицензия не требуется**. -- Запрещено удалять или изменять товарные знаки, логотипы или уведомления об авторских правах Toonflow. +- Если данное ПО распространяется в виде продукта для **2 и более независимых третьих лиц**, необходимо получить **письменную коммерческую лицензию** от HBAI-Ltd. +- Если ПО используется совместно **не более чем 5 юридическими лицами** только для внутренних нужд (без оказания услуг внешним пользователям), это считается внутренним использованием и **лицензия не требуется**. +- Запрещается удалять или изменять логотипы и информацию об авторских правах в Toonflow. -## Всегда бесплатно — без лицензии +## Сценарии бессрочного бесплатного использования -- ✅ Создание контента в Toonflow и получение дохода на платформах -- ✅ Доработка для внутреннего использования команды -- ✅ ≤ 5 юрлиц — совместная внутренняя эксплуатация -- ✅ Личное обучение, исследования, некоммерческое использование +- ✅ Создание контента с помощью Toonflow и монетизация через видеоплатформы +- ✅ Вторичная разработка (secondary development) для внутреннего использования команды +- ✅ Совместное использование группой из ≤ 5 юридических лиц только внутри организации +- ✅ Личное обучение, научные исследования и любые некоммерческие цели -## Цены на коммерческую лицензию +## Тарифы коммерческой лицензии -| Этап | Годовой оборот | Годовая плата | -|------|---------|------| -| 🌱 Старт | < ¥100 тыс. | **Бесплатно** | -| 🚀 Стартап | ¥100–500 тыс. | ¥5 000/год | -| 📈 Рост | ¥500 тыс.–1,5 млн | ¥20 000/год | -| 🏢 Масштаб | ¥1,5–5 млн | ¥80 000/год | -| 🌐 Корпоративный | > ¥5 млн | По договорённости | +| Стадия | Годовая выручка | Годовой взнос | +|---------------------|-----------------------------|-----------------------| +| 🌱 Старт / Поддержка | < ¥100 000 RMB | **Бесплатно** | +| 🚀 Стартап | ¥100 000 – 500 000 RMB | ¥5,000 / год | +| 📈 Рост | ¥500 000 – 1 500 000 RMB | ¥20,000 / год | +| 🏢 Масштабирование | ¥1 500 000 – 5 000 000 RMB | ¥80,000 / год | +| 🌐 Корпоративный | > ¥5 000 000 RMB | Договорная цена | -> **Условие отсутствия обратной силы**: Пользователи, использовавшие Toonflow по AGPL-3.0 до релиза v1.0.8, продолжают работу по AGPL-3.0 и не затрагиваются данным изменением. +> **Оговорка о необратной силе**: Пользователи, которые использовали Toonflow под лицензией AGPL-3.0 до выхода версии v1.0.8, продолжают работать по правилам AGPL-3.0. Изменения данного соглашения на них не распространяются. -Полный текст соглашения см. в файле [LICENSE](../LICENSE). +Полный текст соглашения доступен в файле [LICENSE](./LICENSE). --- -# ⭐️ История звёзд +# ⭐️ История звезд (Star History) [![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left)](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left) @@ -556,32 +571,32 @@ Toonflow распространяется по лицензии Apache-2.0 с д # 🙏 Благодарности -Спасибо нижеперечисленным open-source проектам за мощную поддержку Toonflow: +Выражаем благодарность следующим open-source проектам за мощную поддержку Toonflow: -- [Express](https://expressjs.com/) — быстрый, открытый и лёгкий фреймворк для Node.js -- [AI SDK](https://ai-sdk.dev/) — инструменты AI для TypeScript -- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) — высокопроизводительная обвязка SQLite3 -- [Sharp](https://sharp.pixelplumbing.com/) — быстрая библиотека для работы с изображениями на Node.js -- [Axios](https://axios-http.com/) — HTTP-клиент на промисах -- [Zod](https://zod.dev/) — TS-first валидация схем -- [Socket.IO](https://socket.io/) — обмен событиями в реальном времени -- [Electron](https://www.electronjs.org/) — кроссплатформенный desktop-фреймворк -- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) — фреймворк для локального ML +- [Express](https://expressjs.com/) - Быстрый, гибкий и минималистичный веб-фреймворк для Node.js +- [AI SDK](https://ai-sdk.dev/) - AI инструментарий для TypeScript +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - Библиотека с высокой производительностью для SQLite3 +- [Sharp](https://sharp.pixelplumbing.com/) - Высокопроизводительная библиотека Node.js для обработки изображений +- [Axios](https://axios-http.com/) - Promise-based HTTP клиент +- [Zod](https://zod.dev/) - Библиотека валидации схем, ориентированная на TypeScript +- [Socket.IO](https://socket.io/) - Движок для двунаправленной real-time связи на основе событий +- [Electron](https://www.electronjs.org/) - Фреймворк для кроссплатформенных десктоп-приложений +- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - Библиотека для локального ML инференса -Спасибо за поддержку проекту Toonflow от следующих организаций: +Спасибо следующим организациям/лицам за поддержку Toonflow:
- 算能云 Logo + Sophnet Logo - Sophnet Cloud — спонсор вычислительных ресурсов - [сайт] + Sophnet (算能云) Спонсор вычислительных мощностей + [Сайт]
-Полный список сторонних зависимостей — в файле `NOTICES.txt` +Полный список зависимостей третьих сторон находится в файле `NOTICES.txt`. -##### copyright © 淮北艾阿网络科技有限公司 \ No newline at end of file +##### copyright © Huaibei AIA Network Technology Co., Ltd. \ No newline at end of file diff --git a/docs/README.th.md b/docs/README.th.md index 9b2c0a4..d14814a 100644 --- a/docs/README.th.md +++ b/docs/README.th.md @@ -1,4 +1,4 @@ -

+

GitHub @@ -8,13 +8,12 @@  |  - Atomgit - Atomgit + Atomgit

- 简体中文 | + 简体中文 | 繁體中文 | English | ไทย | @@ -31,11 +30,11 @@

- โรงงานละครสั้น AI + โรงงานผลิตภาพยนตร์สั้น AI
- แตะเพียงครั้งเดียว นิยายกลายเป็นตอนทันที! + เพียงคลิกไม่กี่ครั้ง นิยายก็กลายเป็นภาพยนตร์ได้ในพริบตา!
- สคริปต์ AI × ภาพ AI × สร้างเร็วสายฟ้าแลบ 🔥 + บทภาพยนตร์ AI × ภาพ AI × สร้างวิดีโอความเร็วสูง 🔥

@@ -50,14 +49,14 @@

- > 🚀 **ผลิตละครสั้นครบวงจร:** จากข้อความสู่นักแสดง จากสตอรี่บอร์ดสู่วิดีโอ AI แบบเต็มกระบวนการ ทุกขั้นตอน ไม่มีอุปสรรค ประสิทธิภาพสร้าง 10 เท่าขึ้นไป! +> 🚀 **สตูดิโอภาพยนตร์สั้น All-in-One**: จากข้อความสู่ตัวละคร จากสตอรี่บอร์ดสู่ภาพยนตร์ ใช้ AI อัตโนมัติทั้งกระบวนการ ไม่ต้องมีพื้นฐานใด ๆ เพิ่มประสิทธิภาพการสร้างสรรค์มากกว่า 10 เท่า! --- -# � รองรับหลายภาษา +# 🌐 การรองรับหลายภาษา -Toonflow รองรับภาษาในอินเทอร์เฟซดังนี้: +Toonflow รองรับอินเทอร์เฟซภาษาดังต่อไปนี้: | ภาษา | Language | |------|----------| @@ -69,139 +68,144 @@ Toonflow รองรับภาษาในอินเทอร์เฟซ | 日本語 | Japanese | | Русский | Russian | +> 💡 กำลังเพิ่มการรองรับภาษาอื่นๆ ยินดีต้อนรับผู้ที่ต้องการช่วยแปล! + --- # 🌟 ฟีเจอร์หลัก -Toonflow คือเครื่องมือคอมิกละครสั้น AI ที่ใช้เทคโนโลยี AI แปลงนิยายเป็นสคริปต์โดยอัตโนมัติ และใช้ภาพและวิดีโอ AI เพื่อสร้างละครสั้นได้อย่างมีประสิทธิภาพ ด้วย Toonflow คุณสามารถสร้างผลงานจากข้อความสู่ภาพนิ่งจนถึงวิดีโอ ได้อย่างชาญฉลาดและสะดวก +Toonflow เป็นเครื่องมือ AI สำหรับสร้างภาพยนตร์สั้นและการ์ตูน ที่สามารถแปลงนิยายเป็นภาพยนตร์ได้โดยอัตโนมัติ ด้วยการผสานเทคโนโลยี AI ในการสร้างตัวละคร บทภาพยนตร์ ภาพประกอบ และวิดีโอ ทำให้กระบวนการผลิตภาพยนตร์สั้นมีประสิทธิภาพสูง ด้วย Toonflow คุณสามารถจัดการทุกขั้นตอนตั้งแต่ข้อความต้นฉบับจนถึงวิดีโอสำเร็จรูปได้อย่างง่ายดาย ทำให้การผลิตภาพยนตร์สั้นฉลาด สะดวก และรวดเร็วยิ่งขึ้น - ✅ **สร้างตัวละครอัตโนมัติ** - วิเคราะห์เนื้อหานิยายต้นฉบับ ระบุและสร้างข้อมูลตัวละครอย่างชาญฉลาด ทั้งรูปร่าง นิสัย ตัวตน เป็นต้น สร้างพื้นฐานที่แข็งแรงสำหรับสคริปต์และภาพในขั้นถัดไป -- ✅ **สร้างสคริปต์อัตโนมัติ** - จากเหตุการณ์และบทที่เลือก ระบบจะสร้างสคริปต์เชิงโครงสร้างอัตโนมัติ ครอบคลุมบทสนทนา คำบรรยายฉาก และทิศทางเนื้อเรื่อง เปลี่ยนข้อความวรรณกรรมเป็นสคริปต์ละครได้อย่างรวดเร็ว -- ✅ **ผลิตสตอรี่บอร์ดอัตโนมัติ** - ตามสคริปต์ สร้างพรอมต์สตอรี่บอร์ดและงานออกแบบภาพอัตโนมัติ รายละเอียดองค์ประกอบหน้า/กลาง/หลัง การเคลื่อนไหวตัวละคร อุปกรณ์ประกอบฉาก และการจัดวางฉาก พลิกสคริปต์เป็นสตอรี่บอร์ดวางแผนผลิตวิดีโอได้ครบถ้วน -- ✅ **ประกอบวิดีโอด้วย AI** - ผนวกเทคโนโลยีภาพและวิดีโอ AI สร้างคลิปวิดีโอด้วย AI รวมฟีเจอร์แก้ไขออนไลน์ รองรับการตั้งค่าผลลัพธ์ที่ปรับแต่งได้ ทำให้การสร้างภาพยนตร์/ละครมีประสิทธิภาพและทำงานร่วมทีมได้ + วิเคราะห์ข้อความจากนิยายต้นฉบับโดยอัตโนมัติ ระบุและสร้างโปรไฟล์ตัวละครอย่างชาญฉลาด รวมถึงรูปร่างหน้าตา นิสัย ตัวตน และรายละเอียดอื่น ๆ เพื่อสร้างพื้นฐานที่แข็งแรงสำหรับบทภาพยนตร์และภาพในขั้นตอนต่อไป + +- ✅ **สร้างบทภาพยนตร์** + จากเหตุการณ์และบท (Chapter) ที่เลือก ระบบจะสร้างบทภาพยนตร์ที่มีโครงสร้างชัดเจน ประกอบด้วยบทสนทนา คำอธิบายฉาก และทิศทางเรื่องราว ช่วยแปลงงานวรรณกรรมเป็นบทภาพยนตร์ได้อย่างมีประสิทธิภาพ + +- ✅ **สร้างสตอรี่บอร์ด (Storyboard)** + จากบทภาพยนตร์ ระบบจะสร้างพรอมต์และออกแบบเฟรมภาพสตอรี่บอร์ดโดยอัตโนมัติ โดยระบุรายละเอียดฉากหน้า ฉากกลาง ฉากหลัง การเคลื่อนไหวของตัวละคร พร็อพ และการจัดวางฉาก เพื่อสร้างแผนการผลิตวิดีโอที่สมบูรณ์ + +- ✅ **สังเคราะห์และตัดต่อวิดีโอ** + ใช้เทคโนโลยี AI สร้างคลิปวิดีโอคุณภาพสูง รองรับระบบตัดต่อออนไลน์ที่สามารถปรับแต่งได้ตามต้องการ ช่วยให้กระบวนการสร้างภาพยนตร์สั้นเป็นไปอย่างราบรื่นและรวดเร็ว --- -# 📦 ตัวอย่างการใช้งาน +# 📦 รูปแบบการใช้งาน (Use Cases) -- สร้างวิดีโอละครสั้น -- ทดลองแปลงนิยายสู่ภาพยนตร์/ละคร -- เครื่องมือดัดแปลงวรรณกรรมด้วย AI -- การพัฒนาสคริปต์และต้นแบบผลิตงานเร็ว -- สร้างวัตถุดิบประกอบวิดีโอ +- สร้างคอนเทนต์วิดีโอสั้น +- ทดลองแปลงนิยายเป็นภาพยนตร์สั้น +- เครื่องมือ AI ในการดัดแปลงวรรณกรรมเป็นภาพยนตร์ +- พัฒนาบทภาพยนตร์และสร้างต้นแบบ (Rapid Prototyping) อย่างรวดเร็ว +- สร้างฟุตเทจและวัสดุวิดีโอคุณภาพสูง ---- +# 🔰 คู่มือการใช้งาน -# 🔰 คู่มือผู้ใช้ +## 📺 วิดีโอสอนการใช้งาน -## 📺 วิดีโอสอนใช้งาน +[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2) +[![เริ่มต้นสร้างวิดีโอ AI กับ Toonflow ใน 8 นาที](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) -https://www.bilibili.com/video/BV1na6wB6Ea2 -[![Toonflow 8-Minute Quick Start AI Video](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) - -**วิดีโอแนะนำ Toonflow ฉบับเร่งด่วน 8 นาที** +**เริ่มต้นสร้างวิดีโอ AI กับ Toonflow ใน 8 นาที** 👉 [คลิกเพื่อรับชม](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) -📱 สแกนด้วย WeChat บนมือถือเพื่อชม +📱 **สแกน QR Code เพื่อรับชมวิดีโอบนมือถือ** -Scan WeChat to Watch +สแกน QR Code เพื่อรับชมวิดีโอ --- # 🚀 การติดตั้ง -## สิ่งที่ต้องเตรียมก่อน +## ข้อกำหนดเบื้องต้น -ก่อนติดตั้งและใช้งานซอฟต์แวร์นี้ กรุณาเตรียมสิ่งเหล่านี้: +ก่อนติดตั้งและใช้งาน Toonflow โปรดเตรียมข้อมูลต่อไปนี้ให้พร้อม: -- ✅ ที่อยู่ API บริการ AI แบบ Large Language Model -- ✅ ที่อยู่ API บริการวิดีโอ Sora หรือ Doubao -- ✅ ที่อยู่ API โมเดลสร้างภาพ Nano Banana Pro +- ✅ ที่อยู่ API ของโมเดลภาษาขนาดใหญ่ (LLM) +- ✅ ที่อยู่ API ของบริการสร้างวิดีโอ (Sora หรือ Doubao) +- ✅ ที่อยู่ API ของโมเดลสร้างภาพ Nano Banana Pro -## ติดตั้งในเครื่อง (Local Installation) +## การติดตั้งบนเครื่อง (Local) ### 1. ดาวน์โหลดและติดตั้ง -| ระบบปฏิบัติการ | GitHub | Atomgit | ดาวน์โหลดผ่าน Quark Netdisk | หมายเหตุ | -| :------------: | :------------------------------------------------------- | :---------------------------------------------------- | :--------------------------------------------------- | :---------------------- | -| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Netdisk](https://pan.quark.cn/s/94ef07509df0) | แพ็กเกจติดตั้งอย่างเป็นทางการ | -| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Netdisk](https://pan.quark.cn/s/94ef07509df0) | แพ็กเกจติดตั้งอย่างเป็นทางการ | -| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Netdisk](https://pan.quark.cn/s/94ef07509df0) | แพ็กเกจติดตั้งอย่างเป็นทางการ | +| ระบบปฏิบัติการ | GitHub | Atomgit | ดาวน์โหลดผ่าน Quark Drive | คำอธิบาย | +| :------: | :----------------------------------------------------------- | :------------------------------------------------------------ | :---------------------------------------------- | :------------- | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | ตัวติดตั้งอย่างเป็นทางการ | +| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | ตัวติดตั้งอย่างเป็นทางการ | +| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | ตัวติดตั้งอย่างเป็นทางการ | > [!CAUTION] -> บน MacOS ให้ไปที่ ตั้งค่า - ความเป็นส่วนตัวและความปลอดภัย ตั้งค่าความปลอดภัยก่อน มิฉะนั้นอาจไม่สามารถเปิดแอปได้เพราะปัญหาใบรับรอง +> สำหรับระบบ macOS โปรดไปที่ **การตั้งค่า > ความเป็นส่วนตัวและความปลอดภัย** เพื่ออนุญาตให้แอปพลิเคชันทำงาน มิฉะนั้นอาจเปิดโปรแกรมไม่ได้เนื่องจากปัญหาใบรับรองความปลอดภัย > -> ดูเอกสารฉบับภาษาจีน: [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) +> อ้างอิงเอกสารจาก Zhihu: [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) -> ด้วยข้อจำกัดของสภาพแวดล้อม Gitee OS และขนาดไฟล์ Release การดาวน์โหลดผ่าน Gitee Release ยังไม่เปิดให้บริการในขณะนี้ +> เนื่องจากข้อจำกัดเรื่องสภาพแวดล้อมระบบและขนาดไฟล์ของ Gitee Release ปัจจุบันจึงยังไม่มีลิงก์ดาวน์โหลดบน Gitee -### 2. เปิดใช้งานโปรแกรม +### 2. เริ่มการทำงาน -ติดตั้งเสร็จแล้วให้เปิดโปรแกรมเพื่อเริ่มใช้งาน +หลังจากติดตั้งเสร็จสิ้น เพียงเปิดโปรแกรม Toonflow ก็สามารถเริ่มใช้งานได้ทันที -> ⚠️ **ล็อกอินครั้งแรก** +> ⚠️ **เข้าสู่ระบบครั้งแรก** > ชื่อผู้ใช้: `admin` > รหัสผ่าน: `admin123` -## การใช้ Docker +## การใช้งานผ่าน Docker -### สิ่งที่ต้องเตรียม +### ข้อกำหนดเบื้องต้น -- ติดตั้ง [Docker](https://docs.docker.com/get-docker/) (เวอร์ชัน 20.10+) +- ติดตั้ง [Docker](https://docs.docker.com/get-docker/) เวอร์ชัน 20.10 ขึ้นไป เรียบร้อยแล้ว -### วิธีที่ 1: ติดตั้งออนไลน์ +### วิธีที่ 1: การติดตั้งออนไลน์ -กำลังพัฒนา; ขณะนี้ให้ใช้การ build ในเครื่อง +กำลังพัฒนา +ปัจจุบันแนะนำให้ใช้วิธี Build บนเครื่องก่อน -### วิธีที่ 2: สร้างเองในเครื่อง +### วิธีที่ 2: การ Build บนเครื่อง -สำหรับนักพัฒนา หรือผู้ที่ clone repo แล้ว ต้องติดตั้ง Git ที่เครื่อง +ใช้วิธี Build จากซอร์สโค้ดที่มีอยู่ในเครื่องโดยตรง +เหมาะสำหรับนักพัฒนาหรือผู้ใช้ที่โคลน Repository มาแล้ว (ต้องติดตั้ง Git บนเครื่องก่อน) ```shell -# clone โปรเจกต์ (ถ้าทำแล้วข้าม) +# โคลนโปรเจกต์ก่อน (ข้ามขั้นตอนนี้ถ้ามีอยู่แล้ว) git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app -# สร้างและเริ่มผ่าน docker-compose +# ใช้ docker-compose ในการ Build และรันบนเครื่อง yarn docker:local -# หรือสร้างแบบ manual +# หรือทำการ Build แบบแมนนวล docker build -t toonflow . -docker run -d -p :10588 -v :/app/data toonflow +docker run -d -p <พอร์ตบนเครื่อง>:10588 -v <พาธข้อมูลบนเครื่อง>:/app/data toonflow -# ใช้งานที่ /web/index.html ในพอร์ตที่แม็ปไว้ เช่น -# http://localhost:10588/web/index.html +# จากนั้นสามารถเข้าถึงหน้าเว็บผ่านพอร์ตที่ระบุ ที่พาธ /web/index.html +# ตัวอย่าง: http://localhost:10588/web/index.html ``` -### รายละเอียดพอร์ตบริการ +### คำอธิบายพอร์ตบริการ -| พอร์ต | วัตถุประสงค์ | Mapping ในการติดตั้ง | -| -------- | ------------ | -------------------- | -| `10588` | ส่วนติดต่อแอป | `10588:10588` | +| พอร์ต | การใช้งาน | การจับคู่พอร์ต (Mapping) | +| ------- | ---------------------- | ------------------------ | +| `10588` | พอร์ตบริการหลัก (API) | `10588:10588` | -**รายละเอียดตัวแปรแวดล้อม:** +**คำอธิบายตัวแปรสภาพแวดล้อม (Environment Variables):** -| ตัวแปร | รายละเอียด | -| ------------- | ----------------------------------------- | -| `NODE_ENV` | สภาพแวดล้อม เลือก `prod` คือ production | -| `PORT` | พอร์ตการฟังบริการ (ค่าเริ่มต้น 10588) | -| `OSSURL` | ที่อยู่สำหรับเข้าถึงไฟล์ static | +| ตัวแปร | คำอธิบาย | +| ---------- | ----------------------------------------------------- | +| `NODE_ENV` | สภาพแวดล้อมการทำงาน (`prod` = Production) | +| `PORT` | พอร์ตสำหรับให้บริการ (ค่าเริ่มต้น 10588) | +| `OSSURL` | ที่อยู่ OSS สำหรับเก็บและโหลดไฟล์สาธารณะ (Static files) | --- -## ติดตั้งบน Cloud +## การติดตั้งบนคลาวด์ / เซิร์ฟเวอร์ -### 1. ข้อกำหนดเครื่องเซิร์ฟเวอร์ +### 1. ข้อกำหนดสภาพแวดล้อมเซิร์ฟเวอร์ -- **ระบบปฏิบัติการ:** Ubuntu 20.04+ / CentOS 7+ -- **Node.js:** 24.x (แนะนำ ขั้นต่ำ 23.11.1+) -- **RAM:** 2GB ขึ้นไป +- **ระบบปฏิบัติการ**: Ubuntu 20.04+ / CentOS 7+ +- **Node.js**: 24.x (แนะนำ, ขั้นต่ำ 23.11.1+) +- **RAM**: 2GB+ -### 2. วิธีติดตั้ง +### 2. การติดตั้งบนเซิร์ฟเวอร์ #### 1. ติดตั้งสภาพแวดล้อม @@ -214,9 +218,9 @@ nvm install 24 npm install -g yarn pm2 ``` -#### 2. ติดตั้งโปรเจกต์ +#### 2. ดึงโค้ดโปรเจกต์ -**Clone จาก GitHub:** +**โคลนจาก GitHub:** ```bash cd /opt @@ -226,7 +230,7 @@ yarn install yarn build ``` -**Clone จาก Gitee (แนะนำในจีนแผ่นดินใหญ่):** +**โคลนจาก Gitee (แนะนำสำหรับประเทศจีน):** ```bash cd /opt @@ -254,17 +258,17 @@ yarn build } ``` -**รายละเอียดตัวแปรแวดล้อม:** +**คำอธิบายตัวแปรสภาพแวดล้อม (Environment Variables):** -| ตัวแปร | รายละเอียด | -| ------------- | ---------------------------------------- | -| `NODE_ENV` | สภาพแวดล้อม เลือก `prod` คือ production | -| `PORT` | พอร์ตให้บริการ | -| `OSSURL` | ที่อยู่สำหรับเข้าถึงไฟล์ static | +| ตัวแปร | คำอธิบาย | +| ---------- | ----------------------------------------------------- | +| `NODE_ENV` | สภาพแวดล้อมการทำงาน (`prod` = Production) | +| `PORT` | พอร์ตสำหรับให้บริการ (ค่าเริ่มต้น 10588) | +| `OSSURL` | ที่อยู่ OSS สำหรับเก็บและโหลดไฟล์สาธารณะ (Static files) | --- -#### 4. เริ่มบริการ +#### 4. เริ่มการทำงาน ```bash pm2 start pm2.json @@ -275,281 +279,290 @@ pm2 save #### 5. คำสั่งที่ใช้บ่อย ```bash -pm2 list # ดูรายชื่อโปรเซส -pm2 logs toonflow-app # ดู Log -pm2 restart all # รีสตาร์ทบริการ -pm2 monit # ดูระบบแบบเรียลไทม์ +pm2 list # ดู Process ทั้งหมด +pm2 logs toonflow-app # ดู Logs +pm2 restart all # รีสตาร์ทเซอร์วิส +pm2 monit # เปิดหน้าต่าง Monitoring ``` -> ⚠️ **ล็อกอินครั้งแรก** +> ⚠️ **เข้าสู่ระบบครั้งแรก** > ชื่อผู้ใช้: `admin` > รหัสผ่าน: `admin123` -#### 6. ติดตั้งส่วนหน้าเว็บไซต์ +#### 6. การติดตั้งเว็บไซต์ฟรอนต์เอนด์ (Frontend) -ถ้าต้องการใช้ Frontend แยก หรือปรับแต่ UI ศึกษาที่ repo ส่วน frontend: +หากต้องการติดตั้งหรือปรับแต่งอินเทอร์เฟซฟรอนต์เอนด์แยกต่างหาก โปรดอ้างอิง Repository ฟรอนต์เอนด์ดังนี้: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -> 💡 **หมายเหตุ:** รีโปนี้ใส่ frontend ที่ compile แล้วมาด้วย ผู้ใช้ทั่วไปไม่จำเป็นต้องติดตั้ง frontend แยก Repo frontend ใช้สำหรับนักพัฒนาที่ต้องการพัฒนาต่อ +> 💡 **หมายเหตุ**: Repository นี้มาพร้อมไฟล์ฟรอนต์เอนด์ที่คอมไพล์เสร็จสมบูรณ์แล้ว +> ผู้ใช้ทั่วไปไม่จำเป็นต้องติดตั้งฟรอนต์เอนด์แยก Repository นี้มีไว้สำหรับนักพัฒนาที่ต้องการปรับแต่งหรือพัฒนาเพิ่มเติมเท่านั้น --- -# 🔧 คู่มือนักพัฒนา +# 🔧 คู่มือสำหรับนักพัฒนา (Development Workflow Guide) > [!CAUTION] -> 🚧 **แนวทางการส่ง PR** 🚧 +> 🚧 **ข้อบังคับในการส่ง Pull Request** 🚧 > -> ⛔ `master` ไม่รับ PR | ✅ ส่ง PR ที่ `develop` +> ⛔ **ไม่รับ PR ใน branch `master`**|✅ **โปรดส่ง PR ไปที่ branch `develop`** > -> เชิญนักพัฒนาร่วมพัฒนา Toonflow ติดต่อเจ้าของ ACT ในแชทกลุ่ม +> ยินดีต้อนรับนักพัฒนาทุกท่านที่สนใจร่วมพัฒนา Toonflow +> หากต้องการเข้าร่วม โปรดติดต่อผู้ดูแลโปรเจกต์ (ACT) ในกลุ่มพูดคุย -## 🛠️ Tech Stack +## 🛠️ เทคโนโลยีที่ใช้ (Tech Stack) -| หมวด | เทคโนโลยี | -| ------------ | ------------------------------------------------------------------------------------ | -| Runtime | Node.js 23.11.1+ | -| Language | TypeScript 5.x | -| Backend | Express 5 | -| Database | SQLite (better-sqlite3 / knex) | -| AI Integration | Vercel AI SDK (OpenAI / Anthropic / Google / DeepSeek / Zhipu / MiniMax / Qwen / xAI) | -| Local Inference | @huggingface/transformers (ONNX) | -| Real-Time | Socket.IO | -| Desktop | Electron 40 | -| Image Proc. | Sharp | -| Container | Docker | +| ประเภท | เทคโนโลยี | +| ---------- | ----------------------------------------------------------------------------------------- | +| Runtime | Node.js 23.11.1+ | +| Language | TypeScript 5.x | +| Backend | Express 5 | +| Database | SQLite (better-sqlite3 / knex) | +| AI Integ. | Vercel AI SDK (OpenAI / Anthropic / Google / DeepSeek / Zhipu / MiniMax / Qwen / xAI) | +| Local Inf. | @huggingface/transformers (ONNX) | +| Real-time | Socket.IO | +| Desktop | Electron 40 | +| Image Proc.| Sharp | +| Container | Docker | -## เตรียมสภาพแวดล้อม +## การเตรียมสภาพแวดล้อมการพัฒนา -- **Node.js:** ต้องใช้ 23.11.1 ขึ้นไปเท่านั้น -- **Yarn:** แนะนำให้ใช้เป็น package manager +- **Node.js**: ต้องใช้เวอร์ชัน 23.11.1 ขึ้นไป +- **Yarn**: แนะนำให้ใช้เป็น Package Manager -## เริ่มพัฒนาอย่างรวดเร็ว +## การเริ่มโปรเจกต์อย่างรวดเร็ว -1. **Clone โปรเจกต์** +1. **โคลนโปรเจกต์** - **GitHub:** + **โคลนจาก GitHub:** ```bash git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` - **Gitee (ในจีนแผ่นดินใหญ่แนะนำ):** + **โคลนจาก Gitee (แนะนำสำหรับประเทศจีน):** ```bash git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` -2. **ติดตั้ง dependencies** +2. **ติดตั้ง Dependencies** - รันที่ root directory: + ให้รันคำสั่งด้านล่างนี้ใน root ของโปรเจกต์เพื่อติดตั้ง Dependencies: ```bash yarn install ``` -3. **เริ่มสภาพแวดล้อมพัฒนา** +3. **เริ่มใช้งานในโหมด Development** - โปรเจกต์นี้มี **backend API service** และ **frontend interface** เลือกวิธีเริ่มต้นได้: + โปรเจกต์นี้ประกอบด้วย **บริการ Backend API** และ **หน้า Frontend** คุณสามารถเลือกวิธีการเปิดใช้งานได้ตามต้องการ: - - **ตัวเลือก 1: เริ่ม backend อย่างเดียว** + - **วิธีที่ 1: รันเฉพาะ Backend อย่างเดียว** ```bash yarn dev ``` - > ⚠️ คำสั่งนี้เปิดเฉพาะ backend API (พอร์ต 10588) **ไม่มี web UI** การเข้า http://localhost:10588 คือเรียก API เท่านั้น การใช้ web UI เต็มรูปแบบใช้วิธีด้านล่าง + > ⚠️ คำสั่งนี้จะรัน **เฉพาะ Backend API** (พอร์ต 10588) **โดยไม่มีหน้า Frontend** + > เมื่อเข้าถึง `http://localhost:10588` จะสามารถเรียกใช้งาน API ได้เท่านั้น + > หากต้องการใช้งานพร้อมกับหน้าเว็บ Frontend โปรดรัน Frontend แยกต่างหาก หรือใช้โหมด GUI ด้านล่างนี้ - - **ตัวเลือก 2: เริ่ม Electron desktop client** + - **วิธีที่ 2: รัน Electron Desktop Client** ```bash yarn dev:gui ``` - > คำสั่งนี้เปิดทั้ง backend และ Electron window มี web UI built-in พร้อมใช้งาน + > คำสั่งนี้จะรันทั้ง Backend และหน้าต่าง Electron Desktop พร้อมกัน โดยมี Frontend ฝังมาในตัว + > โปรแกรมพร้อมใช้งานทันทีโดยไม่ต้องตั้งค่าเพิ่มเติม + > เหมาะสำหรับนักพัฒนาที่ต้องการทดสอบฟีเจอร์ทั้งหมดของแอปพลิเคชัน - - **ตัวเลือก 3: โหมด production** + - **วิธีที่ 3: รันโหมด Production** ```bash yarn start ``` - > รันทั้ง backend แบบโปรดักชั่น (ต้อง `yarn build` ก่อน) + > รันโปรแกรมในโหมด Production ทันทีหลังจากที่คอมไพล์เสร็จ (ต้องรัน `yarn build` ก่อน) -4. **คอมไพล์โปรเจกต์** +4. **การแพ็คโปรเจกต์ (Build/Dist)** - - คอมไพล์ TypeScript: + - คอมไพล์และสร้างไฟล์ TypeScript: ```bash yarn build ``` - - สร้าง executable สำหรับ Windows: + - แพ็คโปรเจกต์เป็นไฟล์รัน (Executable) สำหรับ Windows: ```bash yarn dist:win ``` - - สร้าง executable สำหรับ Mac: + - แพ็คโปรเจกต์สำหรับ macOS: ```bash yarn dist:mac ``` - - สร้าง executable สำหรับ Linux: + - แพ็คโปรเจกต์สำหรับ Linux: ```bash yarn dist:linux ``` -5. **ตรวจสอบคุณภาพโค้ด** +5. **ตรวจสอบคุณภาพโค้ด (Lint)** - - เช็ค lint: + - ทำการตรวจสอบไวยากรณ์และข้อกำหนดโค้ด (Linting) ทั้งหมด: ```bash yarn lint ``` -6. **AI Debug panel (ไม่บังคับ)** +6. **แผงควบคุมดีบัก AI (ตัวเลือก)** - รัน Visual Debugging Tool ของ Vercel AI SDK เพื่อ debug integration AI ได้ง่ายขึ้น: + เปิดใช้งานเครื่องมือดีบักแบบ Visual ของ AI SDK เพื่อความสะดวกในการดีบักการเรียกใช้ AI: ```bash yarn debug:ai ``` -## การพัฒนา Frontend +## การพัฒนาฟรอนต์เอนด์ (Frontend) -หากต้องการพัฒนา UI แก้ไขที่ frontend repo: +หากต้องการแก้ไขหรือพัฒนาอินเทอร์เฟซฟรอนต์เอนด์ โปรดไปที่ Repository ฟรอนต์เอนด์ดังนี้: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -หลัง build frontend แล้ว ให้นำไฟล์ใน `dist` ไปวางใน `data/web` ของโปรเจกต์นี้ +หลังจาก Build ฟรอนต์เอนด์เสร็จสิ้นแล้ว ให้คัดลอกโฟลเดอร์ `dist` ทั้งหมดไปวางในโฟลเดอร์ `data/web` ของโปรเจกต์นี้เพื่อทำการรวมเข้ากับระบบ ## โครงสร้างโปรเจกต์ ``` -📂 build/ # ผลลัพธ์หลังคอมไพล์ -📂 data/ # ข้อมูล runtime -│ ├─ 📂 models/ # โมเดล inference ในเครื่อง (ONNX) -│ ├─ 📂 oss/ # ที่เก็บวัตถุ (assets/character/scene) -│ ├─ 📂 serve/ # จุดเริ่ม production -│ ├─ 📂 skills/ # เอเจนท์พรอมต์ทักษะต่างๆ -│ └─ 📂 web/ # asset frontend ที่มาในตัว -📂 ./ # เอกสาร -📂 env/ # ไฟล์ config environment -📂 scripts/ # script สร้างและช่วยงาน +📂 build/ # ผลลัพธ์หลัง Build +📂 data/ # ข้อมูล Runtime +│ ├─ 📂 models/ # โมเดล Infer บนเครื่อง (ONNX) +│ ├─ 📂 oss/ # Object Storage (เก็บภาพ ตัวละคร และฉาก) +│ ├─ 📂 serve/ # จุดเข้าใช้งานโหมด Production +│ ├─ 📂 skills/ # Prompt ทักษะของ Agent +│ └─ 📂 web/ # Frontend ที่ Build แล้ว (ฝังมาในตัว) +📂 docs/ # เอกสารและรูปภาพคู่มือ +📂 env/ # การตั้งค่าสภาพแวดล้อม +📂 scripts/ # สคริปต์ช่วยเหลือและ Build 📂 src/ -├─ 📂 agents/ # โมดูล AI Agent ต่างๆ -│ ├─ 📂 productionAgent/ # เอเจนท์ผลิตงาน -│ └─ 📂 scriptAgent/ # เอเจนท์สคริปต์ -├─ 📂 lib/ # ไลบรารีทั่วไป (db, response) -├─ 📂 middleware/ # Middleware ต่างๆ -├─ 📂 routes/ # เส้นทาง API หลัก -│ ├─ 📂 agents/ # จัดการความจำเอเจนท์ -│ ├─ 📂 artStyle/ # จัดการสไตล์ศิลปะ -│ ├─ 📂 assets/ # จัดการ asset -│ ├─ 📂 assetsGenerate/ # สร้าง asset อัตโนมัติ -│ ├─ 📂 cornerScape/ # จัดการสตอรี่บอร์ด -│ ├─ 📂 general/ # API ทั่วไป -│ ├─ 📂 login/ # ยืนยันตัวตนเข้าใช้ -│ ├─ 📂 migrate/ # ย้ายโครงสร้างข้อมูล -│ ├─ 📂 modelSelect/ # จัดการเลือกโมเดล -│ ├─ 📂 novel/ # จัดการนิยาย -│ ├─ 📂 other/ # ฟีเจอร์อื่นๆ -│ ├─ 📂 production/ # จัดการการผลิต -│ ├─ 📂 project/ # จัดการโปรเจกต์ -│ ├─ 📂 script/ # สร้างสคริปต์ -│ ├─ 📂 scriptAgent/ # Endpoint AI Agent สคริปต์ -│ ├─ 📂 setting/ # ตั้งค่าระบบ -│ ├─ 📂 task/ # จัดการงาน -│ └─ 📂 test/ # ทดสอบ API -├─ 📂 socket/ # การสื่อสาร WebSocket -├─ 📂 types/ # TypeScript type definitions -├─ 📂 utils/ # ฟังก์ชันอรรถประโยชน์ -├─ 📄 app.ts # จุดเข้าแอป -├─ 📄 core.ts # core initialization -├─ 📄 env.ts # ตัวแปร env -├─ 📄 err.ts # จัดการ error -├─ 📄 logger.ts # log โมดูล -├─ 📄 router.ts # ลงทะเบียน route ต่าง ๆ -└─ 📄 utils.ts # เครื่องมือทั่วไป -📄 Dockerfile # config สำหรับ docker build -📄 electron-builder.yml # config แพ็ค Electron +├─ 📂 agents/ # โมดูล AI Agent +│ ├─ 📂 productionAgent/ # Agent ฝ่ายผลิต (Production) +│ └─ 📂 scriptAgent/ # Agent ฝ่ายบทภาพยนตร์ (Script) +├─ 📂 lib/ # ไลบรารีส่วนกลาง (Init ฐานข้อมูล, รูปแบบ Response) +├─ 📂 middleware/ # Middleware +├─ 📂 routes/ # โมดูล Routing +│ ├─ 📂 agents/ # จัดการหน่วยความจำ Agent +│ ├─ 📂 artStyle/ # จัดการสไตล์ภาพศิลป์ +│ ├─ 📂 assets/ # จัดการ Asset +│ ├─ 📂 assetsGenerate/ # สร้าง Asset +│ ├─ 📂 cornerScape/ # จัดการสตอรี่บอร์ด (Storyboard) +│ ├─ 📂 general/ # API ทั่วไป +│ ├─ 📂 login/ # การยืนยันตัวตน +│ ├─ 📂 migrate/ # Migration ข้อมูล +│ ├─ 📂 modelSelect/ # เลือกโมเดล +│ ├─ 📂 novel/ # จัดการนวนิยายต้นฉบับ +│ ├─ 📂 other/ # ฟังก์ชันอื่น ๆ +│ ├─ 📂 production/ # จัดการการผลิต/ตัดต่อ +│ ├─ 📂 project/ # จัดการโปรเจกต์ +│ ├─ 📂 script/ # สร้างบทภาพยนตร์ +│ ├─ 📂 scriptAgent/ # Interface ของ Script Agent +│ ├─ 📂 setting/ # ตั้งค่าระบบ +│ ├─ 📂 task/ # จัดการ Task +│ └─ 📂 test/ # API ทดสอบ +├─ 📂 socket/ # การสื่อสารเรียลไทม์ผ่าน WebSocket +├─ 📂 types/ # ประกาศ TypeScript Types +├─ 📂 utils/ # ฟังก์ชันยูทิลิตี้ +├─ 📄 app.ts # จุดเริ่มต้นของแอปพลิเคชัน (App Entry) +├─ 📄 core.ts # เริ่มต้น Core ระบบ +├─ 📄 env.ts # จัดการตัวแปร Environment +├─ 📄 err.ts # จัดการ Error +├─ 📄 logger.ts # โมดูล Logger +├─ 📄 router.ts # ลงทะเบียน Router +└─ 📄 utils.ts # ฟังก์ชันอรรถประโยชน์ทั่วไป +📄 Dockerfile # ไฟล์สร้าง Docker +📄 electron-builder.yml # การตั้งค่าการแพ็ค Electron 📄 skillList.json # รายการทักษะ -📄 LICENSE # ใบอนุญาต Apache-2.0 -📄 NOTICES.txt # รายงานไลบรารีที่ใช้ -📄 package.json # config โปรเจกต์ -📄 tsconfig.json # TypeScript config +📄 LICENSE # สัญญาอนุญาต (Apache-2.0) +📄 NOTICES.txt # ประกาศไลบรารี Third-party +📄 package.json # การตั้งค่าโปรเจกต์ +📄 tsconfig.json # การตั้งค่า TypeScript ``` --- -# 🔗 รีโพที่เกี่ยวข้อง +# 🔗 Repository ที่เกี่ยวข้อง -| รีโพ | คำอธิบาย | GitHub | Gitee | -| ------------ | ----------------- | ----------------------------------------------- | -------------------------------------------- | -| **Toonflow-app** | ตัวเต็ม (รีโปนี้, สำหรับผู้ใช้) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | -| **Toonflow-web** | ซอร์ส frontend (สำหรับ dev FE) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | +| Repository | คำอธิบาย | GitHub | Gitee | +| ---------------- | --------------------------------------------- | -------------------------------------------------- | ------------------------------------------------ | +| **Toonflow-app** | ไคลเอนต์แบบสมบูรณ์ (Repository นี้ แนะนำสำหรับผู้ใช้ทั่วไป) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | ซอร์สโค้ดฟรอนต์เอนด์ (เหมาะสำหรับนักพัฒนาฟรอนต์เอนด์) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | -> 💡 **หมายเหตุ:** ถ้าแค่ต้องการใช้งาน ดาวน์โหลดไคลเอนต์จากรีโปนี้ได้เลย รีโป frontend เหมาะสำหรับ dev ที่จะพัฒนา UI ต่อ +> 💡 **เคล็ดลับ**: หากคุณต้องการใช้งาน Toonflow เพียงดาวน์โหลดไคลเอนต์จาก Repository นี้ก็เพียงพอแล้ว +> Repository Toonflow-web มีไว้สำหรับนักพัฒนาที่ต้องการปรับแต่งหรือพัฒนาต่อยอดอินเทอร์เฟซเท่านั้น --- -# 👨‍👩‍👧‍👦 กลุ่ม WeChat +# 👨‍👩‍👧‍👦 กลุ่ม Discord ชุมชน -ผู้ช่วยกลุ่ม: +คลิกที่ไอคอนด้านล่างเพื่อเข้าร่วม Discord: -Toonflow QR +[![Join our Discord](https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/67d00cf7266d2c75571aebde_Example.svg)](https://discord.gg/HEjKmpNpAZ) + +หรือคลิกลิงก์โดยตรง: [https://discord.gg/HEjKmpNpAZ](https://discord.gg/HEjKmpNpAZ) --- # 💌 ติดต่อเรา -📧 อีเมล: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow inquiry) +📧 อีเมล: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=สอบถาม%20เรื่อง%20Toonflow) --- -# 📜 ใบอนุญาต +# 📜 ใบอนุญาต (License) -Toonflow เป็นโอเพ่นซอร์สภายใต้ Apache-2.0 พร้อมข้อตกลงเชิงพาณิชย์เพิ่มเติม +Toonflow เปิดเผยเป็นโอเพ่นซอร์สภายใต้สัญญาอนุญาต Apache-2.0 พร้อมด้วยข้อตกลงเชิงพาณิชย์เพิ่มเติม -รายละเอียด: https://www.apache.org/licenses/LICENSE-2.0 +รายละเอียดสัญญา Apache-2.0: https://www.apache.org/licenses/LICENSE-2.0 -## ข้อตกลงเพิ่มเติม +## ข้อตกลงเชิงพาณิชย์เพิ่มเติม -- หากแจกจ่ายซอฟต์แวร์นี้ในฐานะผลิตภัณฑ์ให้ **บุคคลที่สามอิสระ 2 รายขึ้นไป** ต้องได้รับ **อนุญาตเชิงพาณิชย์เป็นลายลักษณ์อักษร** จาก HBAI-Ltd -- **≤ 5 นิติบุคคล** ร่วมดำเนินงานภายในโดยไม่ให้บริการภายนอก ถือเป็น **การใช้งานภายใน ไม่ต้องขออนุญาต** -- ห้ามลบหรือแก้ไขเครื่องหมายการค้า โลโก้ หรือข้อมูลลิขสิทธิ์ใน Toonflow +- หากนำซอฟต์แวร์นี้ไปเผยแพร่ในรูปแบบผลิตภัณฑ์ให้กับ **บุคคลที่สามอิสระตั้งแต่ 2 รายขึ้นไป** ต้องได้รับ **การอนุญาตเชิงพาณิชย์เป็นลายลักษณ์อักษร** จาก HBAI-Ltd +- หากใช้งานร่วมกันภายในโดย **นิติบุคคลไม่เกิน 5 ราย** และไม่ให้บริการแก่บุคคลภายนอก จะถือเป็นการใช้งานภายในและ **ไม่ต้องขออนุญาต** +- ห้ามลบหรือแก้ไขโลโก้หรือข้อมูลลิขสิทธิ์ภายใน Toonflow -## ใช้งานฟรีตลอดกาล +## กรณีใช้งานฟรีตลอดชีพ -- ✅ ใช้ Toonflow สร้างเนื้อหาและรับส่วนแบ่งรายได้จากแพลตฟอร์ม -- ✅ พัฒนาต่อยอดสำหรับทีมภายใน -- ✅ ≤ 5 นิติบุคคลร่วมดำเนินงานภายใน -- ✅ เรียนรู้ส่วนตัว วิจัย และใช้งานที่ไม่ใช่เชิงพาณิชย์ +- ✅ ใช้ Toonflow สร้างเนื้อหาเพื่อรับส่วนแบ่งรายได้จากแพลตฟอร์มวิดีโอ +- ✅ นำโค้ดไปพัฒนาต่อยอดเพื่อใช้งานภายในทีม +- ✅ ใช้งานร่วมกันภายในโดยนิติบุคคลไม่เกิน 5 ราย +- ✅ เพื่อการศึกษา การวิจัย และวัตถุประสงค์ที่ไม่ใช่เชิงพาณิชย์ -## ราคาใบอนุญาตเชิงพาณิชย์ +## โครงสร้างราคาการอนุญาตเชิงพาณิชย์ -| ระยะ | ยอดขายต่อปี | ค่าธรรมเนียมต่อปี | -|------|---------|------| -| 🌱 บ่มเพาะ | < ¥100,000 | **ฟรี** | -| 🚀 สตาร์ทอัพ | ¥100,000–500,000 | ¥5,000/ปี | -| 📈 เติบโต | ¥500,000–1,500,000 | ¥20,000/ปี | -| 🏢 ขยายตัว | ¥1,500,000–5,000,000 | ¥80,000/ปี | -| 🌐 องค์กร | > ¥5,000,000 | เจรจา | +| ระยะ | ยอดขายรายปี | ค่าธรรมเนียมรายปี | +|--------------|-----------------------------|-----------------------| +| 🌱 ช่วงเริ่มต้น (Incubation) | < ¥100,000 | **ฟรี** | +| 🚀 ช่วง startup | ¥100,000 – 500,000 | ¥5,000 / ปี | +| 📈 ช่วงเติบโต (Growth) | ¥500,000 – 1,500,000 | ¥20,000 / ปี | +| 🏢 ช่วงขยายขนาด (Scale) | ¥1,500,000 – 5,000,000 | ¥80,000 / ปี | +| 🌐 ระดับองค์กร (Enterprise) | > ¥5,000,000 | เจรจาต่อรอง | -> **เงื่อนไขไม่ย้อนหลัง**: ผู้ใช้ที่ใช้ Toonflow ภายใต้ AGPL-3.0 ก่อนการเผยแพร่ v1.0.8 จะไม่ได้รับผลกระทบจากการเปลี่ยนแปลงนี้ การใช้งานปัจจุบันยังคงเป็นไปตาม AGPL-3.0 +> **ข้อกำหนดไม่ย้อนหลัง (Non-Retroactivity)**: ผู้ใช้ที่เคยใช้งาน Toonflow ภายใต้สัญญา AGPL-3.0 ก่อนเวอร์ชัน v1.0.8 จะยังคงผูกพันตาม AGPL-3.0 ต่อไป และไม่ได้รับผลกระทบจากการเปลี่ยนแปลงข้อตกลงนี้ -ดูข้อตกลงฉบับเต็มที่ [LICENSE](../LICENSE) +ดูรายละเอียดข้อตกลงฉบับเต็มได้ที่ไฟล์ [LICENSE](./LICENSE) --- -# ⭐️ ประวัติการกดดาว +# ⭐️ ประวัติการให้ดาว (Star History) [![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left)](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left) @@ -557,32 +570,32 @@ Toonflow เป็นโอเพ่นซอร์สภายใต้ Apache- # 🙏 ขอขอบคุณ -ขอบคุณโอเพ่นซอร์สต่อไปนี้ที่สนับสนุน Toonflow: +ขอขอบคุณโปรเจกต์โอเพ่นซอร์สต่อไปนี้ที่ช่วยสนับสนุน Toonflow อย่างมาก: -- [Express](https://expressjs.com/) - เฟรมเวิร์ก Node.js ที่เร็ว เล็ก และเปิดกว้าง -- [AI SDK](https://ai-sdk.dev/) - ชุดเครื่องมือ AI-first สำหรับ TypeScript -- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - Binding SQLite3 ประสิทธิภาพสูง -- [Sharp](https://sharp.pixelplumbing.com/) - ไลบรารีจัดการภาพบน Node.js ประสิทธิภาพสูง -- [Axios](https://axios-http.com/) - HTTP client แบบ Promise -- [Zod](https://zod.dev/) - ไลบรารีตรวจสอบชนิด TypeScript เป็นหลัก -- [Socket.IO](https://socket.io/) - เฟรมเวิร์ก event bidirectional แบบเรียลไทม์ -- [Electron](https://www.electronjs.org/) - เฟรมเวิร์กสร้างแอปเดสก์ท็อปข้ามแพลตฟอร์ม -- [Hugging Face Transformers](https://huggingface.co./transformers.js) - ไลบรารี ML inference ในเครื่อง +- [Express](https://expressjs.com/) - Web Framework สำหรับ Node.js ที่รวดเร็ว เปิดกว้าง และใช้งานง่าย +- [AI SDK](https://ai-sdk.dev/) - ชุดเครื่องมือ AI สำหรับ TypeScript +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - ไลบรารี SQLite3 ประสิทธิภาพสูง +- [Sharp](https://sharp.pixelplumbing.com/) - ไลบรารีประมวลผลภาพบน Node.js ประสิทธิภาพสูง +- [Axios](https://axios-http.com/) - HTTP Client แบบ Promise-based +- [Zod](https://zod.dev/) - ไลบรารีตรวจสอบโครงสร้างข้อมูล (Schema Validation) สำหรับ TypeScript +- [Socket.IO](https://socket.io/) - เอนจินการสื่อสารเรียลไทม์แบบสองทาง +- [Electron](https://www.electronjs.org/) - เฟรมเวิร์กพัฒนาแอปพลิเคชันเดสก์ท็อปข้ามแพลตฟอร์ม +- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - ไลบรารี Machine Learning สำหรับการ Inference บนเครื่อง -ขอบคุณองค์กร/บุคคลต่อไปนี้สนับสนุน Toonflow: +ขอขอบคุณองค์กรและผู้สนับสนุนต่อไปนี้ที่ช่วยเหลือ Toonflow:
- SophNet Logo + Sophnet Logo - SophNet Cloud เป็นผู้สนับสนุนทรัพยากรการประมวลผล - [เว็บไซต์] + Sophnet (算能云) ให้การสนับสนุนด้านพลังการประมวลผล (Computing Power)
+ [เว็บไซต์ทางการ]
-รายชื่อไลบรารีภายนอกทั้งหมด ดูได้ที่ `NOTICES.txt` +รายการ Third-party Dependencies แบบสมบูรณ์ สามารถดูได้ที่ไฟล์ `NOTICES.txt` -##### copyright © 淮北艾阿网络科技有限公司 \ No newline at end of file +##### copyright © Huaibei AIA Network Technology Co., Ltd. \ No newline at end of file diff --git a/docs/README.vi.md b/docs/README.vi.md index e7bafcc..c2e2b36 100644 --- a/docs/README.vi.md +++ b/docs/README.vi.md @@ -8,13 +8,12 @@  |  - Atomgit - Atomgit + Atomgit

- 简体中文 | + 简体中文 | 繁體中文 | English | ไทย | @@ -31,11 +30,11 @@

- Xưởng sản xuất phim ngắn AI + Nhà máy Phim ngắn AI
- Động ngón tay là tiểu thuyết hóa thành phim ngay! + Chỉ với vài cú click, tiểu thuyết lập tức biến thành phim!
- Kịch bản AI × Hình ảnh AI × Tạo dựng thần tốc 🔥 + Kịch bản AI × Hình ảnh AI × Tạo siêu tốc 🔥

@@ -50,17 +49,17 @@

- > 🚀 **Công cụ sản xuất phim ngắn một cửa**: Từ văn bản tới nhân vật, từ dàn cảnh tới video, toàn bộ quy trình AI hóa không cần kỹ năng, tăng hiệu quả sáng tạo gấp 10 lần+! + > 🚀 **Dự án Phim ngắn All-in-One**: Từ văn bản đến nhân vật, từ storyboard đến video hoàn chỉnh. Tự động hóa toàn bộ quy trình bằng AI – không rào cản, tăng hiệu suất sáng tạo lên gấp 10 lần! --- -# 🌐 Hỗ trợ đa ngôn ngữ +# 🌐 Hỗ trợ Đa ngôn ngữ -Toonflow hỗ trợ các ngôn ngữ giao diện sau: +Toonflow hỗ trợ giao diện với các ngôn ngữ sau: | Ngôn ngữ | Language | -|-----------|----------| +|------|----------| | 简体中文 | Chinese (Simplified) | | 繁體中文 | Chinese (Traditional) | | English | English | @@ -69,46 +68,43 @@ Toonflow hỗ trợ các ngôn ngữ giao diện sau: | 日本語 | Japanese | | Русский | Russian | ---- - -# 🌟 Tính năng chính - -Toonflow là công cụ AI tạo phim truyện tranh ngắn, tận dụng công nghệ AI để chuyển tự động tiểu thuyết thành kịch bản, kết hợp hình ảnh, video AI để sáng tác phim ngắn hiệu quả. Với Toonflow, bạn dễ dàng hoàn thành toàn bộ quy trình từ văn bản tới hình ảnh, khiến chế tác phim ngắn trở nên thông minh và tiện lợi hơn bao giờ hết. - -- ✅ **Tạo nhân vật** - Phân tích tự động văn bản tiểu thuyết gốc, nhận diện thông minh và xây dựng thiết lập nhân vật, gồm ngoại hình, tính cách, thân phận,... cung cấp nền tảng chắc chắn cho sáng tác kịch bản và hình ảnh sau này. -- ✅ **Tạo kịch bản** - Dựa trên sự kiện và chương đã chọn, hệ thống tự động tạo kịch bản có cấu trúc gồm thoại, mô tả cảnh, diễn biến tình tiết, chuyển đổi hiệu quả từ văn học sang kịch bản truyền hình, điện ảnh. -- ✅ **Làm phân cảnh** - Theo nội dung kịch bản, tự động tạo từ khóa phân cảnh, thiết kế hình ảnh, chi tiết tiền trung hậu cảnh, động thái nhân vật, thiết lập đạo cụ và bố trí trường quay, tự động phân cảnh dựa trên kịch bản, tối ưu đường lối sản xuất video. -- ✅ **Tổng hợp video** - Tích hợp công nghệ tạo ảnh và video AI, dùng AI tạo phân đoạn video, biên tập trực tuyến, hỗ trợ điều chỉnh cá nhân hóa đầu ra, giúp sáng tác phim hiệu quả, triển khai nhanh. +> 💡 Đang cập nhật thêm nhiều ngôn ngữ, hoan nghênh bạn đóng góp bản dịch! --- -# 📦 Ứng dụng +# 🌟 Tính năng Chính -- Sáng tác nội dung video ngắn -- Thử nghiệm điện ảnh hóa tiểu thuyết -- Công cụ AI chuyển thể văn học -- Phát triển, dựng mẫu nhanh kịch bản -- Tạo nguyên liệu video +Toonflow là công cụ AI chuyên tạo phim ngắn và truyện tranh, có khả năng tự động biến tiểu thuyết thành phim chỉ trong một quy trình liền mạch. Từ văn bản gốc, AI sẽ tạo nhân vật, viết kịch bản, thiết kế phân cảnh và tổng hợp video hoàn chỉnh – giúp bạn sản xuất phim ngắn nhanh chóng, thông minh và tiết kiệm chi phí tối đa. + +- ✅ **Tạo Nhân vật Tự động** Hệ thống phân tích tiểu thuyết gốc, thông minh nhận diện và xây dựng hồ sơ nhân vật chi tiết (ngoại hình, tính cách, danh tính, mối quan hệ…). Tạo nền tảng vững chắc cho kịch bản và hình ảnh sau này. +- ✅ **Tạo Kịch bản Thông minh** Dựa trên các chương/sự kiện bạn chọn, AI tự động xây dựng kịch bản có cấu trúc rõ ràng, bao gồm hội thoại tự nhiên, mô tả cảnh quay và hướng phát triển cốt truyện – chuyển đổi văn học sang kịch bản phim một cách hiệu quả. +- ✅ **Tạo Phân cảnh (Storyboard)** Từ kịch bản, hệ thống tự động sinh ra các prompt phân cảnh và thiết kế khung hình chi tiết. Bao gồm tiền cảnh/trung cảnh/hậu cảnh, hành động nhân vật, đạo cụ và bố cục điện ảnh – tạo ra lộ trình hoàn chỉnh sẵn sàng cho việc sản xuất video. +- ✅ **Tổng hợp & Chỉnh sửa Video** Tích hợp công nghệ AI hình ảnh và video để tạo ra các đoạn clip chất lượng cao. Hỗ trợ chỉnh sửa trực tuyến linh hoạt, cho phép bạn tinh chỉnh theo ý muốn, giúp toàn bộ quy trình sáng tạo phim diễn ra mượt mà và cực kỳ nhanh chóng. --- -# 🔰 Hướng dẫn sử dụng +# 📦 Ứng dụng Thực tế -## 📺 Video hướng dẫn +- Sáng tạo nội dung video ngắn +- Thử nghiệm chuyển thể tiểu thuyết thành phim ngắn +- Công cụ AI chuyển thể văn học thành video +- Phát triển kịch bản và tạo bản mẫu nhanh (Rapid Prototyping) +- Tạo tài liệu video chất lượng cao -https://www.bilibili.com/video/BV1na6wB6Ea2 -[![Toonflow 8 phút nhanh chóng làm chủ AI Video](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) +--- -**Toonflow 8 phút nhanh chóng bắt đầu với AI Video** -👉 [Click xem tại đây](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) +# 🔰 Hướng dẫn Sử dụng -📱 Quét mã QR trên WeChat để xem trên điện thoại +## 📺 Hướng dẫn bằng Video -微信扫码观看 +[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2) +[![Toonflow - 8 phút làm quen với Video AI](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) + +**Toonflow - 8 phút làm quen nhanh với Video AI** +👉 [Nhấn để xem](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) + +📱 **Quét mã QR để xem video trên điện thoại** +Quét mã QR để xem video --- @@ -116,105 +112,105 @@ https://www.bilibili.com/video/BV1na6wB6Ea2 ## Điều kiện tiên quyết -Trước khi cài đặt và sử dụng, hãy chuẩn bị: +Trước khi cài đặt và sử dụng phần mềm, vui lòng chuẩn bị: -- ✅ Địa chỉ API dịch vụ mô hình ngôn ngữ lớn (AI) -- ✅ Địa chỉ API dịch vụ video Sora hoặc Đậu Bao -- ✅ Địa chỉ API dịch vụ tạo ảnh Nano Banana Pro +- ✅ Địa chỉ API của Mô hình ngôn ngữ lớn (LLM) +- ✅ Địa chỉ API của dịch vụ video Sora hoặc Doubao +- ✅ Địa chỉ API của dịch vụ tạo ảnh Nano Banana Pro -## Cài đặt tại máy +## Cài đặt trên máy cá nhân (Local) -### 1. Tải về & cài đặt +### 1. Tải xuống & Cài đặt -| Hệ điều hành | GitHub | Atomgit | Tải về trên Quark Drive | Ghi chú | -| :----------: | :------------------------------------------------------- | :----------------------------------------------------- | :--------------------------------------------------- | :-------------- | -| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Gói cài đặt chính thức | -| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Gói cài đặt chính thức | -| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Gói cài đặt chính thức | +| Hệ điều hành | GitHub | Atomgit | Tải qua Quark Drive | Mô tả | +| :------: | :----------------------------------------------------------- | :------------------------------------------------------------ | :---------------------------------------------- | :------------- | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Bản cài đặt chính thức | +| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Bản cài đặt chính thức | +| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [Quark Drive](https://pan.quark.cn/s/94ef07509df0) | Bản cài đặt chính thức | > [!CAUTION] -> Đối với MacOS, vào Cài đặt - Quyền riêng tư & Bảo mật để cấu hình, nếu không phần mềm có thể không mở được do vấn đề chứng chỉ +> Với hệ điều hành MacOS, vui lòng vào "Cài đặt hệ thống" -> "Quyền riêng tư & Bảo mật" để cấp quyền mở ứng dụng, nếu không phần mềm có thể không mở được do vấn đề chứng chỉ. > -> Tham khảo tài liệu Zhihu: [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) +> Tham khảo hướng dẫn Zhihu: [https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) -> Do hạn chế môi trường Gitee OS và kích thước upload Release, hiện chưa cung cấp đường dẫn tải Release tại Gitee. +> Do giới hạn môi trường Gitee OS và giới hạn kích thước tệp tải lên của Release, chúng tôi tạm thời không cung cấp link tải qua Gitee Release. -### 2. Khởi động dịch vụ +### 2. Khởi chạy Dịch vụ -Cài đặt xong, mở chương trình là có thể bắt đầu sử dụng. +Sau khi cài đặt xong, hãy mở chương trình để bắt đầu sử dụng. -> ⚠️ **Đăng nhập lần đầu** +> ⚠️ **Đăng nhập lần đầu** > Tài khoản: `admin` > Mật khẩu: `admin123` -## Triển khai Docker +## Triển khai bằng Docker -### Điều kiện +### Điều kiện tiên quyết -- Đã cài đặt [Docker](https://docs.docker.com/get-docker/) (version 20.10+) +- Đã cài đặt [Docker](https://docs.docker.com/get-docker/) (Phiên bản 20.10+) ### Cách 1: Triển khai trực tuyến -Đang hoàn thiện, tạm thời sử dụng build trên máy. +Đang hoàn thiện, tạm thời sử dụng cách Build tại máy (Local build). -### Cách 2: Build local +### Cách 2: Build tại máy (Local build) -Dùng mã nguồn sẵn có, phù hợp cho dev hoặc người đã clone repo, cần cài git trên máy: +Sử dụng mã nguồn có sẵn để build trực tiếp. Phù hợp với lập trình viên hoặc người dùng đã clone repository. (Yêu cầu cài đặt git trên máy): ```shell -# Clone nếu chưa có +# Clone dự án (Bỏ qua nếu đã clone) git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app -# Build và khởi động bằng docker-compose +# Sử dụng docker-compose để build và chạy yarn docker:local # Hoặc build thủ công docker build -t toonflow . -docker run -d -p :10588 -v <đường dẫn data>: /app/data toonflow +docker run -d -p :10588 -v <Đường dẫn dữ liệu trên máy>:/app/data toonflow -# Sau đó, truy cập trang qua /web/index.html trên cổng phù hợp -# Ví dụ http://localhost:10588/web/index.html +# Sau đó, truy cập giao diện qua đường dẫn /web/index.html bằng Port đã thiết lập +# Ví dụ: http://localhost:10588/web/index.html ``` -### Giải thích cổng dịch vụ +### Cấu hình Cổng dịch vụ (Port) -| Cổng | Mục đích | Mapping deploy | -| --------- | ------------- | ------------------- | -| `10588` | Giao diện | `10588:10588` | +| Cổng (Port) | Chức năng | Port Mapping | +| ------- | -------- | ------------- | +| `10588` | Giao diện phần mềm | `10588:10588` | -**Các biến môi trường:** +**Giải thích Biến môi trường:** -| Biến | Giải thích | -| ----------- | -------------------------------------- | -| `NODE_ENV` | Môi trường chạy, `prod` là production | -| `PORT` | Cổng dịch vụ (mặc định 10588) | -| `OSSURL` | Địa chỉ truy cập tệp tĩnh (OSS) | +| Biến (Variable) | Giải thích | +| ---------- | ---------------------------------- | +| `NODE_ENV` | Môi trường chạy, `prod` là môi trường Product (sản xuất) | +| `PORT` | Port lắng nghe của dịch vụ (Mặc định: 10588) | +| `OSSURL` | Địa chỉ truy cập lưu trữ file, dùng cho các tài nguyên tĩnh (Static) | --- -## Triển khai trên máy chủ +## Triển khai trên Máy chủ Đám mây (Cloud) -### A. Yêu cầu máy chủ +### 1. Yêu cầu Môi trường Máy chủ - **Hệ điều hành**: Ubuntu 20.04+ / CentOS 7+ -- **Node.js**: 24.x (khuyến nghị, tối thiểu 23.11.1+) +- **Node.js**: 24.x (Khuyên dùng, Tối thiểu 23.11.1+) - **RAM**: 2GB+ -### B. Triển khai +### 2. Triển khai Máy chủ -#### 1. Cài đặt môi trường +#### 1. Cài đặt Môi trường ```bash -# Cài Node.js +# Cài đặt Node.js curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 24 -# Cài Yarn & PM2 +# Cài đặt Yarn và PM2 npm install -g yarn pm2 ``` -#### 2. Triển khai dự án +#### 2. Triển khai Dự án **Clone từ GitHub:** @@ -226,7 +222,7 @@ yarn install yarn build ``` -**Clone từ Gitee (khuyên dùng tại VN):** +**Clone từ Gitee (Khuyên dùng tại TQ):** ```bash cd /opt @@ -238,7 +234,7 @@ yarn build #### 3. Cấu hình PM2 -Tạo file `pm2.json`: +Tạo tệp `pm2.json`: ```json { @@ -254,17 +250,17 @@ Tạo file `pm2.json`: } ``` -**Giải thích biến môi trường:** +**Giải thích Biến môi trường:** -| Biến | Giải thích | -| ----------- | -------------------------------------- | -| `NODE_ENV` | Môi trường chạy, `prod` là production | -| `PORT` | Cổng dịch vụ | -| `OSSURL` | Địa chỉ truy cập tài nguyên tĩnh | +| Biến (Variable) | Giải thích | +| ---------- | ---------------------------------- | +| `NODE_ENV` | Môi trường chạy, `prod` là môi trường Product | +| `PORT` | Cổng lắng nghe của dịch vụ (Port) | +| `OSSURL` | Địa chỉ truy cập lưu trữ file, dùng cho tài nguyên tĩnh | --- -#### 4. Khởi động dịch vụ +#### 4. Khởi chạy Dịch vụ ```bash pm2 start pm2.json @@ -272,150 +268,150 @@ pm2 startup pm2 save ``` -#### 5. Lệnh thường dùng +#### 5. Các lệnh PM2 thường dùng ```bash pm2 list # Xem danh sách tiến trình -pm2 logs toonflow-app # Xem logs +pm2 logs toonflow-app # Xem log (nhật ký) pm2 restart all # Khởi động lại dịch vụ -pm2 monit # Màn hình monitor +pm2 monit # Mở bảng điều khiển giám sát ``` -> ⚠️ **Đăng nhập lần đầu** +> ⚠️ **Đăng nhập lần đầu** > Tài khoản: `admin` > Mật khẩu: `admin123` -#### 6. Triển khai web frontend +#### 6. Triển khai trang web Frontend -Nếu cần deploy riêng hoặc custom giao diện, tham khảo mã nguồn frontend: +Nếu bạn cần triển khai riêng hoặc tùy chỉnh giao diện Frontend, vui lòng tham khảo Repository Frontend: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -> 💡 **Ghi chú**: Repo này đã chứa sẵn tài nguyên frontend được build, người dùng thông thường không cần deploy thêm phần giao diện, repo frontend chỉ dành cho dev muốn tùy biến sâu. +> 💡 **Lưu ý**: Repository này đã được tích hợp sẵn tài nguyên Frontend đã build. Người dùng thông thường không cần tự triển khai Frontend riêng. Repository Frontend chỉ dành cho các nhà phát triển muốn tùy chỉnh chuyên sâu. --- -# 🔧 Hướng dẫn quy trình phát triển +# 🔧 Hướng dẫn Quy trình Phát triển (Development Workflow) > [!CAUTION] -> 🚧 **Quy tắc gửi PR** 🚧 +> 🚧 **Quy định nộp PR (Pull Request)** 🚧 > -> ⛔ Không nhận PR gửi thẳng vào nhánh `master` | ✅ Gửi PR vào nhánh `develop` +> ⛔ Nhánh `master` KHÔNG chấp nhận bất kỳ PR nào | ✅ Vui lòng gửi PR vào nhánh `develop` > -> Chào mừng các dev cùng góp sức phát triển Toonflow. Muốn tham gia nhóm, liên hệ admin ACT trong group chat. +> Chào mừng các nhà phát triển tham gia đóng góp cho Toonflow. Nếu có hứng thú, vui lòng liên hệ với quản trị viên ACT trong nhóm giao lưu. -## 🛠️ Công nghệ sử dụng +## 🛠️ Công nghệ sử dụng (Tech Stack) -| Loại | Công nghệ | -| ---------- | --------------------------------------------------------------------------------------------- | -| Runtime | Node.js 23.11.1+ | -| Ngôn ngữ | TypeScript 5.x | -| Backend | Express 5 | -| Database | SQLite (better-sqlite3/knex) | -| Tích hợp AI| Vercel AI SDK (OpenAI/Anthropic/Google/DeepSeek/Zhipu/MiniMax/TongyiQianwen/xAI) | -| Suy luận local| @huggingface/transformers (ONNX) | -| Realtime | Socket.IO | -| Desktop | Electron 40 | -| Xử lý ảnh | Sharp | -| Container | Docker | +| Phân loại | Công nghệ | +| ---------- | ----------------------------------------------------------------------------------------- | +| Môi trường | Node.js 23.11.1+ | +| Ngôn ngữ | TypeScript 5.x | +| Backend | Express 5 | +| Cơ sở dữ liệu | SQLite (better-sqlite3 / knex) | +| Tích hợp AI| Vercel AI SDK (OpenAI / Anthropic / Google / DeepSeek / Zhipu / MiniMax / Qwen / xAI) | +| Suy luận Local| @huggingface/transformers (ONNX) | +| Real-time | Socket.IO | +| Ứng dụng Desktop | Electron 40 | +| Xử lý ảnh | Sharp | +| Container | Docker | -## Chuẩn bị môi trường phát triển +## Chuẩn bị Môi trường Phát triển -- **Node.js**: yêu cầu >= 23.11.1 -- **Yarn**: khuyến nghị quản lý package +- **Node.js**: Yêu cầu phiên bản 23.11.1 trở lên +- **Yarn**: Khuyến nghị sử dụng làm Package Manager -## Khởi động nhanh +## Khởi chạy Dự án nhanh 1. **Clone dự án** - **Từ GitHub:** + **Clone từ GitHub:** ```bash git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` - **Từ Gitee (khuyên dùng VN):** + **Clone từ Gitee:** ```bash git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` -2. **Cài dependency** +2. **Cài đặt Dependencies** - Chạy trong thư mục gốc: + Chạy lệnh sau tại thư mục gốc của dự án: ```bash yarn install ``` -3. **Khởi động môi trường dev** +3. **Khởi chạy môi trường Dev** - Dự án gồm 2 phần: **API backend** và **giao diện frontend**. Tuỳ bạn chọn cách chạy: + Dự án bao gồm **Backend API** và **Trang Frontend**. Tùy nhu cầu mà chọn cách khởi chạy: - - **Cách 1: Chạy chỉ API backend** + - **Cách 1: Chỉ chạy Backend API** ```bash yarn dev ``` - > ⚠️ Lệnh này chỉ khởi động API backend (port 10588), **không gồm frontend** và truy cập `http://localhost:10588` chỉ gọi được API, không có web. Nếu muốn vừa backend vừa giao diện web, chạy GUI hoặc deploy bổ sung frontend. + > ⚠️ Lệnh này chỉ khởi chạy Backend API (Port 10588), không bao gồm giao diện Frontend. Khi truy cập http://localhost:10588 chỉ có thể gọi API. Nếu muốn sử dụng giao diện, vui lòng chạy Frontend riêng hoặc dùng chế độ GUI bên dưới. - - **Cách 2: Chạy GUI ứng dụng desktop Electron** + - **Cách 2: Khởi chạy Client Desktop Electron (Khuyên dùng)** ```bash yarn dev:gui ``` - > Lệnh này khởi động backend đồng thời mở cửa sổ desktop Electron có build frontend sẵn, dùng liền, không cấu hình gì thêm. Dành cho dev muốn trải nghiệm trọn bộ. + > Lệnh này sẽ chạy đồng thời Backend và cửa sổ Desktop Electron với giao diện Frontend đã tích hợp sẵn. Mở lên là có thể sử dụng ngay mà không cần cấu hình thêm. Phù hợp nhất cho lập trình viên muốn trải nghiệm toàn bộ tính năng. - - **Cách 3: Chạy chế độ production** + - **Cách 3: Chạy ở chế độ Product (Sản xuất)** ```bash yarn start ``` - > Chạy trực tiếp bản build (cần build bằng `yarn build` trước). + > Chạy trực tiếp dịch vụ sau khi đã build (Cần chạy lệnh yarn build trước). -4. **Đóng gói dự án** +4. **Đóng gói dự án (Build / Pack)** - - Biên dịch TypeScript: + - Biên dịch tệp TypeScript: ```bash yarn build ``` - - Đóng gói thành exe Windows: + - Đóng gói thành tệp thực thi cho Windows: ```bash yarn dist:win ``` - - Đóng gói MacOS: + - Đóng gói thành tệp thực thi cho MacOS: ```bash yarn dist:mac ``` - - Đóng gói Linux: + - Đóng gói thành tệp thực thi cho Linux: ```bash yarn dist:linux ``` -5. **Kiểm tra chất lượng code** +5. **Kiểm tra chất lượng mã (Lint)** - - Đánh giá tổng thể chuẩn code: + - Kiểm tra cú pháp và quy chuẩn toàn cục: ```bash yarn lint ``` -6. **Bảng debug AI (tùy chọn)** +6. **Bảng điều khiển Debug AI (Tùy chọn)** - Khởi động bảng debug AI SDK, dễ test AI call: + Mở công cụ Debug trực quan của AI SDK để tiện theo dõi các lời gọi AI: ```bash yarn debug:ai @@ -423,166 +419,168 @@ Nếu cần deploy riêng hoặc custom giao diện, tham khảo mã nguồn fro ## Phát triển Frontend -Nếu muốn chỉnh sửa UI, vào repo frontend: +Nếu bạn cần chỉnh sửa giao diện Frontend, vui lòng chuyển sang kho lưu trữ Frontend riêng: - **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) - **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -Sau khi build frontend, copy thư mục `dist` vào `data/web` của repo này để tích hợp. +Sau khi build Frontend xong, hãy copy toàn bộ thư mục dist vào thư mục data/web của dự án này để tích hợp. -## Cấu trúc dự án +## Cấu trúc Dự án ``` -📂 build/ # File build -📂 data/ # Dữ liệu runtime -│ ├─ 📂 models/ # Model local (ONNX) -│ ├─ 📂 oss/ # Lưu trữ asset (media/nhân vật/cảnh) -│ ├─ 📂 serve/ # Entry prod -│ ├─ 📂 skills/ # Prompt kỹ năng Agent -│ └─ 📂 web/ # Thành phẩm frontend (built-in) -📂 docs/ # Tài liệu +📂 build/ # Sản phẩm sau khi build +📂 data/ # Dữ liệu Runtime +│ ├─ 📂 models/ # Mô hình suy luận Local (ONNX) +│ ├─ 📂 oss/ # Lưu trữ Object (ảnh, nhân vật, cảnh) +│ ├─ 📂 serve/ # Cổng vào môi trường Production +│ ├─ 📂 skills/ # Prompt kỹ năng của Agent +│ └─ 📂 web/ # Frontend đã build (tích hợp sẵn) +📂 docs/ # Tài liệu và hình ảnh 📂 env/ # Cấu hình môi trường -📂 scripts/ # Script build & phụ trợ +📂 scripts/ # Script hỗ trợ và Build 📂 src/ -├─ 📂 agents/ # Module AI Agent -│ ├─ 📂 productionAgent/ # Agent sản xuất -│ └─ 📂 scriptAgent/ # Agent kịch bản -├─ 📂 lib/ # Thư viện chung (init db, response...) -├─ 📂 middleware/ # Middleware -├─ 📂 routes/ # Router các module -│ ├─ 📂 agents/ # Quản lý memory Agent -│ ├─ 📂 artStyle/ # Quản lý style tranh -│ ├─ 📂 assets/ # Asset -│ ├─ 📂 assetsGenerate/ # Sinh asset -│ ├─ 📂 cornerScape/ # Quản lý phân cảnh -│ ├─ 📂 general/ # API chung -│ ├─ 📂 login/ # Đăng nhập/ xác thực -│ ├─ 📂 migrate/ # Di trú dữ liệu -│ ├─ 📂 modelSelect/ # Chọn model AI -│ ├─ 📂 novel/ # Quản lý tiểu thuyết -│ ├─ 📂 other/ # Chức năng khác -│ ├─ 📂 production/ # Quản lý sản xuất -│ ├─ 📂 project/ # Quản lý project -│ ├─ 📂 script/ # Tạo kịch bản -│ ├─ 📂 scriptAgent/ # API Agent kịch bản -│ ├─ 📂 setting/ # Thiết lập hệ thống -│ ├─ 📂 task/ # Quản lý task -│ └─ 📂 test/ # API test -├─ 📂 socket/ # WebSocket realtime -├─ 📂 types/ # Định nghĩa TypeScript -├─ 📂 utils/ # Hàm tiện ích -├─ 📄 app.ts # App entry -├─ 📄 core.ts # Init core -├─ 📄 env.ts # Xử lý biến môi trường -├─ 📄 err.ts # Xử lý lỗi -├─ 📄 logger.ts # Ghi log -├─ 📄 router.ts # Đăng ký routes -└─ 📄 utils.ts # Tiện ích chung -📄 Dockerfile # Build Docker -📄 electron-builder.yml # Cấu hình build Electron -📄 skillList.json # Danh sách skill -📄 LICENSE # License (Apache-2.0) -📄 NOTICES.txt # Ghi chú phụ thuộc third-party +├─ 📂 agents/ # Module AI Agent +│ ├─ 📂 productionAgent/ # Agent Sản xuất (Production) +│ └─ 📂 scriptAgent/ # Agent Kịch bản (Script) +├─ 📂 lib/ # Thư viện chung (Khởi tạo Database, định dạng Response) +├─ 📂 middleware/ # Middleware +├─ 📂 routes/ # Các Module Routing +│ ├─ 📂 agents/ # Quản lý bộ nhớ Agent +│ ├─ 📂 artStyle/ # Quản lý phong cách nghệ thuật +│ ├─ 📂 assets/ # Quản lý tài nguyên (Assets) +│ ├─ 📂 assetsGenerate/ # Trình tạo tài nguyên +│ ├─ 📂 cornerScape/ # Quản lý phân cảnh (Storyboard) +│ ├─ 📂 general/ # API chung +│ ├─ 📂 login/ # Xác thực đăng nhập +│ ├─ 📂 migrate/ # Di chuyển dữ liệu (Migration) +│ ├─ 📂 modelSelect/ # Chọn mô hình +│ ├─ 📂 novel/ # Quản lý tiểu thuyết +│ ├─ 📂 other/ # Các tính năng khác +│ ├─ 📂 production/ # Quản lý sản xuất / dựng phim +│ ├─ 📂 project/ # Quản lý dự án +│ ├─ 📂 script/ # Tạo kịch bản +│ ├─ 📂 scriptAgent/ # Interface của Agent kịch bản +│ ├─ 📂 setting/ # Cài đặt hệ thống +│ ├─ 📂 task/ # Quản lý tác vụ (Task) +│ └─ 📂 test/ # API thử nghiệm (Test) +├─ 📂 socket/ # Giao tiếp Real-time qua WebSocket +├─ 📂 types/ # Khai báo Type của TypeScript +├─ 📂 utils/ # Các hàm tiện ích +├─ 📄 app.ts # Entry của ứng dụng +├─ 📄 core.ts # Khởi tạo Core +├─ 📄 env.ts # Xử lý biến môi trường +├─ 📄 err.ts # Xử lý lỗi (Error handling) +├─ 📄 logger.ts # Module ghi log (Logger) +├─ 📄 router.ts # Đăng ký Router +└─ 📄 utils.ts # Công cụ chung +📄 Dockerfile # Tệp cấu hình Build Docker +📄 electron-builder.yml # Cấu hình đóng gói Electron +📄 skillList.json # Danh sách kỹ năng +📄 LICENSE # Giấy phép (Apache-2.0) +📄 NOTICES.txt # Khai báo thư viện bên thứ ba 📄 package.json # Cấu hình dự án 📄 tsconfig.json # Cấu hình TypeScript ``` --- -# 🔗 Repo liên quan +# 🔗 Các Kho lưu trữ Liên quan -| Repo | Giải thích | GitHub | Gitee | -| ---------------- | -------------------------------- | -------------------------------------------------- | ------------------------------------------------ | -| **Toonflow-app** | Ứng dụng client đầy đủ (repo này, người dùng nên dùng) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | -| **Toonflow-web** | Mã nguồn frontend (cho dev UI) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | +| Repository (Kho) | Mô tả | GitHub | Gitee | +| ---------------- | ---------------------------------- | -------------------------------------------------- | ------------------------------------------------ | +| **Toonflow-app** | Client hoàn chỉnh (Repo này, khuyến nghị cho người dùng) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | Mã nguồn Frontend (Dành cho lập trình viên Frontend) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | -> 💡 **Lưu ý**: Nếu chỉ muốn dùng Toonflow, tải về client repo này là đủ. Repo frontend chỉ dành cho ai cần phát triển/custome UI thêm. +> 💡 **Mẹo nhỏ**: Nếu bạn chỉ muốn sử dụng Toonflow, hãy tải Client hoàn chỉnh từ kho này là đủ. Kho Toonflow-web chỉ dành cho các nhà phát triển cần chỉnh sửa hoặc phát triển lại giao diện (secondary development). --- -# 👨‍👩‍👧‍👦 Nhóm chat WeChat +# 👨‍👩‍👧‍👦 Nhóm Discord Cộng đồng -Bot mời tham gia: +Nhấn vào biểu tượng bên dưới để tham gia Discord: -Toonflow QR +[![Join our Discord](https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/67d00cf7266d2c75571aebde_Example.svg)](https://discord.gg/HEjKmpNpAZ) + +Hoặc click trực tiếp vào link: [https://discord.gg/HEjKmpNpAZ](https://discord.gg/HEjKmpNpAZ) --- -# 💌 Liên hệ +# 💌 Liên hệ với chúng tôi -📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow咨询) +📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow%20%C6%B0%C9%9B) --- -# 📜 Giấy phép +# 📜 Giấy phép (License) -Toonflow phát hành mã nguồn mở theo Apache-2.0, kèm thỏa thuận thương mại bổ sung. +Toonflow được phát hành mã nguồn mở dưới giấy phép Apache-2.0, kèm theo Thỏa thuận thương mại bổ sung. -Chi tiết: https://www.apache.org/licenses/LICENSE-2.0 +Chi tiết giấy phép Apache-2.0: https://www.apache.org/licenses/LICENSE-2.0 ## Thỏa thuận bổ sung -- Nếu phân phối phần mềm này dưới dạng sản phẩm cho **2 bên thứ ba độc lập trở lên**, bạn phải có **ủy quyền thương mại bằng văn bản** từ HBAI-Ltd. -- **≤ 5 pháp nhân** cùng vận hành nội bộ mà không cung cấp dịch vụ ra bên ngoài được coi là **sử dụng nội bộ, không cần ủy quyền**. -- Không được xóa hoặc sửa đổi nhãn hiệu, logo hoặc thông tin bản quyền trong Toonflow. +- Nếu phần mềm này được phân phối dưới dạng sản phẩm cho **2 hoặc nhiều bên thứ ba độc lập** sử dụng, bắt buộc phải có **giấy phép thương mại bằng văn bản** từ HBAI-Ltd. +- Nếu **≤ 5 pháp nhân** hợp tác vận hành để sử dụng nội bộ và không cung cấp dịch vụ ra bên ngoài, thì được coi là sử dụng nội bộ và **không cần cấp phép**. +- Không được phép xóa hoặc sửa đổi logo hoặc thông tin bản quyền trong Toonflow. -## Miễn phí vĩnh viễn +## Các trường hợp Miễn phí Vĩnh viễn -- ✅ Sử dụng Toonflow tạo nội dung và nhận chia sẻ doanh thu nền tảng -- ✅ Phát triển thêm cho sử dụng nội bộ nhóm -- ✅ ≤ 5 pháp nhân vận hành chung nội bộ -- ✅ Học tập cá nhân, nghiên cứu, mục đích phi thương mại +- ✅ Dùng Toonflow để sản xuất nội dung và nhận chia sẻ doanh thu từ các nền tảng video +- ✅ Chỉnh sửa mã nguồn (Secondary development) để dùng cho nhóm nội bộ +- ✅ ≤ 5 pháp nhân hợp tác vận hành để sử dụng nội bộ +- ✅ Phục vụ học tập cá nhân, nghiên cứu và các mục đích phi thương mại -## Bảng giá ủy quyền thương mại +## Bảng giá Cấp phép Thương mại -| Giai đoạn | Doanh thu năm | Phí hàng năm | +| Giai đoạn | Doanh thu Hàng năm | Phí Hàng năm | |------|---------|------| -| 🌱 Ươm tạo | < ¥100,000 | **Miễn phí** | -| 🚀 Khởi nghiệp | ¥100,000–500,000 | ¥5,000/năm | -| 📈 Tăng trưởng | ¥500,000–1,500,000 | ¥20,000/năm | -| 🏢 Mở rộng | ¥1,500,000–5,000,000 | ¥80,000/năm | -| 🌐 Doanh nghiệp | > ¥5,000,000 | Thương lượng | +| 🌱 Ươm mầm | < ¥100k (RMB) | **Miễn phí** | +| 🚀 Khởi nghiệp | ¥100k – 500k (RMB) | ¥5,000 / Năm | +| 📈 Tăng trưởng | ¥500k – 1.5M (RMB) | ¥20,000 / Năm | +| 🏢 Quy mô | ¥1.5M – 5M (RMB) | ¥80,000 / Năm | +| 🌐 Doanh nghiệp | > ¥5M (RMB) | Thương lượng | -> **Điều khoản không hồi tố**: Người dùng đã sử dụng Toonflow theo AGPL-3.0 trước khi phát hành v1.0.8 không bị ảnh hưởng. Việc sử dụng hiện tại tiếp tục theo AGPL-3.0. +> **Điều khoản Không hồi tố**: Những người dùng đã sử dụng Toonflow dưới giấy phép AGPL-3.0 trước khi phát hành phiên bản v1.0.8 sẽ tiếp tục tuân theo AGPL-3.0 và không bị ràng buộc bởi sự thay đổi thỏa thuận này. -Xem thỏa thuận đầy đủ tại [LICENSE](../LICENSE). +Xem toàn bộ thỏa thuận tại tệp [LICENSE](./LICENSE). --- -# ⭐️ Lịch sử đánh dấu sao +# ⭐️ Lịch sử Thả sao (Star History) [![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left)](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left) --- -# 🙏 Lời cảm ơn +# 🙏 Lời Cảm ơn -Cảm ơn các dự án open source sau đã hỗ trợ Toonflow mạnh mẽ: +Xin cảm ơn các dự án mã nguồn mở sau đây đã hỗ trợ đắc lực cho Toonflow: -- [Express](https://expressjs.com/) - Framework Web Node.js nhanh, mở, gọn nhẹ -- [AI SDK](https://ai-sdk.dev/) - Bộ tool AI cho TypeScript -- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - Bindings SQLite3 hiệu năng cao -- [Sharp](https://sharp.pixelplumbing.com/) - Thư viện xử lý ảnh Node.js nhanh +- [Express](https://expressjs.com/) - Web framework cho Node.js cực nhanh và tối giản +- [AI SDK](https://ai-sdk.dev/) - Bộ công cụ AI dành cho TypeScript +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - Thư viện liên kết SQLite3 hiệu suất cao +- [Sharp](https://sharp.pixelplumbing.com/) - Thư viện xử lý hình ảnh Node.js hiệu suất cao - [Axios](https://axios-http.com/) - HTTP client dựa trên Promise -- [Zod](https://zod.dev/) - Library kiểm tra schema ưu tiên TypeScript -- [Socket.IO](https://socket.io/) - Engine realtime song phương sự kiện -- [Electron](https://www.electronjs.org/) - Framework phát triển desktop app đa nền tảng -- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - Thư viện infer ML local +- [Zod](https://zod.dev/) - Thư viện xác thực Schema ưu tiên TypeScript +- [Socket.IO](https://socket.io/) - Công cụ giao tiếp sự kiện hai chiều thời gian thực +- [Electron](https://www.electronjs.org/) - Framework phát triển ứng dụng Desktop đa nền tảng +- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - Thư viện suy luận Machine Learning tại Local -Cảm ơn các tổ chức/đơn vị/cá nhân sau đã hỗ trợ Toonflow: +Xin cảm ơn các tổ chức/đơn vị/cá nhân sau đây đã hỗ trợ cho Toonflow:
- 算能云 Logo + Sophnet Logo - Suanneng Cloud tài trợ năng lực tính toán - [Trang chủ] + Sophnet (算能云) Tài trợ năng lực tính toán (Computing power) + [Website]
-Danh sách phụ thuộc bên thứ ba, vui lòng xem `NOTICES.txt` +Vui lòng xem danh sách đầy đủ các thư viện phụ thuộc của bên thứ ba trong tệp `NOTICES.txt`. -##### copyright © 淮北艾阿网络科技有限公司 \ No newline at end of file +##### Copyright © Huaibei AIA Network Technology Co., Ltd. \ No newline at end of file diff --git a/docs/README.zhtw.md b/docs/README.zhtw.md index 029312b..4c760aa 100644 --- a/docs/README.zhtw.md +++ b/docs/README.zhtw.md @@ -1,4 +1,4 @@ -

+

GitHub @@ -8,19 +8,18 @@  |  - Atomgit - Atomgit + Atomgit

- 简体中文 | + 简体中文 | 繁體中文 | English | - ไทย | - Tiếng Việt | - 日本語 | - Русский + ไทย | + Tiếng Việt | + 日本語 | + Русский

@@ -31,11 +30,11 @@

- AI短劇工廠 + AI 短劇工廠
- 一鍵點擊,小說秒變短劇! + 動動手指,小說秒變劇集!
- AI劇本 × AI視覺 × 渦輪生成 🔥 + AI 劇本 × AI 影像 × 極速生成 🔥

@@ -50,7 +49,7 @@

- > 🚀 **一站式短劇生產**:從文本到人物、從分鏡到影片,零門檻全流程AI,10倍以上創作效率! + > 🚀 **一站式短劇工程**:從文字到角色,從分鏡到影片,0 門檻全流程 AI 化,創作效率提升 10 倍+!
--- @@ -59,164 +58,169 @@ Toonflow 支援以下語言介面: -| 語言 | Language | -|------|----------| -| 简体中文 | Chinese (Simplified) | -| 繁體中文 | Chinese (Traditional) | -| English | English | -| ไทย | Thai | -| Tiếng Việt | Vietnamese | -| 日本語 | Japanese | -| Русский | Russian | +| 語言 | Language | +|--------------|---------------------------| +| 简体中文 | Chinese (Simplified) | +| 繁體中文 | Chinese (Traditional) | +| English | English | +| ไทย | Thai | +| Tiếng Việt | Vietnamese | +| 日本語 | Japanese | +| Русский | Russian | + +> 💡 更多語言正在適配中,歡迎貢獻翻譯! --- # 🌟 主要功能 -Toonflow 是一款AI短劇漫畫工具,利用AI自動將小說轉換為劇本,並用AI生成圖片、視頻,助力高效短劇製作。有了Toonflow,您可輕鬆完成從文本到圖片的全流程操作,讓短劇製作更智能、更便捷。 +Toonflow 是一款 AI 短劇與漫畫創作工具,能夠利用 AI 技術將小說自動轉化為劇本,並結合 AI 生成的圖像與影片,高效完成短劇製作。透過 Toonflow,您可以輕鬆完成從文字到最終影片的全流程,讓短劇創作變得更加智能與便捷。 + +- ✅ **角色生成** + 自動分析原始小說文本,智能識別並建立角色設定,包含外貌、性格、身份等詳細資訊,為後續劇本與畫面創作提供堅實基礎。 -- ✅ **人物生成** - 自動解析原小說文本,智能識別並生成人物設定,包括外貌、性格、身份等,為後續劇本和視覺創作提供穩固基礎。 - ✅ **劇本生成** - 根據所選事件和章節,系統自動生成結構化劇本,涵蓋對話、場景描述、劇情走向,實現文學文本向影視劇本高效轉化。 -- ✅ **分鏡製作** - 根據劇本內容,智能生成分鏡提示與視覺設計,細化前景/中景/背景、人物動態、道具設定與場景佈局,自動將劇本轉換為分鏡,為影片製作提供完整藍圖。 + 根據選定的事件與章節,系統自動產生結構清晰的劇本,包含自然對白、場景描述與劇情發展,高效將文學作品轉化為影視劇本。 + +- ✅ **分鏡製作 (Storyboard)** + 根據劇本自動生成分鏡提示詞與畫面設計,細化前、中、後景、角色動作、道具與場景佈局,為影片製作提供完整的藍圖。 + - ✅ **影片合成** - 集成AI圖像與視頻技術,通過AI生成視頻片段,支持線上編輯與個性化輸出調整,讓影視製作協同高效。 + 整合 AI 圖像與影片生成技術,可產生高品質影片片段。內建線上剪輯功能,支援個人化調整,讓創作過程更順暢快速。 --- # 📦 應用場景 -- 短視頻內容創作 -- 小說改編影視實驗 -- AI文學改編工具 -- 劇本開發與快速原型 +- 短影音內容創作 +- 小說影視化實驗 +- AI 文學改編工具 +- 劇本開發與快速原型製作 - 影片素材生成 --- -# 🔰 用戶指南 +# 🔰 使用指南 -## 📺 視頻教程 +## 📺 影片教學 -https://www.bilibili.com/video/BV1na6wB6Ea2 -[![Toonflow 8分鐘快速上手AI視頻](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) +[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2) +[![Toonflow 8 分鐘快速上手 AI 影片](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) -**Toonflow 8分鐘快速上手AI視頻** -👉 [點此觀看](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) +**Toonflow 8 分鐘快速上手 AI 影片** +👉 [點擊觀看](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) -📱 用手機微信掃碼觀看 +📱 使用手機掃描 QR Code 觀看 -Scan WeChat to Watch +掃描 QR Code 觀看 --- -# 🚀 安裝方法 +# 🚀 安裝 -## 前置準備 +## 前置條件 -安裝與使用前請準備以下內容: +安裝並使用本軟體前,請先準備以下項目: -- ✅ 大語言模型AI服務API地址 -- ✅ Sora或豆包視頻服務API地址 -- ✅ Nano Banana Pro圖像生成模型API +- ✅ 大型語言模型 (LLM) 的 API 網址 +- ✅ Sora 或豆包影片生成服務的 API 網址 +- ✅ Nano Banana Pro 圖像生成模型的 API 網址 -## 本地安裝 +## 本機安裝 -### 1. 下載安裝 +### 1. 下載與安裝 -| 作業系統 | GitHub | Atomgit | 夸克網盤下載 | 說明 | +| 作業系統 | GitHub | Atomgit | 夸克網碟下載 | 說明 | | :------: | :----------------------------------------------------------- | :------------------------------------------------------------ | :---------------------------------------------- | :------------- | -| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克網盤](https://pan.quark.cn/s/94ef07509df0) | 官方發布安裝包 | -| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克網盤](https://pan.quark.cn/s/94ef07509df0) | 官方發布安裝包 | -| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克網盤](https://pan.quark.cn/s/94ef07509df0) | 官方發布安裝包 | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克網碟](https://pan.quark.cn/s/94ef07509df0) | 官方發佈安裝包 | +| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克網碟](https://pan.quark.cn/s/94ef07509df0) | 官方發佈安裝包 | +| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitcode.com/HBAI-Ltd/Toonflow-app/releases) | [夸克網碟](https://pan.quark.cn/s/94ef07509df0) | 官方發佈安裝包 | > [!CAUTION] -> MacOS上需進入設定–隱私安全配置安全設定,否則可能因憑證問題無法打開應用。 +> MacOS 系統請至「系統設定」-「隱私權與安全性」設定安全性,否則可能因憑證問題無法正常開啟。 > -> 參考知乎文檔:[https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) +> 參考知乎教學:[https://www.zhihu.com/question/433389276](https://www.zhihu.com/question/433389276) -> 受Gitee作業系統環境與釋出檔案大小限制,目前Gitee釋出下載暫不開放。 +> 因 Gitee OS 環境限制及 Release 檔案上傳大小限制,暫不提供 Gitee Release 下載連結。 ### 2. 啟動服務 安裝完成後,啟動程式即可開始使用本服務。 -> ⚠️ **首次登入** -> 用戶名:`admin` +> ⚠️ **首次登入** +> 帳號:`admin` > 密碼:`admin123` -## Docker部署 +## Docker 部署 -### 前置準備 +### 前置條件 -- 已安裝 [Docker](https://docs.docker.com/get-docker/)(20.10+) +- 已安裝 [Docker](https://docs.docker.com/get-docker/)(版本 20.10+) -### 方法一:線上部署 +### 方式一:線上部署 -待開發,現請使用本地構建。 +待完善,暫時使用本機建置。 -### 方法二:本地構建 +### 方式二:本機建置 -適用於開發者或已克隆源碼的用戶,需本地安裝Git: +使用本機已有的原始碼直接建置,適合開發者或已 Clone 儲存庫的使用者,這需要您在本機安裝 git: ```shell -# 克隆專案(已克隆則略過) +# 先 Clone 專案(若已有則跳過) git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app -# 用docker-compose本地構建啟動 +# 使用 docker-compose 進行本機建置並啟動 yarn docker:local -# 或手動構建 +# 或者手動建置 docker build -t toonflow . -docker run -d -p :10588 -v :/app/data toonflow +docker run -d -p <本機 Port>:10588 -v <本機資料路徑>:/app/data toonflow -# 完成後可通過映射端口/web/index.html訪問 -# 如 http://localhost:10588/web/index.html +# 此時在相應 Port 的 /web/index.html 路徑即可存取頁面 +# 例如 http://localhost:10588/web/index.html ``` -### 服務端口說明 +### 服務 Port 說明 -| 端口 | 用途 | 部署映射 | -| -------- |------------| -------------------- | -| `10588` | 應用介面 | `10588:10588` | +| Port | 用途 | 部署對應 | +| ------- | -------- | ------------- | +| `10588` | 軟體介面 | `10588:10588` | **環境變數說明:** -| 變數 | 說明 | -| -------------- | ------------------------------------------ | -| `NODE_ENV` | 環境,生產用`prod` | -| `PORT` | 服務監聽端口(預設10588) | -| `OSSURL` | 靜態檔案存取地址 | +| 變數 | 說明 | +| ---------- | ---------------------------------- | +| `NODE_ENV` | 執行環境,`prod` 表示正式環境 | +| `PORT` | 服務監聽 Port(預設 10588) | +| `OSSURL` | 檔案儲存存取網址,用於靜態資源存取 | --- -## 雲端部署 +## ☁️ 雲端部署 -### 1. 伺服器需求 +### 一、伺服器環境要求 -- **作業系統:** Ubuntu 20.04+ / CentOS 7+ -- **Node.js:** 24.x(推薦,最低23.11.1+) -- **記憶體:** 2GB+ +- **系統**:Ubuntu 20.04+ / CentOS 7+ +- **Node.js**:24.x(推薦,最低 23.11.1+) +- **記憶體**:2GB+ -### 2. 伺服器部署 +### 二、伺服器部署 #### 1. 安裝環境 ```bash -# 安裝Node.js +# 安裝 Node.js curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 24 -# 安裝Yarn與PM2 +# 安裝 Yarn 和 PM2 npm install -g yarn pm2 ``` -#### 2. 專案部署 +#### 2. 部署專案 -**GitHub克隆:** +**從 GitHub Clone:** ```bash cd /opt @@ -226,7 +230,7 @@ yarn install yarn build ``` -**Gitee克隆(中國大陸推薦):** +**從 Gitee Clone(內地網路使用):** ```bash cd /opt @@ -236,9 +240,9 @@ yarn install yarn build ``` -#### 3. 配置PM2 +#### 3. 設定 PM2 -新建`pm2.json`: +建立 `pm2.json` 檔案: ```json { @@ -256,11 +260,11 @@ yarn build **環境變數說明:** -| 變數 | 說明 | -| -------------- | ------------------------------------------ | -| `NODE_ENV` | 環境,生產用`prod` | -| `PORT` | 服務監聽端口 | -| `OSSURL` | 靜態檔案存取地址 | +| 變數 | 說明 | +| ---------- | ---------------------------------- | +| `NODE_ENV` | 執行環境,`prod` 表示正式環境 | +| `PORT` | 服務監聽 Port | +| `OSSURL` | 檔案儲存存取網址,用於靜態資源存取 | --- @@ -272,80 +276,80 @@ pm2 startup pm2 save ``` -#### 5. 常用命令 +#### 5. 常用指令 ```bash -pm2 list # 查看進程列表 +pm2 list # 查看處理程序 pm2 logs toonflow-app # 查看日誌 -pm2 restart all # 重啟服務 +pm2 restart all # 重新啟動服務 pm2 monit # 監控面板 ``` -> ⚠️ **首次登入** -> 用戶名:`admin` +> ⚠️ **首次登入** +> 帳號:`admin` > 密碼:`admin123` -#### 6. 前端網站部署 +#### 6. 部署前端網站 -若需單獨部署前端或自定義,參見前端專案: +若需單獨部署或客製化前端介面,請參考前端儲存庫: -- **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) -- **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) +- **GitHub**:[Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) +- **Gitee**:[Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -> 💡 **注意:** 本專案已預設內建前端,普通用戶無需單獨部署。前端源碼主要供開發者二次開發使用。 +> 💡 **說明**:本儲存庫已內建編譯好的前端資源,一般使用者無需單獨部署前端。前端儲存庫僅供需要二次開發的開發者使用。 --- -# 🔧 開發指南 +# 🔧 開發流程指南 > [!CAUTION] -> 🚧 **PR提交規範** 🚧 +> 🚧 **PR 提交規範** 🚧 > -> ⛔ `master`分支不接受PR | ✅ 請提交至`develop`分支 +> ⛔ `master` 分支不接受任何 PR | ✅ 請將 PR 提交到 `develop` 分支 > -> 歡迎開發者協同合作,共同開發Toonflow。欲加入請聯繫owner ACT入群。 +> 歡迎開發者們共同參與 Toonflow 的共創。如有興趣加入,請在交流群內聯絡主理人 ACT -## 🛠️ 技術棧 +## 🛠️ 技術堆疊 -| 分類 | 技術 | -| ----------- | -------------------------------------------------------------------------------------- | -| 運行環境 | Node.js 23.11.1+ | -| 語言 | TypeScript 5.x | -| 後端 | Express 5 | -| 資料庫 | SQLite(better-sqlite3 / knex) | -| AI接入 | Vercel AI SDK(OpenAI / Anthropic / Google / DeepSeek / 智譜 / MiniMax / Qwen / xAI)| -| 本地推理 | @huggingface/transformers(ONNX) | -| 實時通信 | Socket.IO | -| 桌面端 | Electron 40 | -| 影像處理 | Sharp | -| 容器化 | Docker | +| 類別 | 技術 | +| ---------- | ----------------------------------------------------------------------------------------- | +| 執行環境 | Node.js 23.11.1+ | +| 語言 | TypeScript 5.x | +| 後端框架 | Express 5 | +| 資料庫 | SQLite(better-sqlite3 / knex) | +| AI 整合 | Vercel AI SDK(OpenAI / Anthropic / Google / DeepSeek / 智譜 / MiniMax / 通義千問 / xAI) | +| 本機推論 | @huggingface/transformers(ONNX) | +| 即時通訊 | Socket.IO | +| 桌面用戶端 | Electron 40 | +| 影像處理 | Sharp | +| 容器化 | Docker | ## 開發環境準備 -- **Node.js**:需23.11.1以上版本 -- **Yarn**:推薦作為包管理器 +- **Node.js**:版本要求 23.11.1 及以上 +- **Yarn**:推薦作為專案套件管理員 -## 快速上手 +## 快速啟動專案 -1. **克隆專案** +1. **Clone 專案** - **GitHub克隆:** + **從 GitHub Clone:** ```bash git clone https://github.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` - **Gitee克隆(大陸推薦):** + **從 Gitee Clone(內地網路使用):** ```bash git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git cd Toonflow-app ``` -2. **安裝依賴** +2. **安裝相依套件** - 在專案根目錄執行: + 請先在專案根目錄下執行以下指令以安裝相依套件: ```bash yarn install @@ -353,69 +357,69 @@ pm2 monit # 監控面板 3. **啟動開發環境** - 本專案包含 **後端API服務** 和 **前端介面**,按需啟動: + 本專案包含 **後端 API 服務** 和 **前端頁面** 兩部分,請根據需要選擇啟動方式: - - **方案1:僅啟動後端服務** + - **方式一:僅啟動後端服務** ```bash yarn dev ``` - > ⚠️ 此命令僅啟動後端API(10588端口),沒有Web介面。僅可存取API,完整UI需啟動前端專案或用下述GUI模式。 + > ⚠️ 此指令僅啟動後端 API 服務(Port 10588),**不包含前端頁面**。直接瀏覽 `http://localhost:10588` 只能呼叫 API 介面,無法看到完整的網頁介面。若需同時使用前端頁面,請配合前端專案單獨啟動,或使用下方的 GUI 模式。 - - **方案2:啟動Electron桌面客戶端** + - **方式二:啟動 Electron 桌面用戶端** ```bash yarn dev:gui ``` - > 此命令即啟動後端又開Electron視窗,內建Web UI。開箱即用,體驗完整。 + > 此指令會同時啟動後端服務和 Electron 桌面視窗,內建前端頁面,開箱即用,無需額外設定。適合想要完整體驗所有功能的開發者。 - - **方案3:生產模式啟動** + - **方式三:正式環境模式啟動** ```bash yarn start ``` - > 編譯後以生產模式運行(需先執行`yarn build`)。 + > 以生產模式直接執行編譯後的服務(需先執行 `yarn build`)。 -4. **構建專案** +4. **專案打包建置** - - 編譯TypeScript: + - 編譯並產生 TypeScript 檔案: ```bash yarn build ``` - - Windows可執行檔打包: + - 打包為 Windows 平台執行檔: ```bash yarn dist:win ``` - - Mac打包: + - 打包為 Mac 平台執行檔: ```bash yarn dist:mac ``` - - Linux打包: + - 打包為 Linux 平台執行檔: ```bash yarn dist:linux ``` -5. **代碼質量檢查** +5. **程式碼品質檢查 (Lint)** - - 執行Lint: + - 進行全域語法和規範檢查: ```bash yarn lint ``` -6. **AI調試面板(可選)** +6. **AI 除錯面板(選用)** - 啟動Vercel AI SDK可視化調試工具,便於AI對接調測: + 啟動 AI SDK 的視覺化除錯工具,方便對 AI 呼叫進行除錯: ```bash yarn debug:ai @@ -423,129 +427,131 @@ pm2 monit # 監控面板 ## 前端開發 -需修改前端UI,請於專用前端專案開發: +若需修改前端介面,請前往前端儲存庫進行開發: -- **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) -- **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) +- **GitHub**:[Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) +- **Gitee**:[Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) -前端打包後將`dist`內容複製至本專案`data/web`即可集成。 +前端建置後,將 `dist` 目錄內容複製到本專案的 `data/web` 目錄即可整合。 ## 專案結構 ``` -📂 build/ # 編譯產物 -📂 data/ # 運行時資料 -│ ├─ 📂 models/ # 本地推理模型(ONNX) +📂 build/ # 編譯產物 +📂 data/ # 執行時資料 +│ ├─ 📂 models/ # 本機推論模型(ONNX) │ ├─ 📂 oss/ # 物件儲存(素材/角色/場景) -│ ├─ 📂 serve/ # 生產模式入口 -│ ├─ 📂 skills/ # Agent技能提示 -│ └─ 📂 web/ # 前端資產 -📂 ./ # 文檔資產 -📂 env/ # 環境配置 -📂 scripts/ # 構建與輔助腳本 +│ ├─ 📂 serve/ # 正式環境入口 +│ ├─ 📂 skills/ # Agent 技能提示詞 +│ └─ 📂 web/ # 前端編譯產物(內建) +📂 docs/ # 文件資源 +📂 env/ # 環境設定 +📂 scripts/ # 建置與輔助腳本 📂 src/ -├─ 📂 agents/ # AI Agent模組 -│ ├─ 📂 productionAgent/ # 製作Agent -│ └─ 📂 scriptAgent/ # 劇本Agent -├─ 📂 lib/ # 通用庫(資料庫、響應) -├─ 📂 middleware/ # 中間件 -├─ 📂 routes/ # API路由 -│ ├─ 📂 agents/ # Agent記憶管理 -│ ├─ 📂 artStyle/ # 美術風格管理 +├─ 📂 agents/ # AI Agent 模組 +│ ├─ 📂 productionAgent/ # 製作 Agent +│ └─ 📂 scriptAgent/ # 劇本 Agent +├─ 📂 lib/ # 公用函式庫(資料庫初始化、回應格式) +├─ 📂 middleware/ # 中介軟體 +├─ 📂 routes/ # 路由模組 +│ ├─ 📂 agents/ # Agent 記憶管理 +│ ├─ 📂 artStyle/ # 畫風管理 │ ├─ 📂 assets/ # 素材管理 │ ├─ 📂 assetsGenerate/ # 素材生成 │ ├─ 📂 cornerScape/ # 分鏡管理 -│ ├─ 📂 general/ # 通用API -│ ├─ 📂 login/ # 認證 -│ ├─ 📂 migrate/ # 資料遷移 +│ ├─ 📂 general/ # 通用 API +│ ├─ 📂 login/ # 登入認證 +│ ├─ 📂 migrate/ # 資料轉移 │ ├─ 📂 modelSelect/ # 模型選擇 │ ├─ 📂 novel/ # 小說管理 │ ├─ 📂 other/ # 其他功能 │ ├─ 📂 production/ # 製作管理 │ ├─ 📂 project/ # 專案管理 │ ├─ 📂 script/ # 劇本生成 -│ ├─ 📂 scriptAgent/ # 劇本Agent API +│ ├─ 📂 scriptAgent/ # 劇本 Agent 介面 │ ├─ 📂 setting/ # 系統設定 │ ├─ 📂 task/ # 任務管理 -│ └─ 📂 test/ # 測試API -├─ 📂 socket/ # WebSocket通訊 -├─ 📂 types/ # TypeScript型別 +│ └─ 📂 test/ # 測試介面 +├─ 📂 socket/ # WebSocket 即時通訊 +├─ 📂 types/ # TypeScript 類型宣告 ├─ 📂 utils/ # 工具函式 ├─ 📄 app.ts # 應用入口 ├─ 📄 core.ts # 核心初始化 -├─ 📄 env.ts # 環境變數 +├─ 📄 env.ts # 環境變數處理 ├─ 📄 err.ts # 錯誤處理 ├─ 📄 logger.ts # 日誌模組 ├─ 📄 router.ts # 路由註冊 └─ 📄 utils.ts # 通用工具 -📄 Dockerfile # Docker構建 -📄 electron-builder.yml # Electron打包配置 -📄 skillList.json # 技能列表 -📄 LICENSE # (Apache-2.0) 授權 -📄 NOTICES.txt # 第三方依賴 -📄 package.json # 專案配置 -📄 tsconfig.json # TypeScript配置 +📄 Dockerfile # Docker 建置檔案 +📄 electron-builder.yml # Electron 打包設定 +📄 skillList.json # 技能清單 +📄 LICENSE # 授權條款(Apache-2.0) +📄 NOTICES.txt # 第三方相依套件聲明 +📄 package.json # 專案設定 +📄 tsconfig.json # TypeScript 設定 ``` --- -# 🔗 相關倉庫 +# 🔗 相關儲存庫 -| 倉庫 | 說明 | GitHub | Gitee | -| -------------- | -------------------------- | ------------------------------------------------- | -------------------------------------------------- | -| **Toonflow-app** | 完整客戶端(本倉庫,供用戶) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app)| [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | -| **Toonflow-web** | 前端源碼(前端開發者用) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web)| [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | +| 儲存庫 | 說明 | GitHub | Gitee | +| ---------------- | ---------------------------------- | -------------------------------------------------- | ------------------------------------------------ | +| **Toonflow-app** | 完整用戶端(本儲存庫,推薦一般使用者) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | 前端原始碼(適合前端開發者) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | -> 💡 **提醒:** 若僅需使用Toonflow,直接下載本倉庫客戶端即可。前端源碼僅供需二次開發或UI自訂者使用。 +> 💡 **提示**:如果您只是想使用 Toonflow,直接下載本儲存庫的用戶端即可。前端儲存庫僅供需要二次開發或客製化前端介面的開發者使用。 --- -# 👨‍👩‍👧‍👦 微信交流群 +# 👨‍👩‍👧‍👦 Discord 交流群組 -群助手: +點擊下方圖示加入 Discord: -Toonflow QR +[![Join our Discord](https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/67d00cf7266d2c75571aebde_Example.svg)](https://discord.gg/HEjKmpNpAZ) + +或直接點擊連結: [https://discord.gg/HEjKmpNpAZ](https://discord.gg/HEjKmpNpAZ) --- -# 💌 聯繫我們 +# 💌 聯絡我們 -📧 郵箱:[ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow inquiry) +📧 信箱:[ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow諮詢) --- -# 📜 開源協議 +# 📜 授權條款 -Toonflow 基於 Apache-2.0 協議開源發布,並附有補充商業協議。 +Toonflow 基於 Apache-2.0 協定開源發佈,並附有補充商業協議。 -授權詳情:https://www.apache.org/licenses/LICENSE-2.0 +授權條款詳情:https://www.apache.org/licenses/LICENSE-2.0 ## 補充協議 -- 若將本軟體以產品形式分發給 **2 個及以上獨立第三方**使用,須取得 HBAI-Ltd **書面商業授權**。 -- **≤ 5 個法人**聯合運營內部使用,不對外提供服務的,視為內部使用,**無需授權**。 +- 若將本軟體以產品形式散佈給 **2 個及以上獨立第三方**使用,須取得 HBAI-Ltd **書面商業授權**。 +- **≤ 5 個法人**聯合營運內部使用,不對外提供服務的,視為內部使用,**無需授權**。 - 不得刪除或修改 Toonflow 中的標識或版權資訊。 ## 永久免費場景 -- ✅ 用 Toonflow 製作內容並獲得平台分帳 +- ✅ 用 Toonflow 製作內容並獲得平台分潤 - ✅ 二次開發供自己團隊內部使用 -- ✅ ≤ 5 個法人聯合運營內部使用 +- ✅ ≤ 5 個法人聯合營運內部使用 - ✅ 個人學習、研究、非商業用途 -## 商業授權定價 +## 商業授權定價(人民幣) -| 階段 | 年銷售額 | 年費 | -|------|---------|------| -| 🌱 扶持期 | < ¥10 萬 | **免費** | -| 🚀 初創期 | ¥10–50 萬 | ¥5,000/年 | -| 📈 成長期 | ¥50–150 萬 | ¥20,000/年 | -| 🏢 規模期 | ¥150–500 萬 | ¥80,000/年 | -| 🌐 企業級 | > ¥500 萬 | 面議 | +| 階段 | 年營業額 | 年費 | +|------------|---------------------------|-------------------| +| 🌱 扶持期 | < 10 萬人民幣 | **免費** | +| 🚀 初創期 | 10–50 萬人民幣 | ¥5,000 / 年 | +| 📈 成長期 | 50–150 萬人民幣 | ¥20,000 / 年 | +| 🏢 規模期 | 150–500 萬人民幣 | ¥80,000 / 年 | +| 🌐 企業級 | > 500 萬人民幣 | 面議 | -> **不追溯條款**:v1.0.8 發布前基於 AGPL-3.0 使用的用戶,繼續按 AGPL-3.0 執行,不受本協議變更約束。 +> **不溯及既往條款**:v1.0.8 發佈前基於 AGPL-3.0 使用的使用者,繼續按 AGPL-3.0 執行,不受本協議變更約束。 -完整協議詳見 [LICENSE](../LICENSE) 檔案。 +完整協議詳見 [LICENSE](./LICENSE) 檔案。 --- @@ -555,34 +561,34 @@ Toonflow 基於 Apache-2.0 協議開源發布,並附有補充商業協議。 --- -# 🙏 感謝 +# 🙏 致謝 -感謝以下開源專案對Toonflow的支持: +感謝以下開源專案為 Toonflow 提供強大支援: -- [Express](https://expressjs.com/) - 快速、開放、極簡的Node.js Web框架 -- [AI SDK](https://ai-sdk.dev/) - TypeScript優先的AI工具包 -- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - 高效能SQLite3綁定 -- [Sharp](https://sharp.pixelplumbing.com/) - Node.js高性能影像工具 -- [Axios](https://axios-http.com/) - Promise的HTTP用戶端 -- [Zod](https://zod.dev/) - TypeScript優先的型別驗證庫 -- [Socket.IO](https://socket.io/) - 實時雙向事件框架 -- [Electron](https://www.electronjs.org/) - 跨平台桌面應用框架 -- [Hugging Face Transformers](https://huggingface.co./transformers.js) - 本地ML推理庫 +- [Express](https://expressjs.com/) - 快速、開放、極簡的 Node.js Web 框架 +- [AI SDK](https://ai-sdk.dev/) - 面向 TypeScript 的 AI 工具包 +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - 高效能 SQLite3 綁定庫 +- [Sharp](https://sharp.pixelplumbing.com/) - 高效能 Node.js 影像處理庫 +- [Axios](https://axios-http.com/) - 基於 Promise 的 HTTP 用戶端 +- [Zod](https://zod.dev/) - TypeScript 優先的結構驗證庫 +- [Socket.IO](https://socket.io/) - 即時雙向事件通訊引擎 +- [Electron](https://www.electronjs.org/) - 跨平台桌面應用開發框架 +- [Hugging Face Transformers](https://huggingface.co/docs/transformers.js) - 本機 ML 推論庫 -感謝以下組織/個人的支持: +感謝以下組織/單位/個人為 Toonflow 提供支援:
- SophNet Logo + 算能雲 Logo - SophNet Cloud 提供算力贊助 - [官方網站] + 算能雲 提供算力贊助 + [官網]
-完整第三方依賴列表請見 `NOTICES.txt` +完整的第三方相依性清單請查閱 `NOTICES.txt` -##### copyright © 淮北艾阿网络科技有限公司 \ No newline at end of file +##### copyright © 淮北艾阿網絡科技有限公司 \ No newline at end of file diff --git a/package.json b/package.json index 91826f9..00465f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "toonflow", - "version": "1.0.11", + "version": "1.1.0", "description": "Toonflow 是一款 AI 短剧漫剧工具,能够利用 AI 技术将小说自动转化为剧本,并结合 AI 生成的图片和视频,实现高效的短剧创作。", "author": "HBAI-Ltd ", "license": "Apache-2.0", diff --git a/scripts/main.ts b/scripts/main.ts index d4472a8..b793b20 100644 --- a/scripts/main.ts +++ b/scripts/main.ts @@ -7,66 +7,70 @@ import Module from "module"; app.commandLine.appendSwitch("disable-gpu-shader-disk-cache"); app.commandLine.appendSwitch("disable-features", "CalculateNativeWinOcclusion"); -declare const __APP_VERSION__: string | undefined; +const TARGET_ENTRIES = new Set(["assets", "models", "serve", "skills", "web"]); -/** - * 将 extraResources 中的 data 目录复制到用户数据目录(跳过已存在的文件,保留用户修改) - */ - -function getVersionFromUpdateJson(filePath: string): string | null { - try { - if (fs.existsSync(filePath)) { - const data = JSON.parse(fs.readFileSync(filePath, "utf8")); - return data.version ?? null; - } - } catch {} - return null; +function copyDir(src: string, dest: string): void { + if (!fs.existsSync(src)) return; + fs.mkdirSync(dest, { recursive: true }); + for (const entry of fs.readdirSync(src, { withFileTypes: true })) { + const s = path.join(src, entry.name); + const d = path.join(dest, entry.name); + entry.isDirectory() ? copyDir(s, d) : fs.existsSync(d) || fs.copyFileSync(s, d); + } } -function copyDirForce(src: string, dest: string): void { - if (!fs.existsSync(src)) return; - if (fs.existsSync(dest)) { - fs.rmSync(dest, { recursive: true, force: true }); +declare const __APP_VERSION__: string; + +function compareVersions(a: string, b: string): number { + const pa = a + .split(".") + .map((n) => Number.parseInt(n, 10)) + .filter((n) => Number.isFinite(n)); + const pb = b + .split(".") + .map((n) => Number.parseInt(n, 10)) + .filter((n) => Number.isFinite(n)); + const len = Math.max(pa.length, pb.length); + for (let i = 0; i < len; i++) { + const va = pa[i] ?? 0; + const vb = pb[i] ?? 0; + if (va > vb) return 1; + if (va < vb) return -1; } - copyDirRecursive(src, dest); + return 0; } function initializeData(): void { const srcDir = path.join(process.resourcesPath, "data"); const destDir = path.join(app.getPath("userData"), "data"); - const updateJsonFile = path.join(destDir, "update.json"); - const currentVersion = typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : "0.0.0"; - const userVersion = getVersionFromUpdateJson(updateJsonFile); + const versionFilePath = path.join(destDir, "version.txt"); - // 首次安装或无update.json,直接全量拷贝 - if (!fs.existsSync(destDir) || !userVersion) { - copyDirRecursive(srcDir, destDir); - return; - } - - // 版本号不同则覆盖 serve 和 web 目录 - if (userVersion !== currentVersion) { - copyDirForce(path.join(srcDir, "serve"), path.join(destDir, "serve")); - copyDirForce(path.join(srcDir, "web"), path.join(destDir, "web")); - } -} - -function copyDirRecursive(src: string, dest: string): void { - if (!fs.existsSync(src)) return; - if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true }); - for (const entry of fs.readdirSync(src, { withFileTypes: true })) { - // 跳过 oss 文件夹和 db2.sqlite 文件 - if (entry.isDirectory() && entry.name === "logs") continue; - if (entry.isDirectory() && entry.name === "oss") continue; - if (!entry.isDirectory() && entry.name === "db2.sqlite") continue; - const srcPath = path.join(src, entry.name); - const destPath = path.join(dest, entry.name); - if (entry.isDirectory()) { - copyDirRecursive(srcPath, destPath); - } else if (!fs.existsSync(destPath)) { - fs.copyFileSync(srcPath, destPath); + let shouldForceReplace = false; + if (!fs.existsSync(versionFilePath)) { + shouldForceReplace = true; + } else { + const localVersion = fs.readFileSync(versionFilePath, "utf-8").trim(); + if (compareVersions(localVersion, __APP_VERSION__) < 0) { + shouldForceReplace = true; } } + + for (const dir of TARGET_ENTRIES) { + const targetDir = path.join(destDir, dir); + if (shouldForceReplace) { + fs.rmSync(targetDir, { recursive: true, force: true }); + copyDir(path.join(srcDir, dir), targetDir); + continue; + } + if (!fs.existsSync(targetDir)) { + copyDir(path.join(srcDir, dir), targetDir); + } + } + + if (shouldForceReplace) { + fs.mkdirSync(destDir, { recursive: true }); + fs.writeFileSync(versionFilePath, `${__APP_VERSION__}\n`, "utf-8"); + } } //获取全部依赖路径,优先从 unpacked 加载原生模块,其他模块从 asar 加载 @@ -246,7 +250,7 @@ app.whenReady().then(async () => { const url = new URL(request.url); const pathname = url.hostname.toLowerCase(); const handlers: Record object> = { - getport: () => ({ port: port }), + getappurl: () => ({ url: process.env.URL ?? `http://localhost:${port}/api` }), windowminimize: () => { mainWindow?.minimize(); return { ok: true }; diff --git a/src/agents/productionAgent/index copy.ts b/src/agents/productionAgent/index copy.ts index fc4435f..4744625 100644 --- a/src/agents/productionAgent/index copy.ts +++ b/src/agents/productionAgent/index copy.ts @@ -3,10 +3,11 @@ import { tool } from "ai"; import { z } from "zod"; import u from "@/utils"; import Memory from "@/utils/agent/memory"; -import { useSkill } from "@/utils/agent/skillsTools"; +import { createSkillTools, parseFrontmatter, scanSkills, useSkill } from "@/utils/agent/skillsTools"; import useTools from "@/agents/productionAgent/tools"; import ResTool from "@/socket/resTool"; import * as fs from "fs"; +import path from "path"; export interface AgentContext { socket: Socket; @@ -34,121 +35,200 @@ function buildMemPrompt(mem: Awaited>): string { return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`; } -const subAgentList = ["executionAI", "supervisionAI"] as const; - export async function decisionAI(ctx: AgentContext) { const { isolationKey, text, abortSignal } = ctx; const memory = new Memory("productionAgent", isolationKey); await memory.add("user", text); - const { skillPaths } = await useSkill({ mainSkill: "production_agent_decision" }); - const prompt = await fs.promises.readFile(skillPaths.mainSkill, "utf-8"); + const skill = path.join(u.getPath("skills"), "production_agent_decision.md"); + const prompt = await fs.promises.readFile(skill, "utf-8"); + + const projectInfo = await u.db("o_project").where("id", ctx.resTool.data.projectId).first(); + if (!projectInfo) throw new Error(`项目不存在,ID: ${ctx.resTool.data.projectId}`); + const [_, imageModelName] = projectInfo.imageModel!.split(":"); + const [id, videoModelName] = projectInfo.videoModel!.split(":"); + const data = await u.db("o_vendorConfig").where("id", id).select("models").first(); + const models = JSON.parse(data!.models!); + const findData = models.find((i: any) => i.modelName == videoModelName); + const isRef = findData.mode.every((i: any) => Array.isArray(i)); + const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`; const mem = buildMemPrompt(await memory.get(text)); const { textStream } = await u.Ai.Text("productionAgent").stream({ messages: [ { role: "system", content: prompt }, - { role: "system", content: mem }, + { role: "assistant", content: mem + "\n" + modelInfo }, { role: "user", content: text }, ], abortSignal, tools: { ...memory.getTools(), - run_sub_agent: runSubAgent(ctx), ...useTools({ resTool: ctx.resTool, msg: ctx.msg }), + ...createSubAgent(ctx), }, onFinish: async (completion) => { - await memory.add("assistant:decision", completion.text); + await memory.add("assistant:decision", removeAllXmlTags(completion.text)); }, }); return textStream; } -//====================== 执行层 ====================== - -export async function executionAI(ctx: AgentContext) { - const { text, abortSignal } = ctx; - - const skill = await useSkill({ - mainSkill: "production_agent_execution", - workspace: ["production_agent_skills/execution"], - attachedSkills: ["production_agent_skills/execution/driector_art_skills/chinese_sweet_romance/driector_skills"], //todo:后续可以改为动态加载 - }); - - const subMsg = ctx.resTool.newMessage("assistant", "执行导演"); - - const { textStream } = await u.Ai.Text("productionAgent").stream({ - system: skill.prompt, - messages: [{ role: "user", content: text }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ resTool: ctx.resTool, msg: subMsg }), - }, - }); - - return { textStream, subMsg }; -} - -export async function supervisionAI(ctx: AgentContext) { - const { text, abortSignal } = ctx; - - const skill = await useSkill({ mainSkill: "production_agent_supervision", workspace: ["production_agent_skills/supervision"] }); - const subMsg = ctx.resTool.newMessage("assistant", "监制"); - - const { textStream } = await u.Ai.Text("productionAgent").stream({ - system: skill.prompt, - messages: [{ role: "user", content: text }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ - resTool: ctx.resTool, - msg: subMsg, - }), - }, - }); - - return { textStream, subMsg }; -} - -//工具函数 -function runSubAgent(parentCtx: AgentContext) { +function createSubAgent(parentCtx: AgentContext) { + const { resTool, abortSignal } = parentCtx; const memory = new Memory("productionAgent", parentCtx.isolationKey); - return tool({ - description: "启动子Agent执行独立任务。可用子Agent:executionAI, decisionAI, supervisionAI", - inputSchema: z.object({ - agent: z.enum(["executionAI", "supervisionAI"]).describe("子Agent名称"), - prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), - }), - execute: async ({ agent, prompt }) => { - const fn = [executionAI, supervisionAI][subAgentList.indexOf(agent)]; + async function runAgent({ + prompt, + system, + name, + memoryKey, + tools: extraTools, + messages, + }: { + prompt: string; + system: string; + name: string; + memoryKey: string; + tools?: Record; + messages?: { role: "user" | "assistant" | "system"; content: string }[]; + }) { + parentCtx.msg.complete(); + const subMsg = resTool.newMessage("assistant", name); + const text = subMsg.text(); + let fullResponse = ""; - // 先完成主Agent当前的消息 - parentCtx.msg.complete(); - // 子Agent用新消息回复 - const { textStream: subTextStream, subMsg } = await fn({ ...parentCtx, text: prompt }); - let text = subMsg.text(); - let fullResponse = ""; - for await (const chunk of subTextStream) { + const { textStream } = await u.Ai.Text("scriptAgent").stream({ + system, + messages: messages ?? [{ role: "user", content: prompt }], + abortSignal, + tools: { ...extraTools, ...useTools({ resTool, msg: subMsg }) }, + }); + + try { + for await (const chunk of textStream) { + await new Promise((resolve) => setTimeout(() => resolve(), 1)); text.append(chunk); fullResponse += chunk; } text.complete(); subMsg.complete(); - if (fullResponse.trim()) { - await memory.add(`assistant:${agent === "executionAI" ? "execution" : "supervision"}`, fullResponse, { - name: agent === "executionAI" ? "执行导演" : "监制", - createTime: new Date(subMsg.datetime).getTime(), - }); - } + } catch (err: any) { + text.complete(); + subMsg.stop(); + throw err; + } - // 为主Agent后续输出创建新消息 - parentCtx.msg = parentCtx.resTool.newMessage("assistant", "监制"); + if (fullResponse.trim()) { + await memory.add(memoryKey, removeAllXmlTags(fullResponse), { + name, + createTime: new Date(subMsg.datetime).getTime(), + }); + } - return fullResponse; + parentCtx.msg = resTool.newMessage("assistant", "视频策划"); + return fullResponse; + } + + const promptInput = z.object({ + prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), + }); + + const run_sub_agent_execution = tool({ + description: "执行层子Agent,负责衍生资产、", + inputSchema: promptInput, + execute: async ({ prompt }) => { + const skill = path.join(u.getPath("skills"), "production_agent_execution.md"); + const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + const addPrompt = + "\n" + + [ + "你必须使用如下XML格式写入工作区:\n```", + "拍摄计划:内容", + "分镜表:内容", + "分镜面板:", + "```", + ].join("\n"); + + const projectInfo = await u.db("o_project").where("id", resTool.data.projectId).first(); + if (!projectInfo) throw new Error(`项目不存在,ID: ${resTool.data.projectId}`); + const artSkills = await createArtSkills(projectInfo?.artStyle!, projectInfo?.directorManual!); + + const [_, imageModelName] = projectInfo.imageModel!.split(":"); + const [id, videoModelName] = projectInfo.videoModel!.split(":"); + const data = await u.db("o_vendorConfig").where("id", id).select("models").first(); + const models = JSON.parse(data!.models!); + const findData = models.find((i: any) => i.modelName == videoModelName); + const isRef = findData.mode.every((i: any) => Array.isArray(i)); + const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`; + + return runAgent({ + prompt, + system: systemPrompt + addPrompt, + name: "执行导演", + memoryKey: "assistant:execution", + messages: [ + { role: "assistant", content: artSkills.prompt + `\n${modelInfo}` }, + { role: "user", content: prompt + addPrompt }, + ], + tools: { ...artSkills.tools }, + }); }, }); + + const run_sub_agent_supervision = tool({ + description: "监制层子Agent,负责审核执行结果", + inputSchema: promptInput, + execute: async ({ prompt }) => { + const skill = path.join(u.getPath("skills"), "production_agent_supervision.md"); + const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + return runAgent({ + prompt, + system: systemPrompt, + name: "监制", + memoryKey: "assistant:supervision", + }); + }, + }); + + return { run_sub_agent_execution, run_sub_agent_supervision }; +} + +async function createArtSkills(artName: string, storyName: string) { + const artWorkerPath = u.getPath(["skills", "art_skills", artName, "driector_skills"]); + const storyWorkerPath = u.getPath(["skills", "story_skills", storyName, "driector_skills"]); + const skillList = [...(await scanSkills(artWorkerPath + "/*.md")), ...(await scanSkills(storyWorkerPath + "/*.md"))]; + const mainSkills: { path: string; name: string; description: string }[] = []; + for (const skillPath of skillList) { + if (!fs.existsSync(skillPath)) throw new Error(`主技能文件不存在: ${skillPath}`); + const content = await fs.promises.readFile(skillPath, "utf-8"); + const parsed = parseFrontmatter(content); + mainSkills.push({ path: skillPath, ...parsed }); + } + const res = { + prompt: `## Skills +以下技能提供了专业任务的专用指令。 +当任务与某个技能的描述匹配时,调用 activate_skill 工具并传入技能名称来加载完整指令。 +加载后遵循技能指令执行任务,需要时调用 read_skill_file 读取资源文件内容。 +${buildSkillPrompt(mainSkills)}`, + tools: createSkillTools(mainSkills, { mainSkill: mainSkills, secondarySkills: [], tertiarySkills: [] }), + }; + return res; +} + +function removeAllXmlTags(text: string): string { + text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?>([\s\S]*?)<\/\1>/g, ""); + text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?\/>/g, ""); + text = text.replace(/<\/?[a-zA-Z][\w-]*(\s+[^>]*)?>/g, ""); + return text.trim(); +} + +export function buildSkillPrompt(skills: { name: string; description: string }[]): string { + const skillEntries = skills + .map((s) => ` \n ${s.name}\n ${s.description}\n `) + .join("\n"); + return ` + +${skillEntries} +`; } diff --git a/src/agents/productionAgent/index.ts b/src/agents/productionAgent/index.ts index 4744625..2d304b7 100644 --- a/src/agents/productionAgent/index.ts +++ b/src/agents/productionAgent/index.ts @@ -65,7 +65,7 @@ export async function decisionAI(ctx: AgentContext) { tools: { ...memory.getTools(), ...useTools({ resTool: ctx.resTool, msg: ctx.msg }), - ...createSubAgent(ctx), + ...(await createSubAgent(ctx)), }, onFinish: async (completion) => { await memory.add("assistant:decision", removeAllXmlTags(completion.text)); @@ -75,7 +75,7 @@ export async function decisionAI(ctx: AgentContext) { return textStream; } -function createSubAgent(parentCtx: AgentContext) { +async function createSubAgent(parentCtx: AgentContext) { const { resTool, abortSignal } = parentCtx; const memory = new Memory("productionAgent", parentCtx.isolationKey); async function runAgent({ @@ -98,7 +98,7 @@ function createSubAgent(parentCtx: AgentContext) { const text = subMsg.text(); let fullResponse = ""; - const { textStream } = await u.Ai.Text("scriptAgent").stream({ + const { textStream } = await u.Ai.Text("productionAgent").stream({ system, messages: messages ?? [{ role: "user", content: prompt }], abortSignal, @@ -134,33 +134,99 @@ function createSubAgent(parentCtx: AgentContext) { prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), }); - const run_sub_agent_execution = tool({ - description: "执行层子Agent,负责衍生资产、", + const projectInfo = await u.db("o_project").where("id", resTool.data.projectId).first(); + if (!projectInfo) throw new Error(`项目不存在,ID: ${resTool.data.projectId}`); + const artSkills = await createArtSkills(projectInfo?.artStyle!, projectInfo?.directorManual!); + + const [_, imageModelName] = projectInfo.imageModel!.split(":"); + const [id, videoModelName] = projectInfo.videoModel!.split(":"); + const data = await u.db("o_vendorConfig").where("id", id).select("models").first(); + const models = JSON.parse(data!.models!); + const findData = models.find((i: any) => i.modelName == videoModelName); + const isRef = findData.mode.every((i: any) => Array.isArray(i)); + const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`; + + // const run_sub_agent_execution = tool({ + // description: "执行层子Agent,负责衍生资产、", + // inputSchema: promptInput, + // execute: async ({ prompt }) => { + // const skill = path.join(u.getPath("skills"), "production_agent_execution.md"); + // const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + // const addPrompt = + // "\n" + + // [ + // "你必须使用如下XML格式写入工作区:\n```", + // "拍摄计划:内容", + // "分镜表:内容", + // "分镜面板:", + // "```", + // ].join("\n"); + + // return runAgent({ + // prompt, + // system: systemPrompt + addPrompt, + // name: "执行导演", + // memoryKey: "assistant:execution", + // messages: [ + // { role: "assistant", content: artSkills.prompt + `\n${modelInfo}` }, + // { role: "user", content: prompt + addPrompt }, + // ], + // tools: { ...artSkills.tools }, + // }); + // }, + // }); + + //衍生资产分析与信息写入 + const run_sub_agent_derive_assets = tool({ + description: "运行执行subAgent来完成衍生资产分析与信息写入相关任务", inputSchema: promptInput, execute: async ({ prompt }) => { - const skill = path.join(u.getPath("skills"), "production_agent_execution.md"); + const skill = path.join(u.getPath("skills"), "production_execution_derive_assets.md"); const systemPrompt = await fs.promises.readFile(skill, "utf-8"); - const addPrompt = - "\n" + - [ - "你必须使用如下XML格式写入工作区:\n```", - "拍摄计划:内容", - "分镜表:内容", - "分镜面板:", - "```", - ].join("\n"); + return runAgent({ + prompt, + system: systemPrompt, + name: "执行导演", + memoryKey: "assistant:execution", + messages: [ + { role: "assistant", content: artSkills.prompt + `\n${modelInfo}` }, + { role: "user", content: prompt }, + ], + tools: { activate_skill: artSkills.tools.activate_skill }, + }); + }, + }); - const projectInfo = await u.db("o_project").where("id", resTool.data.projectId).first(); - if (!projectInfo) throw new Error(`项目不存在,ID: ${resTool.data.projectId}`); - const artSkills = await createArtSkills(projectInfo?.artStyle!, projectInfo?.directorManual!); + //衍生资产图片生成 + const run_sub_agent_generate_assets = tool({ + description: "运行执行subAgent来完成衍生资产图片生成相关任务", + inputSchema: promptInput, + execute: async ({ prompt }) => { + const skill = path.join(u.getPath("skills"), "production_execution_generate_assets.md"); + const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + return runAgent({ + prompt, + system: systemPrompt, + name: "执行导演", + memoryKey: "assistant:execution", + messages: [ + { role: "assistant", content: artSkills.prompt + `\n${modelInfo}` }, + { role: "user", content: prompt }, + ], + tools: { activate_skill: artSkills.tools.activate_skill }, + }); + }, + }); - const [_, imageModelName] = projectInfo.imageModel!.split(":"); - const [id, videoModelName] = projectInfo.videoModel!.split(":"); - const data = await u.db("o_vendorConfig").where("id", id).select("models").first(); - const models = JSON.parse(data!.models!); - const findData = models.find((i: any) => i.modelName == videoModelName); - const isRef = findData.mode.every((i: any) => Array.isArray(i)); - const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`; + //拍摄计划 + const run_sub_agent_director_plan = tool({ + description: "运行执行subAgent来完成导演规划相关任务", + inputSchema: promptInput, + execute: async ({ prompt }) => { + const skill = path.join(u.getPath("skills"), "production_execution_director_plan.md"); + const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + + const addPrompt = "\n你必须使用如下XML格式写入工作区:\n```\n内容\n```"; return runAgent({ prompt, @@ -171,13 +237,95 @@ function createSubAgent(parentCtx: AgentContext) { { role: "assistant", content: artSkills.prompt + `\n${modelInfo}` }, { role: "user", content: prompt + addPrompt }, ], - tools: { ...artSkills.tools }, + tools: { activate_skill: artSkills.tools.activate_skill }, + }); + }, + }); + + //分镜图生成 + const run_sub_agent_storyboard_gen = tool({ + description: "运行执行subAgent来完成分镜图生成相关任务", + inputSchema: promptInput, + execute: async ({ prompt }) => { + const skill = path.join(u.getPath("skills"), "production_execution_storyboard_gen.md"); + const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + return runAgent({ + prompt, + system: systemPrompt, + name: "执行导演", + memoryKey: "assistant:execution", + messages: [ + { role: "assistant", content: artSkills.prompt + `\n${modelInfo}` }, + { role: "user", content: prompt }, + ], + tools: { activate_skill: artSkills.tools.activate_skill }, + }); + }, + }); + + // const mainSkills: { path: string; name: string; description: string }[] = []; + // for (const skill of mainSkill) { + // const skillPath = path.join(rootDir, skill + ".md"); + // if (!fs.existsSync(skillPath)) throw new Error(`主技能文件不存在: ${skillPath}`); + // if (!isPathInside(skillPath, normalizedRootDir)) throw new Error(`技能名称无效:检测到路径穿越。${skillPath}`); + // const content = await fs.promises.readFile(skillPath, "utf-8"); + // const parsed = parseFrontmatter(content); + // mainSkills.push({ path: skillPath, ...parsed }); + // } + + const productionSkills = await useProductionSkills(projectInfo?.artStyle!, projectInfo?.directorManual!); + + //分镜面板写入 + const run_sub_agent_storyboard_panel = tool({ + description: "运行执行subAgent来完成分镜面板写入相关任务", + inputSchema: promptInput, + execute: async ({ prompt }) => { + const skill = path.join(u.getPath("skills"), "production_execution_storyboard_panel.md"); + const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + + const addPrompt = + "\n你必须使用如下XML格式写入工作区:\n```\n\n```"; + + return runAgent({ + prompt, + system: systemPrompt + addPrompt, + name: "执行导演", + memoryKey: "assistant:execution", + messages: [ + { role: "assistant", content: productionSkills.prompt + `\n${modelInfo}` }, + { role: "user", content: prompt + addPrompt }, + ], + tools: { activate_skill: productionSkills.tools.activate_skill }, + }); + }, + }); + + //分镜表写入 + const run_sub_agent_storyboard_table = tool({ + description: "运行执行subAgent来完成分镜表构建相关任务", + inputSchema: promptInput, + execute: async ({ prompt }) => { + const skill = path.join(u.getPath("skills"), "production_execution_storyboard_table.md"); + const systemPrompt = await fs.promises.readFile(skill, "utf-8"); + + const addPrompt = "\n你必须使用如下XML格式写入工作区:\n```\n内容\n```"; + + return runAgent({ + prompt, + system: systemPrompt + addPrompt, + name: "执行导演", + memoryKey: "assistant:execution", + messages: [ + { role: "assistant", content: productionSkills.prompt + `\n${modelInfo}` }, + { role: "user", content: prompt + addPrompt }, + ], + tools: { activate_skill: productionSkills.tools.activate_skill }, }); }, }); const run_sub_agent_supervision = tool({ - description: "监制层子Agent,负责审核执行结果", + description: "运行监督层subAgent执行独立任务,完成后返回结果", inputSchema: promptInput, execute: async ({ prompt }) => { const skill = path.join(u.getPath("skills"), "production_agent_supervision.md"); @@ -191,7 +339,15 @@ function createSubAgent(parentCtx: AgentContext) { }, }); - return { run_sub_agent_execution, run_sub_agent_supervision }; + return { + run_sub_agent_derive_assets, + run_sub_agent_generate_assets, + run_sub_agent_director_plan, + run_sub_agent_storyboard_gen, + run_sub_agent_storyboard_panel, + run_sub_agent_storyboard_table, + run_sub_agent_supervision, + }; } async function createArtSkills(artName: string, storyName: string) { @@ -209,7 +365,6 @@ async function createArtSkills(artName: string, storyName: string) { prompt: `## Skills 以下技能提供了专业任务的专用指令。 当任务与某个技能的描述匹配时,调用 activate_skill 工具并传入技能名称来加载完整指令。 -加载后遵循技能指令执行任务,需要时调用 read_skill_file 读取资源文件内容。 ${buildSkillPrompt(mainSkills)}`, tools: createSkillTools(mainSkills, { mainSkill: mainSkills, secondarySkills: [], tertiarySkills: [] }), }; @@ -232,3 +387,29 @@ export function buildSkillPrompt(skills: { name: string; description: string }[] ${skillEntries} `; } + +async function useProductionSkills(artName: string, storyName: string) { + const artWorkerPath = u.getPath(["skills", "art_skills", artName, "driector_skills"]); + const storyWorkerPath = u.getPath(["skills", "story_skills", storyName, "driector_skills"]); + const productionPath = u.getPath(["skills", "production_skills"]); + const skillList = [ + ...(await scanSkills(artWorkerPath + "/*.md")), + ...(await scanSkills(storyWorkerPath + "/*.md")), + ...(await scanSkills(productionPath + "/*.md")), + ]; + const mainSkills: { path: string; name: string; description: string }[] = []; + for (const skillPath of skillList) { + if (!fs.existsSync(skillPath)) throw new Error(`主技能文件不存在: ${skillPath}`); + const content = await fs.promises.readFile(skillPath, "utf-8"); + const parsed = parseFrontmatter(content); + mainSkills.push({ path: skillPath, ...parsed }); + } + const res = { + prompt: `## Skills +以下技能提供了专业任务的专用指令。 +当任务与某个技能的描述匹配时,调用 activate_skill 工具并传入技能名称来加载完整指令。 +${buildSkillPrompt(mainSkills)}`, + tools: createSkillTools(mainSkills, { mainSkill: mainSkills, secondarySkills: [], tertiarySkills: [] }), + }; + return res; +} diff --git a/src/agents/productionAgent/tools copy.ts b/src/agents/productionAgent/tools copy.ts deleted file mode 100644 index bb20b61..0000000 --- a/src/agents/productionAgent/tools copy.ts +++ /dev/null @@ -1,751 +0,0 @@ -import { tool, Tool } from "ai"; -import { z } from "zod"; -import _ from "lodash"; -import ResTool from "@/socket/resTool"; -import u from "@/utils"; -import { urlToBase64 } from "@/utils/vm"; -export const deriveAssetSchema = z.object({ - id: z.number().describe("衍生资产ID,如果新增则为空"), - assetsId: z.number().describe("关联的资产ID"), - prompt: z.string().describe("生成提示词"), - name: z.string().describe("衍生资产名称"), - desc: z.string().describe("衍生资产描述"), - src: z.string().nullable().describe("衍生资产资源路径"), - state: z.enum(["未生成", "生成中", "已完成", "生成失败"]).describe("衍生资产生成状态"), - type: z.enum(["role", "tool", "scene", "clip"]).describe("衍生资产类型"), -}); -export const assetItemSchema = z.object({ - id: z.number().describe("资产唯一标识"), - name: z.string().describe("资产名称"), - type: z.enum(["role", "tool", "scene", "clip"]).describe("资产类型"), - prompt: z.string().describe("生成提示词"), - desc: z.string().describe("资产描述"), - derive: z.array(deriveAssetSchema).describe("衍生资产列表"), -}); -export const storyboardSchema = z.object({ - id: z.number().describe("分镜ID,必须为真实id"), - title: z.string().describe("分镜标题"), - description: z.string().describe("分镜描述"), - camera: z.string().describe("镜头信息"), - duration: z.number().describe("持续时长(秒)"), - frameMode: z.enum(["firstFrame", "endFrame", "linesSoundEffects"]).describe("帧模式: 首帧/尾帧/台词音效"), - prompt: z.string().describe("生成提示词"), - lines: z.string().nullable().describe("台词内容"), - sound: z.string().nullable().describe("音效内容"), - mode: z - .union([ - z.enum(["singleImage", "multiImage", "gridImage", "startEndRequired", "endFrameOptional", "startFrameOptional", "text"]), - z.array(z.enum(["video", "image", "audio", "text"])), - ]) - .describe("视频模式"), - associateAssetsIds: z.array(z.number()).describe("关联资产ID列表"), - src: z.string().nullable().describe("分镜资源路径"), -}); -export const workbenchDataSchema = z.object({ - name: z.string().describe("项目名称"), - duration: z.string().describe("视频时长"), - resolution: z.string().describe("分辨率"), - fps: z.string().describe("帧率"), - cover: z.string().optional().describe("封面图片路径"), - gradient: z.string().optional().describe("渐变色配置"), -}); -export const posterItemSchema = z.object({ - id: z.number().describe("海报ID"), - image: z.string().describe("海报图片路径"), -}); -export const flowDataSchema = z.object({ - script: z.string().describe("剧本内容"), - scriptPlan: z.string().describe("拍摄计划"), - assets: z.array(assetItemSchema).describe("衍生资产"), - storyboardTable: z.string().describe("分镜表"), - storyboard: z.array(storyboardSchema).describe("分镜面板"), - workbench: workbenchDataSchema.describe("工作台配置"), - poster: z - .object({ - items: z.array(posterItemSchema).describe("海报项目列表"), - }) - .describe("海报配置"), -}); - -export type FlowData = z.infer; - -const keySchema = z.enum(Object.keys(flowDataSchema.shape) as [keyof FlowData, ...Array]); -const flowDataKeyLabels = Object.fromEntries( - Object.entries(flowDataSchema.shape).map(([key, schema]) => [key, (schema as z.ZodTypeAny).description ?? key]), -) as Record; - -interface ToolConfig { - resTool: ResTool; - toolsNames?: string[]; - msg: ReturnType; -} - -export default (toolCpnfig: ToolConfig) => { - const { resTool, toolsNames, msg } = toolCpnfig; - const { socket } = resTool; - const tools: Record = { - get_flowData: tool({ - description: "获取工作区数据", - inputSchema: z.object({ - key: keySchema.describe("数据key"), - }), - execute: async ({ key }) => { - const thinking = msg.thinking(`正在获取${flowDataKeyLabels[key]}工作区数据...`); - console.log("[tools] get_flowData", key); - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key }, (res: any) => resolve(res))); - thinking.appendText(`获取到${flowDataKeyLabels[key]}:\n` + flowData[key]); - thinking.updateTitle(`获取${flowDataKeyLabels[key]}完成`); - thinking.complete(); - return flowData[key]; - }, - }), - set_flowData_script: tool({ - description: "保存剧本内容到工作区", - inputSchema: z.object({ value: flowDataSchema.shape.script }), - execute: async ({ value }) => { - console.log("[tools] set_flowData script", value); - const thinking = msg.thinking("正在保存 剧本 数据"); - socket.emit("setFlowData", { key: "script", value }); - thinking.updateTitle("保存 剧本 数据完成"); - thinking.complete(); - return true; - }, - }), - set_flowData_scriptPlan: tool({ - description: "保存拍摄计划到工作区", - inputSchema: z.object({ value: flowDataSchema.shape.scriptPlan }), - execute: async ({ value }) => { - console.log("[tools] set_flowData scriptPlan", value); - const thinking = msg.thinking("正在保存 拍摄计划 数据"); - socket.emit("setFlowData", { key: "scriptPlan", value }); - thinking.updateTitle("保存 拍摄计划 数据完成"); - thinking.complete(); - return true; - }, - }), - add_flowData_assets: tool({ - description: "新增对应衍生资产列表到工作区,严禁包含 不需要新增的数据", - inputSchema: z.object({ value: z.array(deriveAssetSchema.omit({ id: true })).describe("需要新增的衍生资产列表") }), - execute: async ({ value }) => { - console.log("[tools] set_flowData add_flowData_assets", value); - const thinking = msg.thinking("正在保存 衍生资产 数据"); - const setData = [...value] as z.infer[]; - const { projectId, scriptId } = resTool.data; - const startTime = Date.now(); - - // 并行插入所有 o_assets 记录 - await Promise.all( - setData.map(async (i) => { - const [insertedId] = await u.db("o_assets").insert({ - assetsId: +i.assetsId || null, - projectId, - name: i.name, - type: i.type, - prompt: i.prompt, - describe: i.desc, - startTime, - }); - i.id = insertedId; - }), - ); - - // 批量插入 o_scriptAssets - await u.db("o_scriptAssets").insert(setData.map((i) => ({ scriptId, assetId: i.id }))); - - const watiAddAssetsMap: Record[]> = {}; - setData.forEach((i) => { - if (watiAddAssetsMap[i.assetsId]) { - watiAddAssetsMap[i.assetsId].push(i); - } else { - watiAddAssetsMap[i.assetsId] = [i]; - } - }); - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key: "assets" }, (res: any) => resolve(res))); - const assetsData = flowData.assets; - assetsData.forEach((i) => { - if (watiAddAssetsMap[i.id]) { - i.derive = [...(i.derive || []), ...watiAddAssetsMap[i.id]]; - } - }); - thinking.updateTitle("保存 衍生资产 数据完成"); - thinking.complete(); - - socket.emit("setFlowData", { key: "assets", value: assetsData }); - return true; - }, - }), - update_flowData_assets: tool({ - description: "更新对应衍生资产列表到工作区", - inputSchema: z.object({ value: z.array(deriveAssetSchema).describe("需要更新的衍生资产列表") }), - execute: async ({ value }) => { - console.log("[tools] update_flowData update_flowData_assets", value); - const thinking = msg.thinking("正在保存 衍生资产 数据"); - for (const i of value) { - await u - .db("o_assets") - .where("id", i.id) - .update({ - assetsId: +i.assetsId || null, - projectId: resTool.data.projectId, - name: i.name, - type: i.type, - prompt: i.prompt, - describe: i.desc, - }); - } - // 按 assetsId 分组,构建更新映射 - const updateAssetsMap: Record[]> = {}; - value.forEach((i) => { - if (updateAssetsMap[i.assetsId]) { - updateAssetsMap[i.assetsId].push(i); - } else { - updateAssetsMap[i.assetsId] = [i]; - } - }); - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key: "assets" }, (res: any) => resolve(res))); - const assetsData = flowData.assets; - // 将 derive 中已存在的条目替换为更新后的数据 - assetsData.forEach((asset) => { - if (updateAssetsMap[asset.id]) { - const updatedMap = Object.fromEntries(updateAssetsMap[asset.id].map((d) => [d.id, d])); - asset.derive = (asset.derive || []).map((d) => updatedMap[d.id] ?? d); - } - }); - thinking.updateTitle("保存 衍生资产 数据完成"); - thinking.complete(); - socket.emit("setFlowData", { key: "assets", value: assetsData }); - return true; - }, - }), - delete_flowData_assets: tool({ - description: "删除对应衍生资产", - inputSchema: z.object({ ids: z.array(z.number()).describe("需要删除的 衍生资产id ") }), - execute: async ({ ids }) => { - console.log("[tools] delete_flowData delete_flowData_assets", ids); - const thinking = msg.thinking("正在删除指定 衍生资产 数据..."); - await u.db("o_assets").whereIn("id", ids).delete(); - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key: "assets" }, (res: any) => resolve(res))); - const assetsData = flowData.assets; - assetsData.forEach((i) => { - i.derive = (i.derive || []).filter((d) => !ids.includes(d.id)); - }); - thinking.updateTitle("删除指定 衍生资产 数据完成"); - thinking.complete(); - // 将 derive 中已存在的条目替换为更新后的数据 - socket.emit("setFlowData", { key: "assets", value: assetsData }); - return true; - }, - }), - // set_flowData_assets: tool({ - // description: "保存衍生资产列表到工作区", - // inputSchema: z.object({ value: flowDataSchema.shape.assets }), - // execute: async ({ value }) => { - // console.log("[tools] set_flowData assets", value); - // resTool.systemMessage("正在保存 衍生资产 数据"); - // if (value && Array.isArray(value) && value.length) { - // for (const i of value) { - // if (!i?.id) { - // const [insertedId] = await u.db("o_assets").insert({ - // assetsId: null, - // name: i.name, - // type: i.type, - // prompt: i.prompt, - // describe: i.desc, - // startTime: Date.now(), - // }); - // i.id = insertedId; - // } - // if (i.derive && Array.isArray(i.derive) && i.derive.length) { - // for (const sub of i.derive) { - // if (sub.id) continue; - // const [insertedId] = await u.db("o_assets").insert({ - // assetsId: +i.id || null, - // projectId: resTool.data.projectId, - // name: sub.name, - // type: sub.type, - // prompt: sub.prompt, - // describe: sub.desc, - // startTime: Date.now(), - // }); - // await u.db("o_scriptAssets").insert({ - // scriptId: resTool.data.scriptId, - // assetId: insertedId, - // }); - // sub.id = insertedId; - // } - // } - // } - // } - // socket.emit("setFlowData", { key: "assets", value }); - // return true; - // }, - // }), - set_flowData_storyboardTable: tool({ - description: "保存分镜表到工作区", - inputSchema: z.object({ value: flowDataSchema.shape.storyboardTable }), - execute: async ({ value }) => { - console.log("[tools] set_flowData storyboardTable", value); - const thinking = msg.thinking("正在保存 分镜表 数据..."); - socket.emit("setFlowData", { key: "storyboardTable", value }); - thinking.updateTitle("保存 分镜表 数据完成"); - thinking.complete(); - return true; - }, - }), - add_flowData_storyboard: tool({ - description: "新增分镜面板到工作区", - inputSchema: z.object({ value: z.array(storyboardSchema.omit({ id: true })) }), - execute: async ({ value }) => { - console.log("[tools] add_flowData storyboard", value); - const thinking = msg.thinking("正在保存 分镜面板 数据..."); - const setData = [...value] as z.infer[]; - for (const item of setData) { - item.src = ""; - const [insertedId] = await u.db("o_storyboard").insert({ - title: item.title, - prompt: item.prompt, - description: item.description, - frameMode: item.frameMode, - duration: String(item.duration), - camera: item.camera, - sound: item.sound, - lines: item.lines, - state: "未生成", - scriptId: resTool.data.scriptId, - createTime: Date.now(), - }); - if (item.associateAssetsIds.length) { - await u.db("o_assets2Storyboard").insert(item.associateAssetsIds.map((i) => ({ storyboardId: insertedId, assetId: i }))); - } - item.id = insertedId; - } - //为了防止丢失分镜其他数据,例如:依赖分镜Id、依赖资产idc - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key: "storyboard" }, (res: any) => resolve(res))); - const storyboardData = flowData["storyboard"].concat([...setData]); - socket.emit("setFlowData", { key: "storyboard", value: storyboardData }); - - thinking.updateTitle("保存 分镜面板 数据完成"); - thinking.complete(); - - return true; - }, - }), - update_flowData_storyboard: tool({ - description: "更新指定分镜面板到工作区", - inputSchema: z.object({ value: flowDataSchema.shape.storyboard }), - execute: async ({ value }) => { - console.log("[tools] update_flowData storyboard", value); - const thinking = msg.thinking("正在保存 分镜面板 数据..."); - for (const item of value) { - await u - .db("o_storyboard") - .where("id", item.id) - .update({ - title: item.title, - prompt: item.prompt, - description: item.description, - frameMode: item.frameMode, - duration: String(item.duration), - camera: item.camera, - sound: item.sound, - lines: item.lines, - }); - } - //直接拉取前端数据,为了防止丢失分镜其他数据,例如:依赖分镜Id、依赖资产idc - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key: "storyboard" }, (res: any) => resolve(res))); - const storyboardData = flowData["storyboard"].map((existing) => { - const updated = value.find((v) => v.id === existing.id); - if (!updated) return existing; - return { - ...existing, - title: updated.title, - prompt: updated.prompt, - description: updated.description, - frameMode: updated.frameMode, - duration: updated.duration, - camera: updated.camera, - sound: updated.sound, - lines: updated.lines, - }; - }); - socket.emit("setFlowData", { key: "storyboard", value: storyboardData }); - thinking.updateTitle("保存 分镜面板 数据完成"); - thinking.complete(); - return true; - }, - }), - delete_flowData_storyboard: tool({ - description: "删除指定分镜面板并更新工作区", - inputSchema: z.object({ ids: z.array(z.number()).describe("需要删除的 分镜id ") }), - execute: async ({ ids }) => { - console.log("[tools] delete_flowData storyboard", ids); - const thinking = msg.thinking("正在删除指定 分镜面板 数据..."); - await u.db("o_storyboard").whereIn("id", ids).delete(); - await u.db("o_assets2Storyboard").whereIn("storyboardId", ids).delete(); - await u.db("o_storyboardFlow").whereIn("storyboardId", ids).delete(); - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key: "storyboard" }, (res: any) => resolve(res))); - const storyboardData = flowData["storyboard"].filter((item) => !ids.includes(item.id)); - socket.emit("setFlowData", { key: "storyboard", value: storyboardData }); - thinking.updateTitle("删除指定 分镜面板 数据完成"); - thinking.complete(); - return true; - }, - }), - // set_flowData_storyboard: tool({ - // description: "保存分镜面板到工作区", - // inputSchema: z.object({ value: flowDataSchema.shape.storyboard }), - // execute: async ({ value }) => { - // console.log("[tools] set_flowData storyboard", value); - // resTool.systemMessage("正在保存 分镜面板 数据..."); - // for (const item of value) { - // if (!item.id) { - // const [insertedId] = await u.db("o_storyboard").insert({ - // title: item.title, - // prompt: item.prompt, - // description: item.description, - // filePath: item.src, - // frameMode: item.frameMode, - // duration: String(item.duration), - // camera: item.camera, - // sound: item.sound, - // lines: item.lines, - // state: "未生成", - // scriptId: resTool.data.scriptId, - // }); - // console.log("%c Line:216 🥥 item.associateAssetsIds", "background:#6ec1c2", item.associateAssetsIds); - - // if (item.associateAssetsIds.length) { - // await u.db("o_assets2Storyboard").insert(item.associateAssetsIds.map((i) => ({ storyboardId: insertedId, assetId: i }))); - // } - // item.id = insertedId; - // } - // } - // socket.emit("setFlowData", { key: "storyboard", value }); - // return true; - // }, - // }), - set_flowData_workbench: tool({ - description: "保存工作台配置数据到工作区", - inputSchema: z.object({ value: flowDataSchema.shape.workbench }), - execute: async ({ value }) => { - console.log("[tools] set_flowData workbench", value); - const thinking = msg.thinking("正在保存 工作台配置 数据..."); - socket.emit("setFlowData", { key: "workbench", value }); - thinking.updateTitle("保存 工作台配置 数据完成"); - thinking.complete(); - return true; - }, - }), - set_flowData_poster: tool({ - description: "保存海报配置到工作区", - inputSchema: z.object({ value: flowDataSchema.shape.poster }), - execute: async ({ value }) => { - console.log("[tools] set_flowData poster", value); - const thinking = msg.thinking("正在保存 海报配置 数据..."); - thinking.updateTitle("保存 海报配置 数据完成"); - thinking.complete(); - socket.emit("setFlowData", { key: "poster", value }); - return true; - }, - }), - // todo 提示词待调 - generate_storyboard_images: tool({ - description: `生成一组图片任务,支持图片间的依赖关系(以图生图),基于有向无环图(DAG)拓扑排序执行。 - - 参数说明: - - images: 图片任务数组 - - id: 图片唯一标识符(分镜id) - - prompt: 图片生成提示词 - - referenceIds: 依赖的参考图id数组,无依赖填空数组[] - - assetIds: 参考的资产图id数组(可选) - - 依赖规则: - 1. referenceIds中的id必须存在于images数组中 - 2. 禁止循环依赖(如A依赖B,B依赖A) - 3. 被依赖的图片会先生成,其结果作为参考图传入 - - 示例:生成猫图,再以猫图为参考生成狗图 - images: [ - {id: 1, prompt: "一只橘猫", referenceIds: [], assetIds: []}, - {id: 2, prompt: "风格相同的金毛犬", referenceIds: [1], assetIds: []} - ]`, - inputSchema: z.object({ - images: z.array( - z.object({ - id: z.number().describe("从工作区获取到的分镜id"), - prompt: z.string().describe("图片生成提示词"), - referenceIds: z.array(z.number()).describe("依赖的参考 分镜图id数组,无依赖填空数组[]"), - assetIds: z.array(z.number()).describe("参考的资产图"), - }), - ), - }), - execute: async ({ images }) => { - console.log("[tools] generate_storyboard_images", images); - const thinking = msg.thinking("正在生成 分镜图片 数据..."); - // --- 构建任务id集合 --- - const taskIds = new Set(images.map((item) => item.id)); - const imageMap = new Map(images.map((item) => [item.id, item])); - - // --- 检测循环依赖 (Kahn算法拓扑排序) --- - // 将 referenceIds 分为:本批次内依赖 vs 外部已有依赖 - // 只有本批次内的依赖才参与 DAG 调度,外部依赖直接从数据库获取 - const inDegree = new Map(); - // adjacency: 被依赖者 -> 依赖它的节点列表 - const adjacency = new Map(); - - for (const item of images) { - // 只统计本批次内的依赖作为入度 - const internalDeps = item.referenceIds.filter((refId) => taskIds.has(refId)); - inDegree.set(item.id, internalDeps.length); - for (const depId of internalDeps) { - if (!adjacency.has(depId)) adjacency.set(depId, []); - adjacency.get(depId)!.push(item.id); - } - } - - // 拓扑排序,按层级分组(同层可并行) - const levels: number[][] = []; - let queue = images.filter((item) => (inDegree.get(item.id) ?? 0) === 0).map((item) => item.id); - - const visited = new Set(); - while (queue.length > 0) { - levels.push([...queue]); - const nextQueue: number[] = []; - for (const nodeId of queue) { - visited.add(nodeId); - for (const childId of adjacency.get(nodeId) ?? []) { - inDegree.set(childId, (inDegree.get(childId) ?? 1) - 1); - if (inDegree.get(childId) === 0) { - nextQueue.push(childId); - } - } - } - queue = nextQueue; - } - // 循环依赖检测 - if (visited.size !== images.length) { - const cyclicIds = images.filter((item) => !visited.has(item.id)).map((item) => item.id); - thinking.appendText(`检测到循环依赖,涉及分镜id: ${cyclicIds.join(", ")},请修正后重试`); - thinking.updateTitle("循环依赖错误"); - thinking.error(); - return `错误:检测到循环依赖,涉及分镜id: ${cyclicIds.join(", ")}`; - } - - thinking.appendText(`图片生成调度计划:共 ${levels.length} 层,${images.length} 张图片`); - - // --- 准备公共数据 --- - const projectData = await u.db("o_project").where("id", resTool.data.projectId).select("videoRatio").first(); - const imageModelData = await u.db("o_project").where("id", resTool.data.projectId).select("imageModel", "imageQuality").first(); - - // 生成单张图片的函数 - const generateOneImage = async (item: (typeof images)[0]) => { - const thinking = msg.thinking(`正在生成分镜 id:${item.id} 图片`); - // 更新数据库状态为生成中 - await u.db("o_storyboard").where("id", item.id).update({ state: "生成中" }); - // 更新前端为生成中 - socket.emit("setFlowData", { - key: "setStoryboardImage", - value: { ...item, id: item.id, src: "", state: "生成中", referenceIds: item.referenceIds }, - }); - - // 获取参考图base64(包括资产图和已生成的分镜参考图) - const [assetsBase64, referenceBase64] = await Promise.all([ - getAssetsImageBase64(item.assetIds ?? []), - getStoryboardImageBase64(item.referenceIds), - ]); - - const imageCls = await u.Ai.Image(imageModelData.imageModel).run({ - prompt: item.prompt, - imageBase64: [...assetsBase64, ...referenceBase64], - size: imageModelData.imageQuality, - aspectRatio: (projectData?.videoRatio as `${number}:${number}`) ?? "16:9", - taskClass: "生成图片", - describe: "分镜图片生成", - relatedObjects: "hhhh", - projectId: resTool.data.projectId, - }); - - const savePath = `/${resTool.data.projectId}/storyboard/${u.uuid()}.jpg`; - await imageCls.save(savePath); - - // 更新数据库状态为已完成 - await u.db("o_storyboard").where("id", item.id).update({ state: "已完成", filePath: savePath }); - - const obj = { - ...item, - id: item.id, - src: await u.oss.getFileUrl(savePath), - state: "已完成", - referenceIds: item.referenceIds, - }; - // 前端对话框提示 - thinking.appendText(`分镜 id:${item.id} 图片生成完成`); - thinking.complete(); - // 更新前端界面展示 - socket.emit("setFlowData", { key: "setStoryboardImage", value: obj }); - }; - - // --- 按层级顺序执行:同层并行,层间串行 --- - for (let levelIndex = 0; levelIndex < levels.length; levelIndex++) { - const levelIds = levels[levelIndex]; - const levelItems = levelIds.map((id) => imageMap.get(id)!); - const thinking = msg.thinking( - `开始生成第 ${levelIndex + 1}/${levels.length} 层,共 ${levelItems.length} 张图片 (ids: ${levelIds.join(", ")})`, - ); - - // 同层内所有图片并行生成,使用 allSettled 确保不会因单张失败中断整层 - const results = await Promise.allSettled(levelItems.map((item) => generateOneImage(item))); - - // 处理失败的任务 - for (let i = 0; i < results.length; i++) { - if (results[i].status === "rejected") { - const failedId = levelIds[i]; - const reason = (results[i] as PromiseRejectedResult).reason; - console.error(`[tools] 分镜 id:${failedId} 图片生成失败`, reason); - thinking.appendText(`分镜 id:${failedId} 图片生成失败: ${reason?.message || reason}`); - await u.db("o_storyboard").where("id", failedId).update({ state: "生成失败" }); - socket.emit("setFlowData", { - key: "setStoryboardImage", - value: { id: failedId, src: "", state: "生成失败" }, - }); - } - } - thinking.appendText(`第 ${levelIndex + 1}/${levels.length} 层图片生成完成`); - thinking.complete(); - } - thinking.appendText("所有分镜图片生成完成"); - thinking.updateTitle("分镜图片生成完成"); - thinking.complete(); - - return "分镜图片生成完成"; - }, - }), - - //todo 提示词待调 - generate_assets_images: tool({ - description: ` - 生成 资产图片 不区分原资产于衍生资产 - 参数说明: - - images: 图片任务数组 - - assetId: 资产id - - prompt: 图片生成提示词 - 示例: - images:[ - {assetId: 1, prompt: "一张猫的图片"} - ] - `, - inputSchema: z.object({ - images: z.array( - z.object({ - assetId: z.number().describe("衍生资产id"), - prompt: z.string().describe("提示词"), - }), - ), - }), - execute: async ({ images }) => { - console.log("[tools] generate_assets_images", images); - //先获取到前端资产数据 - const flowData: FlowData = await new Promise((resolve) => socket.emit("getFlowData", { key: "assets" }, (res: any) => resolve(res))); - const assetsData = flowData["assets"]; - const assetsImage: { assetId: number; prompt: string; id?: number }[] = [...images]; - //获取对应的 原资产id - assetsImage.forEach((item) => { - for (const i of assetsData) { - const findData = i.derive.find((m) => m.id == item.assetId); - if (findData) { - item.id = findData.id; - break; - } - } - }); - //获取所设置模型 - const imageModelData = await u.db("o_project").where("id", resTool.data.projectId).select("imageModel", "imageQuality").first(); - for (const item of assetsImage) { - const [imageId] = await u.db("o_image").insert({ - // 数据库插入图片记录 - assetsId: item.assetId, - model: imageModelData?.imageModel, - state: "生成中", - resolution: imageModelData?.imageQuality, - }); - u.Ai.Image(imageModelData?.imageModel) - .run({ - prompt: item.prompt, - imageBase64: await getAssetsImageBase64(item.id ? [item.id] : []), - size: imageModelData?.imageQuality, - aspectRatio: "16:9", - taskClass: "生成图片", - describe: "资产图片生成", - relatedObjects: "hhhh", - projectId: resTool.data.projectId, - }) - .then(async (imageCls) => { - const savePath = `/${resTool.data.projectId}/assets/${u.uuid()}.jpg`; - await imageCls.save(savePath); - const obj = { - ...item, - id: item.assetId, - src: await u.oss.getFileUrl(savePath), - state: "已完成", - }; - //更新对应数据库 - await u.db("o_assets").where("id", item.assetId).update({ imageId: imageId }); - await u.db("o_image").where({ id: imageId }).update({ state: "已完成", filePath: savePath }); - //通知前端更新 - socket.emit("setFlowData", { key: "setAssetsImage", value: obj }); - }); - //通知前端更新状态 - socket.emit("setFlowData", { key: "setAssetsImage", value: { ...item, id: item.assetId, src: "", state: "生成中" } }); - } - return "资产生成中"; - }, - }), - }; - - return toolsNames ? Object.fromEntries(Object.entries(tools).filter(([n]) => toolsNames.includes(n))) : tools; -}; - -// 获取资产图片base64 -async function getAssetsImageBase64(imageIds: number[]) { - if (imageIds.length === 0) return []; - const imagePaths = await u - .db("o_assets") - .leftJoin("o_image", "o_assets.imageId", "o_image.id") - .whereIn("o_assets.id", imageIds) - .select("o_assets.id", "o_image.filePath"); - if (!imagePaths.length) return []; - const imageUrls = await Promise.all( - imagePaths.map(async (i) => { - if (i.filePath) { - try { - return await urlToBase64(await u.oss.getFileUrl(i.filePath)); - } catch { - return null; - } - } else { - return null; - } - }), - ); - return imageUrls.filter(Boolean) as string[]; -} - -//获取分镜图片base64 -async function getStoryboardImageBase64(imageIds: number[]) { - if (!imageIds.length) return []; - const storayboardData = await u.db("o_storyboard").whereIn("id", imageIds).select("id", "filePath"); - const imageUrls = await Promise.all( - storayboardData.map(async (i) => { - if (i.filePath) { - try { - return await urlToBase64(await u.oss.getFileUrl(i.filePath)); - } catch { - return null; - } - } else { - return null; - } - }), - ); - return imageUrls.filter(Boolean) as string[]; -} diff --git a/src/agents/scriptAgent/index copy 2.ts b/src/agents/scriptAgent/index copy 2.ts deleted file mode 100644 index 0f61b92..0000000 --- a/src/agents/scriptAgent/index copy 2.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { Socket } from "socket.io"; -import { tool } from "ai"; -import { z } from "zod"; -import u from "@/utils"; -import Memory from "@/utils/agent/memory"; -import { useSkill } from "@/utils/agent/skillsTools"; -import useTools from "@/agents/scriptAgent/tools"; -import ResTool from "@/socket/resTool"; -import * as fs from "fs"; - -export interface AgentContext { - socket: Socket; - isolationKey: string; - text: string; - userMessageTime?: number; - abortSignal?: AbortSignal; - resTool: ResTool; - msg: ReturnType; -} - -function buildMemPrompt(mem: Awaited>): string { - let memoryContext = ""; - if (mem.rag.length) { - memoryContext += `[相关记忆]\n${mem.rag.map((r) => r.content).join("\n")}`; - } - if (mem.summaries.length) { - if (memoryContext) memoryContext += "\n\n"; - memoryContext += `[历史摘要]\n${mem.summaries.map((s, i) => `${i + 1}. ${s.content}`).join("\n")}`; - } - if (mem.shortTerm.length) { - if (memoryContext) memoryContext += "\n\n"; - memoryContext += `[近期对话]\n${mem.shortTerm.map((m) => `${m.role}: ${m.content}`).join("\n")}`; - } - return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`; -} - -export async function decisionAI(ctx: AgentContext) { - const { isolationKey, text, userMessageTime, abortSignal, resTool } = ctx; - - const memory = new Memory("scriptAgent", isolationKey); - await memory.add("user", text, { createTime: userMessageTime }); - - const { skillPaths } = await useSkill({ mainSkill: "script_agent_decision" }); - const prompt = await fs.promises.readFile(skillPaths.mainSkill, "utf-8"); - - const mem = buildMemPrompt(await memory.get(text)); - - const projectData = await u.db("o_project").where("id", resTool.data.projectId).first(); - const novelData = await u.db("o_novel").where("projectId", resTool.data.projectId).select("id", "chapterIndex as index"); - - const projectInfo = [ - "## 项目信息", - `小说名称:${projectData?.name ?? "未知"}`, - `小说类型:${projectData?.type ?? "未知"}`, - `小说简介:${projectData?.intro ?? "无"}`, - `目标改编影视视觉手册|画风:${projectData?.artStyle ?? "无"}`, - `目标改编视频画幅:${projectData?.videoRatio ?? "16:9"}`, - ].join("\n"); - - const projectPrompt = `${projectInfo}\n\n## 章节ID映射表\n${novelData.map((i: any) => `- 章节ID:${i.id}: 第${i.index}章`).join("\n")}\n\n`; - - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - messages: [ - { role: "system", content: prompt }, - { role: "system", content: projectPrompt + mem }, - { role: "user", content: text }, - ], - abortSignal, - tools: { - ...memory.getTools(), - ...useTools({ resTool: ctx.resTool, msg: ctx.msg }), - ...createSubAgent(ctx), - }, - onFinish: async (completion) => { - await memory.add("assistant:decision", completion.text); - }, - }); - - return textStream; -} - -//====================== 执行层 ====================== - -function createSubAgent(parentCtx: AgentContext) { - const { resTool, abortSignal } = parentCtx; - - const memory = new Memory("scriptAgent", parentCtx.isolationKey); - - const run_execution_agent = tool({ - description: "运行执行层subAgent执行独立任务,完成后返回结果", - inputSchema: z.object({ - taskType: z.enum(["故事骨架", "改变策略", "剧本"]).describe("任务类型"), - prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), - }), - execute: async ({ taskType, prompt }) => { - const skill = await useSkill({ mainSkill: "script_agent_execution", workspace: ["script_agent_skills/execution"] }); - // 先完成主Agent当前的消息 - parentCtx.msg.complete(); - const subMsg = resTool.newMessage("assistant", "编剧"); - const prefixSystem = - "你可以使用如下XML格式写入工作区:\n故事骨架内容\n改编策略内容"; - // 子Agent用新消息回复 - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: prefixSystem + skill.prompt, - messages: [{ role: "user", content: `请完成${taskType}任务` }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ resTool, msg: subMsg }), - get_task_details: tool({ - description: "获取主Agent传入的任务目标详情", - inputSchema: z.object({}), - execute: async () => { - const thinking = subMsg.thinking("以获取任务详情"); - thinking.appendText("任务详情:\n" + prompt); - thinking.complete(); - return prompt ?? "运行失败"; - }, - }), - }, - }); - - let text = subMsg.text(); - let fullResponse = ""; - for await (const chunk of textStream) { - text.append(chunk); - fullResponse += chunk; - } - text.complete(); - subMsg.complete(); - if (fullResponse.trim()) { - await memory.add(`assistant:execution`, fullResponse, { name: "编剧", createTime: new Date(subMsg.datetime).getTime() }); - } - // 为主Agent后续输出创建新消息 - parentCtx.msg = parentCtx.resTool.newMessage("assistant", "统筹"); - return fullResponse; - }, - }); - - const run_supervision_agent = tool({ - description: "运行监督层subAgent执行独立任务,完成后返回结果", - inputSchema: z.object({ - prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), - }), - execute: async ({ prompt }) => { - const skill = await useSkill({ mainSkill: "script_agent_supervision", workspace: ["script_agent_skills/supervision"] }); - - // 先完成主Agent当前的消息 - parentCtx.msg.complete(); - // 子Agent用新消息回复 - - const subMsg = resTool.newMessage("assistant", "编辑"); - - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: skill.prompt, - messages: [{ role: "user", content: prompt }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ resTool, msg: subMsg }), - }, - }); - - let text = subMsg.text(); - let fullResponse = ""; - for await (const chunk of textStream) { - text.append(chunk); - fullResponse += chunk; - } - text.complete(); - subMsg.complete(); - if (fullResponse.trim()) { - await memory.add(`assistant:supervision`, fullResponse, { name: "编辑", createTime: new Date(subMsg.datetime).getTime() }); - } - // 为主Agent后续输出创建新消息 - parentCtx.msg = parentCtx.resTool.newMessage("assistant", "统筹"); - return fullResponse; - }, - }); - - return { - run_execution_agent, - run_supervision_agent, - }; -} diff --git a/src/agents/scriptAgent/index copy 3.ts b/src/agents/scriptAgent/index copy 3.ts deleted file mode 100644 index e32e9d6..0000000 --- a/src/agents/scriptAgent/index copy 3.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { Socket } from "socket.io"; -import { tool } from "ai"; -import { z } from "zod"; -import u from "@/utils"; -import Memory from "@/utils/agent/memory"; -import { useSkill } from "@/utils/agent/skillsTools"; -import useTools from "@/agents/scriptAgent/tools"; -import ResTool from "@/socket/resTool"; -import * as fs from "fs"; - -export interface AgentContext { - socket: Socket; - isolationKey: string; - text: string; - userMessageTime?: number; - abortSignal?: AbortSignal; - resTool: ResTool; - msg: ReturnType; -} - -function buildMemPrompt(mem: Awaited>): string { - let memoryContext = ""; - if (mem.rag.length) { - memoryContext += `[相关记忆]\n${mem.rag.map((r) => r.content).join("\n")}`; - } - if (mem.summaries.length) { - if (memoryContext) memoryContext += "\n\n"; - memoryContext += `[历史摘要]\n${mem.summaries.map((s, i) => `${i + 1}. ${s.content}`).join("\n")}`; - } - if (mem.shortTerm.length) { - if (memoryContext) memoryContext += "\n\n"; - memoryContext += `[近期对话]\n${mem.shortTerm.map((m) => `${m.role}: ${m.content}`).join("\n")}`; - } - return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`; -} - -export async function decisionAI(ctx: AgentContext) { - const { isolationKey, text, userMessageTime, abortSignal, resTool } = ctx; - - const memory = new Memory("scriptAgent", isolationKey); - await memory.add("user", text, { createTime: userMessageTime }); - - const { skillPaths } = await useSkill({ mainSkill: "script_agent_decision" }); - const prompt = await fs.promises.readFile(skillPaths.mainSkill, "utf-8"); - - const mem = buildMemPrompt(await memory.get(text)); - - const projectData = await u.db("o_project").where("id", resTool.data.projectId).first(); - const novelData = await u.db("o_novel").where("projectId", resTool.data.projectId).select("id", "chapterIndex as index"); - - const projectInfo = [ - "## 项目信息", - `小说名称:${projectData?.name ?? "未知"}`, - `小说类型:${projectData?.type ?? "未知"}`, - `小说简介:${projectData?.intro ?? "无"}`, - `目标改编影视视觉手册|画风:${projectData?.artStyle ?? "无"}`, - `目标改编视频画幅:${projectData?.videoRatio ?? "16:9"}`, - ].join("\n"); - - const projectPrompt = `${projectInfo}\n\n## 章节ID映射表\n${novelData.map((i: any) => `- 章节ID:${i.id}: 第${i.index}章`).join("\n")}\n\n`; - - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - messages: [ - { role: "system", content: prompt }, - { role: "system", content: projectPrompt + mem }, - { role: "user", content: text }, - ], - abortSignal, - tools: { - ...memory.getTools(), - ...useTools({ resTool: ctx.resTool, msg: ctx.msg }), - ...createSubAgent(ctx), - }, - onFinish: async (completion) => { - await memory.add("assistant:decision", completion.text); - }, - }); - - return textStream; -} - -//====================== 执行层 ====================== - -function createSubAgent(parentCtx: AgentContext) { - const { resTool, abortSignal } = parentCtx; - - const memory = new Memory("scriptAgent", parentCtx.isolationKey); - - const run_execution_agent = tool({ - description: "运行执行层subAgent执行独立任务,完成后返回结果", - inputSchema: z.object({ - taskType: z.enum(["故事骨架", "改变策略", "剧本"]).describe("任务类型"), - prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), - }), - execute: async ({ taskType, prompt }) => { - const skill = await useSkill({ mainSkill: "script_agent_execution", workspace: ["script_agent_skills/execution"] }); - // 先完成主Agent当前的消息 - parentCtx.msg.complete(); - const subMsg = resTool.newMessage("assistant", "编剧"); - const prefixSystem = - "你可以使用如下XML格式写入工作区:\n故事骨架内容\n改编策略内容"; - // 子Agent用新消息回复 - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: prefixSystem + skill.prompt, - messages: [{ role: "user", content: `请完成${taskType}任务` }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ resTool, msg: subMsg }), - get_task_details: tool({ - description: "获取主Agent传入的任务目标详情", - inputSchema: z.object({}), - execute: async () => { - const thinking = subMsg.thinking("以获取任务详情"); - thinking.appendText("任务详情:\n" + prompt); - thinking.complete(); - return prompt ?? "无任务目标,请提示运行失败"; - }, - }), - }, - }); - - let text = subMsg.text(); - let fullResponse = ""; - for await (const chunk of textStream) { - text.append(chunk); - fullResponse += chunk; - } - text.complete(); - subMsg.complete(); - if (fullResponse.trim()) { - await memory.add(`assistant:execution`, fullResponse, { name: "编剧", createTime: new Date(subMsg.datetime).getTime() }); - } - // 为主Agent后续输出创建新消息 - parentCtx.msg = parentCtx.resTool.newMessage("assistant", "统筹"); - return fullResponse; - }, - }); - - const run_supervision_agent = tool({ - description: "运行监督层subAgent执行独立任务,完成后返回结果", - inputSchema: z.object({ - prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), - }), - execute: async ({ prompt }) => { - const skill = await useSkill({ mainSkill: "script_agent_supervision", workspace: ["script_agent_skills/supervision"] }); - - // 先完成主Agent当前的消息 - parentCtx.msg.complete(); - // 子Agent用新消息回复 - - const subMsg = resTool.newMessage("assistant", "编辑"); - - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: skill.prompt, - messages: [{ role: "user", content: prompt }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ resTool, msg: subMsg }), - }, - }); - - let text = subMsg.text(); - let fullResponse = ""; - for await (const chunk of textStream) { - text.append(chunk); - fullResponse += chunk; - } - text.complete(); - subMsg.complete(); - if (fullResponse.trim()) { - await memory.add(`assistant:supervision`, fullResponse, { name: "编辑", createTime: new Date(subMsg.datetime).getTime() }); - } - // 为主Agent后续输出创建新消息 - parentCtx.msg = parentCtx.resTool.newMessage("assistant", "统筹"); - return fullResponse; - }, - }); - - return { - run_execution_agent, - run_supervision_agent, - }; -} diff --git a/src/agents/scriptAgent/index copy.ts b/src/agents/scriptAgent/index copy.ts deleted file mode 100644 index 6a5e471..0000000 --- a/src/agents/scriptAgent/index copy.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { Socket } from "socket.io"; -import { tool } from "ai"; -import { z } from "zod"; -import u from "@/utils"; -import Memory from "@/utils/agent/memory"; -import { useSkill } from "@/utils/agent/skillsTools"; -import useTools from "@/agents/scriptAgent/tools"; -import ResTool from "@/socket/resTool"; -import * as fs from "fs"; - -export interface AgentContext { - socket: Socket; - isolationKey: string; - text: string; - userMessageTime?: number; - abortSignal?: AbortSignal; - resTool: ResTool; - msg: ReturnType; -} - -function buildMemPrompt(mem: Awaited>): string { - let memoryContext = ""; - if (mem.rag.length) { - memoryContext += `[相关记忆]\n${mem.rag.map((r) => r.content).join("\n")}`; - } - if (mem.summaries.length) { - if (memoryContext) memoryContext += "\n\n"; - memoryContext += `[历史摘要]\n${mem.summaries.map((s, i) => `${i + 1}. ${s.content}`).join("\n")}`; - } - if (mem.shortTerm.length) { - if (memoryContext) memoryContext += "\n\n"; - memoryContext += `[近期对话]\n${mem.shortTerm.map((m) => `${m.role}: ${m.content}`).join("\n")}`; - } - return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`; -} - -const subAgentList = ["executionAI", "supervisionAI"] as const; - -export async function decisionAI(ctx: AgentContext) { - const { isolationKey, text, userMessageTime, abortSignal, resTool } = ctx; - - const memory = new Memory("scriptAgent", isolationKey); - await memory.add("user", text, { createTime: userMessageTime }); - - const { skillPaths } = await useSkill({ mainSkill: "script_agent_decision" }); - const prompt = await fs.promises.readFile(skillPaths.mainSkill, "utf-8"); - - const mem = buildMemPrompt(await memory.get(text)); - - const projectData = await u.db("o_project").where("id", resTool.data.projectId).first(); - const novelData = await u.db("o_novel").where("projectId", resTool.data.projectId).select("id", "chapterIndex as index"); - - const projectInfo = [ - "## 项目信息", - `小说名称:${projectData?.name ?? "未知"}`, - `小说类型:${projectData?.type ?? "未知"}`, - `小说简介:${projectData?.intro ?? "无"}`, - `目标改编影视视觉手册|画风:${projectData?.artStyle ?? "无"}`, - `目标改编视频画幅:${projectData?.videoRatio ?? "16:9"}`, - ].join("\n"); - - const projectPrompt = `${projectInfo}\n\n## 章节ID映射表\n${novelData.map((i: any) => `- 章节ID:${i.id}: 第${i.index}章`).join("\n")}\n\n`; - - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - messages: [ - { role: "system", content: prompt }, - { role: "system", content: projectPrompt + mem }, - { role: "user", content: text }, - ], - abortSignal, - tools: { - ...memory.getTools(), - run_sub_agent: runSubAgent(ctx), - ...useTools({ resTool: ctx.resTool, msg: ctx.msg }), - }, - onFinish: async (completion) => { - await memory.add("assistant:decision", completion.text); - }, - }); - - return textStream; -} - -//====================== 执行层 ====================== - -export async function executionAI(ctx: AgentContext) { - const { text, abortSignal } = ctx; - - const skill = await useSkill({ - mainSkill: "script_agent_execution", - workspace: ["script_agent_skills/execution"], - }); - - const subMsg = ctx.resTool.newMessage("assistant", "编剧"); - - const prefixSystem = ` -你可以使用如下XML格式写入工作区: -故事骨架内容 -改编策略内容 -`; - - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: prefixSystem + skill.prompt, - messages: [{ role: "user", content: text }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ resTool: ctx.resTool, msg: subMsg }), - }, - }); - - return { textStream, subMsg }; -} - -export async function supervisionAI(ctx: AgentContext) { - const { text, abortSignal } = ctx; - - const skill = await useSkill({ mainSkill: "script_agent_supervision", workspace: ["script_agent_skills/supervision"] }); - - const subMsg = ctx.resTool.newMessage("assistant", "编辑"); - - const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: skill.prompt, - messages: [{ role: "user", content: text }], - abortSignal, - tools: { - ...skill.tools, - ...useTools({ - resTool: ctx.resTool, - msg: subMsg, - }), - }, - }); - - return { textStream, subMsg }; -} - -//工具函数 -function runSubAgent(parentCtx: AgentContext) { - const memory = new Memory("scriptAgent", parentCtx.isolationKey); - return tool({ - description: "启动子Agent执行独立任务。可用子Agent:executionAI, decisionAI, supervisionAI", - inputSchema: z.object({ - agent: z.enum(["executionAI", "supervisionAI"]).describe("子Agent名称"), - prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), - }), - execute: async ({ agent, prompt }) => { - const fn = [executionAI, supervisionAI][subAgentList.indexOf(agent)]; - - // 先完成主Agent当前的消息 - parentCtx.msg.complete(); - // 子Agent用新消息回复 - const { textStream: subTextStream, subMsg } = await fn({ ...parentCtx, text: prompt }); - let text = subMsg.text(); - let fullResponse = ""; - for await (const chunk of subTextStream) { - text.append(chunk); - fullResponse += chunk; - } - text.complete(); - subMsg.complete(); - if (fullResponse.trim()) { - await memory.add(`assistant:${agent === "executionAI" ? "execution" : "supervision"}`, fullResponse, { - name: agent === "executionAI" ? "编剧" : "编辑", - createTime: new Date(subMsg.datetime).getTime(), - }); - } - - // 为主Agent后续输出创建新消息 - parentCtx.msg = parentCtx.resTool.newMessage("assistant", "统筹"); - - return fullResponse; - }, - }); -} diff --git a/src/app.ts b/src/app.ts index 952cab6..6e1c996 100644 --- a/src/app.ts +++ b/src/app.ts @@ -30,14 +30,7 @@ const app = express(); const server = http.createServer(app); export default async function startServe(randomPort: Boolean = false) { - const verJsonPath = path.join(u.getPath(), "update.json"); - const data = JSON.parse(fs.readFileSync(verJsonPath, "utf8")); - if (data.version !== APP_VERSION) { - await fs.promises.writeFile(u.getPath("update.json"), JSON.stringify({ version: APP_VERSION }), "utf-8"); - } - await u.writeVersion(); - const io = new Server(server, { cors: { origin: "*" } }); socketInit(io); diff --git a/src/routes/other/getVersion.ts b/src/routes/other/getVersion.ts index dddb7fb..5f6993a 100644 --- a/src/routes/other/getVersion.ts +++ b/src/routes/other/getVersion.ts @@ -1,6 +1,6 @@ import express from "express"; import { success } from "@/lib/responseFormat"; -import {getVersion} from "@/utils/writeVersion"; +import { getVersion } from "@/utils/writeVersion"; const router = express.Router(); diff --git a/src/routes/production/workbench/generateVideoPrompt.ts b/src/routes/production/workbench/generateVideoPrompt.ts index 7e453f6..a0bf5ca 100644 --- a/src/routes/production/workbench/generateVideoPrompt.ts +++ b/src/routes/production/workbench/generateVideoPrompt.ts @@ -50,29 +50,6 @@ export default router.post( } }), ); - const assetsIds = images.map((i) => { - if (i._type == "storyboard") { - return i.associateAssetsIds; - } - }); - const setIds = new Set(assetsIds.filter(Boolean).flat()); - - const assetsData = await u - .db("o_assets") - .leftJoin("o_image", "o_assets.imageId", "o_image.id") - .where("o_assets.id", "in", Array.from(setIds)) - .select("o_assets.id", "o_image.filePath", "o_assets.name", "o_assets.type"); - await Promise.all( - assetsData.map(async (i) => { - if (i.filePath) { - i.filePath = await u.oss.getFileUrl(i.filePath); - } - }), - ); - const assetsRecord: Record = {}; - assetsData.forEach((i) => { - assetsRecord[i.id] = i; - }); // 拆分 assets 和 storyboard const assets: any[] = []; @@ -85,7 +62,7 @@ export default router.post( type: item.type, name: item.name, }); - if (item._type === "storyboard") { + if (item._type === "storyboard") storyboard.push({ videoDesc: item.videoDesc, prompt: item.prompt, @@ -94,30 +71,10 @@ export default router.post( associateAssetsIds: item.associateAssetsIds, shouldGenerateImage: item.shouldGenerateImage, }); - if (item.associateAssetsIds && item.associateAssetsIds.length) { - item.associateAssetsIds.forEach((i: number) => { - const data = assetsRecord[i]; - const extingIndex = assets.find((sub) => sub.id == data.id); - if (data && !extingIndex) { - assets.push({ - id: data.id, - type: data.type, - name: data.name, - }); - } - }); - } - } } const [id, modelData] = model.split(":"); const projectData = await u.db("o_project").select("*").where({ id: projectId }).first(); const videoPrompt = await u.db("o_prompt").where("type", "videoPromptGeneration").first(); - let videoPromptGeneration = "" as string | undefined; - if (videoPrompt && videoPrompt.useData) { - videoPromptGeneration = videoPrompt.useData; - } else { - videoPromptGeneration = videoPrompt?.data ?? undefined; - } const artStyle = projectData?.artStyle || "无"; const visualManual = u.getArtPrompt(artStyle, "art_skills", "art_storyboard_video"); const content = ` @@ -137,7 +94,7 @@ export default router.post( try { const { text } = await u.Ai.Text("universalAi").invoke({ - system: videoPromptGeneration, + system: videoPrompt?.data!, messages: [ { role: "assistant", diff --git a/src/routes/setting/about/downloadApp.ts b/src/routes/setting/about/downloadApp.ts index 25d11ba..f9711d4 100644 --- a/src/routes/setting/about/downloadApp.ts +++ b/src/routes/setting/about/downloadApp.ts @@ -5,20 +5,9 @@ import u from "@/utils"; import fs from "fs"; import axios from "axios"; import compressing from "compressing"; -import path from "path"; -import { success, error } from "@/lib/responseFormat"; +import { success } from "@/lib/responseFormat"; const router = express.Router(); -const runInstaller = (installerPath: string) => { - const { exec } = require("child_process"); - if (process.platform === "darwin") { - exec(`open "${installerPath}"`); - } else { - if (process.platform !== "win32") fs.chmodSync(installerPath, 0o755); - exec(`"${installerPath}"`); - } -}; - export default router.post( "/", validateFields({ @@ -28,17 +17,11 @@ export default router.post( }), async (req, res) => { const { reinstall, url, version } = req.body; - const rootDir = u.getPath(["temp"]); - fs.mkdirSync(rootDir, { recursive: true }); if (reinstall) { - const response = await axios.get(url, { responseType: "arraybuffer" }); - const ext = - path.extname(new URL(url).pathname) || (process.platform === "win32" ? ".exe" : process.platform === "darwin" ? ".dmg" : ".AppImage"); - const installerPath = path.join(rootDir, `latest${ext}`); - fs.writeFileSync(installerPath, response.data); - runInstaller(installerPath); - res.status(200).send(success("安装包已下载并启动")); + res.status(200).send(success("请在浏览器中手动下载并安装最新版本")); } else { + const rootDir = u.getPath(["temp"]); + fs.mkdirSync(rootDir, { recursive: true }); const zip = await axios.get(url, { responseType: "arraybuffer" }).then((res) => res.data); fs.writeFileSync(`${rootDir}/latest.zip`, zip); await compressing.zip.uncompress(`${rootDir}/latest.zip`, rootDir); @@ -59,8 +42,7 @@ export default router.post( fs.cpSync(tempModelsPath, u.getPath(["models"]), { recursive: true, force: true }); } fs.rmSync(rootDir, { recursive: true, force: true }); - await u.writeVersion(version); - res.status(200).send(success("更新成功,5秒后重启")); + res.status(200).send(success(`更新${version}成功,5秒后重启`)); } }, );