video-prompt.md 9.1 KB

视频生成模板(video-prompt)

提炼自 kb-raw/04-SOP工作流/…/flow/4-视频生成prompt.md(含降级策略与图片压缩), 参数约束以本仓实测为准(见 references/jimeng-api.md)。

这是 VOC-SOP 阶段 4b 的提示词与参数规范:把关键帧变成 AI 视频片段。 本技能对应 fmode-mv video。


一、参数约束(★ 实测修正过 KB 的记载)

参数 约束 说明
frames [121, 241] 且 ≡ 1 (mod 24) 合法值只有 121/145/169/193/217/241
单镜时长 只能是 5~10 秒的整数秒 frames = 24 × 秒数 + 1
method '2' 首帧 / '3' 首尾帧 '3' 需要 2 张同比例图
config.image_urls method=2 → 1 张;method=3 → [首帧, 尾帧] 2 张
首帧图比例 长边 / 短边 ≤ 3 否则被拒
尾帧图比例 必须与首帧相同(method=3)
分辨率 统一 720p(¥0.28/秒)省成本 1080p ¥0.63/秒;Pro ¥1/秒
prompt 长度 建议 ≤400 字,最长 800 字
输出画幅 跟随输入图,不跟随 sizeDate

⚠️ KB 只说「范围 [121,241]」,实测还要求 frames % 24 === 1。 传 122 会被拒:x2v pipeline: frames % 24 should be 1。 所以不存在 3 秒或 13 秒的镜头 —— 这一点会反过来约束分镜设计。


二、图片预处理(生成视频前必做)

即梦只吃公网 URL,且对二进制体积有限制(约 4–5MB base64 字符串)。 大 PNG 直传报 Image Decode Error: invalid binary data file size。

// KB 的 sharp 版
const sharp = require('sharp');
await sharp(inputPath).resize(1280, 720).jpeg({ quality: 80 }).toFile(outputPath);
// 2560×1440 PNG (~5.6MB) → 1280×720 JPEG (~200KB);base64 从 ~750万字符降到 ~28万字符
// 本技能仓的零依赖版(lib/jimeng.mjs 的 prepareImageUrl()):ffmpeg 压缩 + 七牛上传
ffmpeg -y -v error -i in.png \
  -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" \
  -q:v 4 out.jpg
// 再 POST /parse/functions/qiniu_uptoken 拿 uptoken → multipart 上传 → 返回 https 直链

法一需要 npm i sharp;本仓选法二(保持零 npm 依赖)。


三、生成方式选择(第一镜 vs 其余)

位置 方式 理由
第 1 段 method=3(首尾帧) 用第 2 镜的关键帧做尾帧,做「空间推进」转场
其余段 method=2(首帧) 更稳、更省,失败率低
末段(可选) method=3 与首帧呼应闭环(KB 版本4 的做法:仅第 1、9 段用 method=3)
场景跨度大的段 必须 method=2 室内→室外、人物→空镜这类两帧会崩坏

3.1 场景跨度大时禁用 method=3(硬规则)

method=3 只用于这三种情况:

  1. 同场景的连续动作
  2. 相似场景的过渡
  3. 数据 / 状态渐变

其余一律 method=2。

3.2 首尾帧设计要点

  • 同一人物:同服装、同发型、同配饰、同场景基本元素;提示词中明确「与首帧同一人物」。
  • 呼应三层:视觉(同机位/同构图/同环境,不同细节)、情感(消极→积极)、主题(核心道具变化)。
  • 写法模板:「与首帧[相同的房间/位置/人物],但[表情不同/服装不同/光线不同],展示变化和成长」

四、method=3 降级策略(必须内置)

KB 原话:method=3 比 method=2 更容易失败 —— 两张图数据量翻倍、首尾帧对画面一致性要求更高。

async function generateVideo(data) {
  if (data.method === '3') {
    const result = await submitVideo({ ...data, method: '3' });
    if (result.data?.workId) return pollAndDownload(result.data.workId);
    console.log('method=3 失败,降级为 method=2');
  }
  // 降级:只传首帧
  return submitVideo({ ...data, method: '2' });
}

降级后必须做两件事:

  1. 把 prompt 改成描述「从首帧到预期效果的过渡」(因为失去了尾帧约束)
  2. 在产物与日志里留痕(本技能用 degraded: true + 日志写明「已从 method=3 降级」)

绝不静默降级。 用户必须能分清哪些镜头是首尾帧、哪些是退而求其次的首帧。


五、运镜与音效(每镜必填)

5.1 运镜词库(一镜一种,禁止叠加)

运镜 适用
固定机位静止 强调等待/结果/冲击;AI 最稳,优先使用
缓慢推近 靠近情绪、紧张升级
缓慢拉远 释放空间、收尾
横向跟随 跟随主体位移
缓慢上摇 / 下摇 揭示垂直空间
手持轻微晃动 真实感、临场感

禁止:「推 + 环绕 + 上摇」叠加;环绕镜头一律不用。

5.2 音效描述(prompt 必须包含)

每个视频的 prompt 中必须包含背景音效描述。

示例:温暖氛围音乐|励志管弦乐|科技感电子音|雨声与远处车流|钢琴单音| 海浪与环境风声|咖啡馆背景人声|心跳声渐强|低沉的弦乐 drone

5.3 运动真实(防「AI 味」,来自版本5 的结论)

视频侧从「画面真实」转向「运动真实」,prompt 里强制加:

  • 手持微抖动(而非丝滑漂浮)
  • 自然眨眼、呼吸、重心转移
  • motion blur
  • consistent identity & lighting
  • 环境动态(树叶、衣物、光影流动)
  • 节奏不要太「AI」(动作不过于均匀同步)

六、视频 prompt 骨架(可直接抄)

{{主体动作,一句话}},
{{镜头运动:slow push in / pull back / pan left / handheld micro-shake}},
{{运动真实约束:gentle natural motion, subtle handheld micro-shake, natural breathing,
  hair strands catching the light, motion blur, consistent identity and lighting}},
{{音效描述:warm ambient piano / tense low strings / rain and distant traffic}},
{{画质词:4k, cinematic, film grain, shallow depth of field}}

中文示例(改写为英文后投喂):

女子在窗边缓缓转头看向镜头,阳光掠过发丝; 镜头缓慢推近;手持轻微晃动,自然呼吸节奏,发丝随风轻摆,运动模糊自然; 温暖氛围钢琴;4k 高清,电影感,胶片颗粒


七、完整配置对象

{
  id: 1,
  name: '第1段视频 - 开场推镜',
  method: '3',                     // '3'=首尾帧(第一段), '2'=首帧
  frames: 121,                     // 5 秒;必须 ∈ {121,145,169,193,217,241}
  resolution: '720p',              // 省钱统一 720p
  firstImage: 'photo1.png',
  lastImage: 'photo2.png',         // 仅 method=3
  prompt: '完整的情景描述 + 运镜 + 音效 + 4k 画质词'
}

提交体:

// method=2
await postJson('/getVideoV3_720p', {
  prompt: PROMPT, frames: 121, method: '2',
  config: { image_urls: [firstFrameUrl] },
});

// method=3 —— 必须传数组,[首帧, 尾帧]
await postJson('/getVideoV3_720p', {
  prompt: PROMPT, frames: 121, method: '3',
  config: { image_urls: [firstFrameUrl, lastFrameUrl] },
});

八、健壮性要求(缺一不可)

要求 做法
幂等 生成前、下载前都检查文件是否已存在,存在即跳过(fs.existsSync)
workId 留痕 记到日志,格式:[时间戳] 类型 \| workId: xxx \| 内容: xxx
段间隔防限流 每段之间 await sleep(15000)
并发退避 遇 50430 / Concurrent Limit:退避 10000 × (retry + 1),上限 5 次
HTML 检测 轮询返回以 <!DOCTYPE / <html 开头 → 不解析,等 30 秒重试
结果兜底 isFinish=true 但 videos 为空 → 改查 GET /parse/classes/ImagineWork/{workId}
异常隔离 单个 fetch failed 只记日志并 continue,不中断整批
超时 统一 600 秒(10 分钟);数字人放宽到 900 秒;超时保留 workId 供手工重查
本地预检 提交前校验 frames 是否 ∈ {121…241} 且 ≡1 mod 24;图片比例 ≤3

以上九条在本技能仓中全部已实现:见 lib/jimeng.mjs(submit / poll / assertValidFrames) 与 scripts/video.mjs(幂等、workId 日志、降级留痕)。


九、映射预检(生成前必做)

photo1 → 视频1(首帧), 视频1(尾帧)
photo3 → 视频2(首帧)
photo4 → 视频3(首帧)
...
  • 每张照片都有对应的视频段?
  • 视频脚本里的首帧路径都指向存在的文件?
  • method=3 的两张图都存在?
  • 映射关系与分镜文档一致?

踩坑记录:某项目 photo1(楼外场景)生成了但没有对应视频,后期才发现需要补生成。


十、成本

分辨率 单价 5 秒单镜 8 镜整片(每镜 5s)
720p ¥0.28/秒 ¥1.41(实测实扣) ≈ ¥11
1080p ¥0.63/秒 ¥3.15 ≈ ¥25
Pro ¥1.00/秒 ¥5.00 ≈ ¥40

试跑省钱:fmode-mv video --from work/storyboard.json --limit 1(1 镜,¥1.41) 零费用验证:--mode still(Ken Burns 兜底,不调 API)