feat(video-pipeline): 重构视频流水线,优化成片时间线规则和状态管理
- 引入 manifest.json 作为唯一状态源,所有子 Agent 操作回写 manifest - 重构 timebuilder 逻辑,支持四种视频适配策略(加速/裁剪/放缓/画面停顿) - 统一 TTS 阶段输出结构,单句和多句均写入 segments[] - 重写字幕和配音生成,基于 segments 精确时长实现音画同步 - 新增 confirm 命令支持按 id 范围确认,上传阶段分离图片和视频 - 添加中间产物写入 output/ 目录的约束,清理废弃配置参数
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { loadAccountConfig, saveManifest, ensureDir, ACCOUNTS_DIR, SKILLS_DIR } = require('./pipeline-utils')
|
||||
const { loadAccountConfig, saveManifest, ensureDir, slugify, ACCOUNTS_DIR, SKILLS_DIR } = require('./pipeline-utils')
|
||||
|
||||
function initManifest(options) {
|
||||
const { account: accountId, mode, items: itemsJson, itemsFile } = options
|
||||
@@ -40,7 +40,8 @@ function initManifest(options) {
|
||||
}
|
||||
|
||||
// 校验必填字段
|
||||
const requiredFields = ['shotDesc', 'script', 'imagePrompt']
|
||||
const requiredFields = ['shotDesc', 'script']
|
||||
const optionalFields = ['imagePrompt', 'videoPrompt', 'lastFramePrompt']
|
||||
const resolvedMode = mode || 'single'
|
||||
|
||||
for (let i = 0; i < rawItems.length; i++) {
|
||||
@@ -52,8 +53,7 @@ function initManifest(options) {
|
||||
}
|
||||
}
|
||||
if (resolvedMode === 'framePair' && !item.lastFramePrompt) {
|
||||
console.error(`错误: 首尾帧模式 items[${i}] 缺少 "lastFramePrompt"(imagePrompt 作为第一帧)`)
|
||||
process.exit(1)
|
||||
delete item.lastFramePrompt // 首尾帧模式 Step 2-A 补充
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +68,11 @@ function initManifest(options) {
|
||||
|
||||
// 构建 items
|
||||
const items = rawItems.map((raw, i) => {
|
||||
const slug = slugify(raw.shotDesc || raw.script || `scene_${i + 1}`)
|
||||
const item = {
|
||||
id: i + 1,
|
||||
status: 'pending',
|
||||
file: `images/scene_${String(i + 1).padStart(2, '0')}_${slug}.jpeg`,
|
||||
shotDesc: raw.shotDesc || '',
|
||||
script: raw.script || '',
|
||||
duration: raw.duration || 5,
|
||||
@@ -129,7 +131,13 @@ function initManifest(options) {
|
||||
console.log(` 画幅: ${manifest.format}, 模式: ${manifest.mode}`)
|
||||
console.log(` Items: ${items.length}`)
|
||||
console.log(` 参考图: ${references.length}`)
|
||||
if (items.some(it => !it.videoPrompt)) {
|
||||
if (items.some(it => !it.imagePrompt)) {
|
||||
console.log(` ⚠ ${items.filter(it => !it.imagePrompt).length} 个 item 缺少 imagePrompt,请运行 Step 2-A(图片提示词)补充`)
|
||||
}
|
||||
if (resolvedMode === 'framePair' && items.some(it => !it.lastFramePrompt)) {
|
||||
console.log(` ⚠ ${items.filter(it => !it.lastFramePrompt).length} 个 item 缺少 lastFramePrompt,请运行 Step 2-A 补充`)
|
||||
}
|
||||
if (items.some(it => !it.videoPrompt && resolvedMode !== 'framePair')) {
|
||||
console.log(` ⚠ ${items.filter(it => !it.videoPrompt).length} 个 item 缺少 videoPrompt,生视频阶段将跳过`)
|
||||
}
|
||||
console.log()
|
||||
|
||||
Reference in New Issue
Block a user