feat(video-from-script): 视频生成阶段增加重复任务检测与原子状态标记

在视频生成流水线中添加两项关键改进:

1. 在 `cmdNext` 中提前将条目状态标记为 `processing` 并持久化,防止同一行被多个并行进程重复取出处理
2. 在 `phaseVideos` 中增加磁盘兜底检测:对无 `video` 字段的条目,根据 `id` 扫描本地视频目录,若发现已有视频文件则恢复引用并跳过生成
3. 优化状态过滤逻辑:`done` 状态且已有视频文件的条目明确跳过并输出原因,减少冗余日志
This commit is contained in:
2026-05-17 16:50:26 +08:00
parent 4495ea8af1
commit 65af6c92fc
2 changed files with 24 additions and 1 deletions

View File

@@ -304,6 +304,11 @@ function cmdNext(args) {
return
}
// 原子标记为 processing防止同一行被重复取出
item.status = 'processing'
batch.stats = calcStats(batch.items)
writeJson(manifestPath, batch)
const result = {
done: false,
row: item.row,

View File

@@ -43,6 +43,8 @@ async function phaseVideos(manifest, manifestPath, options) {
const videoCandidates = manifest.items.filter(it => {
if (it.confirmed === false) return false
if (!it.url || !it.videoPrompt) return false
// 已有视频(本地文件或远程 URL且状态为 done → 跳过,避免重复生成
if (it.status === 'done' && (it.video || it.videoUrl)) return false
return ['done', 'pending', 'failed'].includes(it.status)
})
@@ -54,7 +56,9 @@ async function phaseVideos(manifest, manifestPath, options) {
if (it.confirmed === false) reasons.push("confirmed=false")
if (!it.url) reasons.push("缺少 url图片未上传")
if (!it.videoPrompt) reasons.push("缺少 videoPrompt")
if (it.confirmed !== false && it.url && it.videoPrompt && !["done","pending","failed"].includes(it.status)) {
if (it.status === 'done' && (it.video || it.videoUrl)) {
reasons.push("视频已生成,已跳过")
} else if (!["done","pending","failed"].includes(it.status)) {
reasons.push("status=" + (it.status || "undefined") + "(不在 done/pending/failed 中)")
}
console.log(" - item", it.id || manifest.items.indexOf(it), ":", reasons.length > 0 ? reasons.join(", ") : "已满足全部条件(不应在此)")
@@ -66,6 +70,20 @@ async function phaseVideos(manifest, manifestPath, options) {
const items = []
for (const it of videoCandidates) {
// 磁盘兜底:本地视频文件已存在则恢复引用并跳过
if (!it.video && it.id) {
const fs = require('fs')
const existingVideos = fs.readdirSync(videosDir).filter(f =>
f.includes('_item' + it.id + '_') || f.includes('_item' + it.id + '.')
)
if (existingVideos.length > 0) {
it.video = 'videos/' + existingVideos[existingVideos.length - 1]
it.status = 'done'
delete it.videoTaskId
log('videos', ` item ${it.id} 发现已有视频文件 ${it.video},跳过生成`)
continue
}
}
if (it.video || it.videoUrl) {
if (it.status === 'done') continue
delete it.video