Files
video-create/.claude/skills/video-from-script/scripts/lib/phase-upload.js
sion123 0998fd6ae1 feat(video-pipeline): 重构视频流水线,优化成片时间线规则和状态管理
- 引入 manifest.json 作为唯一状态源,所有子 Agent 操作回写 manifest
- 重构 timebuilder 逻辑,支持四种视频适配策略(加速/裁剪/放缓/画面停顿)
- 统一 TTS 阶段输出结构,单句和多句均写入 segments[]
- 重写字幕和配音生成,基于 segments 精确时长实现音画同步
- 新增 confirm 命令支持按 id 范围确认,上传阶段分离图片和视频
- 添加中间产物写入 output/ 目录的约束,清理废弃配置参数
2026-05-02 00:14:40 +08:00

76 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Phase: upload — OSS 上传
*
* 将图片(含首尾帧)和视频上传到 OSS回写 url / videoUrl
*/
const path = require('path')
const { saveManifest, log, getManifestDir } = require('./pipeline-utils')
async function phaseUpload(manifest, manifestPath) {
const dir = getManifestDir(manifestPath)
const { uploadFile } = require('../oss-upload')
// 图片(含首尾帧 first frame
const imageItems = manifest.items.filter(it =>
it.status === 'done' && it.file && !it.url
)
// 视频
const videoItems = manifest.items.filter(it =>
it.status === 'done' && it.video && !it.videoUrl
)
if (imageItems.length === 0 && videoItems.length === 0) {
log('upload', '无待上传文件,跳过')
return
}
// 上传图片
if (imageItems.length > 0) {
log('upload', `图片: ${imageItems.length}`)
for (let i = 0; i < imageItems.length; i++) {
const item = imageItems[i]
const filePath = path.resolve(dir, item.file)
try {
const { url } = await uploadFile(filePath)
item.url = url
log('upload', ` [${i + 1}/${imageItems.length}] ${item.file} → OK`)
} catch (err) {
item.error = `上传失败: ${err.message}`
log('upload', ` [${i + 1}/${imageItems.length}] 失败: ${err.message}`)
}
// 首尾帧模式:上传 lastFrame
if (item.url && item.lastFrame && !item.lastFrameUrl) {
const lastPath = path.resolve(dir, item.lastFrame)
try {
const { url } = await uploadFile(lastPath)
item.lastFrameUrl = url
log('upload', ` [${i + 1}/${imageItems.length}] lastFrame → OK`)
} catch (err) {
log('upload', ` [${i + 1}/${imageItems.length}] lastFrame 上传失败: ${err.message}`)
}
}
saveManifest(manifestPath, manifest)
}
}
// 上传视频
if (videoItems.length > 0) {
log('upload', `视频: ${videoItems.length}`)
for (let i = 0; i < videoItems.length; i++) {
const item = videoItems[i]
const videoPath = path.resolve(dir, item.video)
try {
const { url } = await uploadFile(videoPath)
item.videoUrl = url
log('upload', ` [${i + 1}/${videoItems.length}] ${item.video} → OK`)
} catch (err) {
log('upload', ` [${i + 1}/${videoItems.length}] 失败: ${err.message}`)
}
saveManifest(manifestPath, manifest)
}
}
}
module.exports = { phaseUpload }