mcpField
F
founder-product-video

founder-product-video

github.com/pika-labs营销与增长411.7k 次安装14 周前更新
代码仓库

关于 founder-product-video

此 Skill 根据产品 URL 和图片制作 65 秒创始人风格产品视频,涵盖品牌素材、创始人画面、字幕与渲染,并在付费生成前要求确认费用。

主要功能

  1. 01制作 65 秒创始人产品视频
  2. 02将产品图片用作视觉参考
  3. 03添加品牌片尾卡与字幕
  4. 04可选添加下三分之一字幕条
  5. 05付费生成前确认费用

适用场景

  1. 01制作创始人主导的产品介绍
  2. 02将产品截图转为视频参考
  3. 03渲染品牌营销视频素材

MCP 相关

默认使用 Pika MCP 工具进行视频生成、渲染、字幕、拼接和音乐混音;可选的下三分之一字幕条使用 MCP compose。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pika-labs/pika-plugins --skill founder-product-video

安装后在 Claude Code 中输入/founder-product-video确认已加载。

附带文件references/ops-notes.md

详细介绍

founder-product-video

根据产品 URL 和用户提供的图片,生成一段 65 秒的创始人风格产品视频:60 秒的创始人出镜视频,加上 5 秒的品牌片尾卡。用户的图片(产品照片/网站截图/应用截图)会作为视觉参考输入 SeeDance;数字产品界面/品牌字标则在生成后合成,以确保可读的 UI 是确定的,而非由模型渲染。

不使用插入镜头。不提取网站 CSS。默认通过 Pika MCP 工具完成 AI 生成、确定性渲染、字幕、拼接和音乐混音。下三分之一叠加层为可选项,默认使用 MCP compose;仅在紧急情况下才使用本地 ffmpeg 作为后备方案。

费用透明度门槛

在进行任何付费 MCP 调用前,调用一次 identity_balance({verbose: true})。告知当前余额、近期消耗速度和剩余可用时长,然后用以下确切消息询问是否继续:

预计费用:典型的四幕 Seedance 创始人视频及配套素材约需 4,000 积分(约 $40)。费用超过 $5,因此请回复 proceed 继续,或回复 cancel 停止。

在用户回复 proceed 前,不得调用任何付费 MCP 工具。如果用户回复 cancel,则停止,不生成内容。对于非交互式 --quick 或 --config 调用者,必须在配置中要求 cost_ack=proceed;如果缺少此项,则显示费用估算并停止,不得消耗积分。

[0] 信息收集 — 首先运行,在任何流水线步骤之前

如果调用时参数为空,原样打印以下菜单并停止,等待用户粘贴输入:

你想制作什么样的创始人视频? 必填:

  • 产品 URL — https://...(任何有实际主页的 URL)
  • 创始人 — 姓名 + 职务,例如 "Eli Kim, CEO"
  • 创始人照片 — 本地路径、https URL,或 generate(我会生成一张肖像)

可选(未提供时使用合理默认值):品牌套件路径 · 自定义手机截图 · 音乐 · 画面比例(16:9 / 9:16 / 1:1)· 地点图片 · 声音风格 · 产品类型

示例:/founder-product-video https://example.com --founder "Eli Kim, CEO" --photo ~/Pictures/eli.jpg

如果交互模式下参数中包含部分输入,跳过菜单,逐项询问缺少的必填字段——一次问一个,等待回答后再问下一个。不要把问题合并成一组。如果用户主动提供了某个字段(例如在触发消息中粘贴了 URL),则跳过该问题,并在最后向用户确认该值。所有必填字段都得到答复后,才能启动流水线。如果适用非交互式快速通道,则改用步骤 [0.5]。

[0.5] 非交互式快速通道

当调用者传入 --quick 或 --config <path>,或者调用者说明他们正在通过 CI、子 Agent、批处理作业或其他任何非交互式运行环境执行时,使用此路径。

本节优先于下方的交互式询问/等待说明。适用时,使用此快速通道,不要转入多轮信息收集,除非确实缺少 url 或创始人姓名/职务。

  • --config <path> 指向一个 JSON 文件,其中包含符合规范输入约定的预置值:url、brand_kit_path 或 build_brand、founder_name、founder_role、founder_photo、assets、music_url、aspect_ratio、location_image_url、voice_style、product_type 和 lower_third。
  • --quick 表示可选项使用默认值;如果省略 brand-kit,则使用 build-a-brand --quick 自动构建品牌套件;如果未提供照片,则使用 founder_photo = "generate"。
  • 对于 --quick 或 --config,在品牌套件分支、创始人照片生成提示、可选项提示、脚本选项或片尾卡/字幕默认值处,不要停下来等待确认。内联记录假设并继续。
  • 如果在参数或配置中找不到 url 或创始人姓名/职务,则只需一次性输出简洁的缺失字段列表并停止,不要启动多轮问答。 1. 产品 URL (必填) — https://...。用于 (a) 在步骤 [1] 中提炼简报,以及 (b) 为下方品牌套件分支提供素材。

2. 品牌套件 (必填) — 交互模式:询问 “你已经有品牌套件文件夹了吗?还是需要我先创建一个?”

  • 如果提供了路径 -> 使用该路径(state.brand_kit_path = <path>)。接受 brand.json,或包含 brand.md、tokens/tokens.json 和 logo 资源的已导出 build-a-brand 套件。
  • 如果回答“创建” -> 针对 URL/简报调用 build-a-brand 技能,并等待导出品牌套件。这是一个完整的品牌形象工作流,可能会暂停以供用户选择;在交互模式下显示这些提示。
  • 快速通道:如果配置提供了 brand_kit_path,则使用该路径。如果配置设置了 build_brand,或 --quick 未提供 brand-kit,则针对 URL/简报调用 build-a-brand --quick 并等待导出品牌套件;不要显示 build-a-brand 提示,也不要因品牌形象选择而暂停。无论走哪个分支,之后都要设置 state.brand_kit_path。只有在没有路径且无法创建品牌套件时,才用一份简短的缺失字段列表停止流程。

3. 创始人身份 (必填) — 交互模式:一次性询问以下三项:

  • founder_name — 例如 “Avery”
  • founder_role — 例如 “CEO, ExampleCo”
  • founder_photo — 本地路径 / https URL / 或字面字符串 generate,用于自动生成肖像。如果为 generate,提示用户提供一句氛围描述(“温暖、休闲商务着装” / “皮克斯风格的 3D 动画” / 等)——这将作为步骤 [4] 中 generate_image 的种子提示词。
  • 快速通道:使用参数/配置中的创始人信息。如果省略 founder_photo,则设置 founder_photo = "generate",并根据产品基调采用中性的创始人肖像氛围;不要另外询问照片氛围。

默认不添加下三分之一字幕条,以保持顺畅流程简洁。如果用户明确要求添加下三分之一字幕条,则记录 state.lower_third = true;在交互模式下,确认 edit_video_compose 会在渲染后添加透明叠加层。

4. 可选附加项 — 交互模式:用一条消息一次性提供以下选项;如果用户没有在同一轮回复中作答,则继续流程,不必等待。快速通道:直接使用下方默认值,不要询问。

  • 自定义图像 — 显示在创始人手机上的 assets 列表(产品照片 / 应用截图)。省略时的默认值: 如果 brand.json.screenshots 中有截图,则使用这些截图;否则在品牌套件中查找明显的截图或产品图片;否则在步骤 [2] 之前使用 capture_website(mode:"screenshot") 截取产品 URL。除非 product_type 明确为 service 且用户接受仅展示环境的视频,否则没有真实产品 UI / 产品图片时,不要继续编写脚本或使用 SeeDance。在快速通道中,如果没有提供、品牌套件中没有,也没有截取到资源,则只停止一次并显示简短的缺少资源错误,不要悄悄生成通用的对话式视频。
  • 音乐 — 本地路径 / https URL / 或 generate(器乐,约 60 秒)。默认值:通过 Kling 背景模式生成。
  • 下三分之一字幕条 — 可选。默认关闭。如果启用,则通过 MCP 渲染透明的 .mov,并使用 edit_video_compose 将其叠加到主体视频上。
  • 宽高比 — 16:9(默认)、9:16、1:1。
  • 场景地点 — 默认为 state.brand.colors.accent 中的纯色无缝背景(简洁的影棚拍摄效果,角色置于单一品牌色背景前,具体颜色取品牌的强调色)。如果用户想要办公室、户外等场景,可用路径 / URL / 文本描述覆盖。
  • 配音风格 — 提供给 SeeDance 的配音指导字符串,例如“温暖、真实的创始人气质,口语化”。默认值:根据 brief.tone 推导。
  • 产品类型 — digital | physical_apparel | physical_object | consumable | service。默认值:在步骤 [2] 中根据资源分析自动推导。 Stage 0 完成后,将所有收集到的值存入 state.inputs。如果已为本次运行创建本地工作目录,也可以将同一对象保存为 <workdir>/inputs.json;不要要求预先定义工作目录环境变量。然后从步骤 [1] 进入流水线。
[0.6] 创始人照片的头像类型探测

在进行任何付费的 generate_reference_video 调用之前,请在本地上传或规范化用户提供的网址后,对解析出的创始人照片/头像网址运行此头像类型探测。这适用于用作角色参考的任何创始人照片,无论是通过 --photo 提供还是生成的。

调用一次 analyze_media:

query: "Classify this image for paid video generation. Is it a photograph of a real human face, an AI-generated realistic portrait, a stylized / illustrated character, or a recognizable trademarked / copyrighted character such as Batman, Pikachu, or Mickey Mouse? Return strict JSON only: { \"avatar_type\": \"real_human\" | \"ai_realistic\" | \"stylized_illustrated\" | \"recognized_ip\", \"recognized_character\": string | null, \"moderation_risk\": \"low\" | \"medium\" | \"high\", \"recommendation\": \"proceed\" | \"warn\" | \"reject\" }. Use null for `recognized_character` when no specific character is recognized; never write \"none\", \"unknown\", or explanatory prose in that field."

根据结果进行分流:

  • 已识别的 IP/版权风险 -> 仅在以下情况下停止:avatar_type 为 "recognized_ip",或 recognized_character 指明了某个具体角色(例如 "Batman"),或 moderation_risk 为 "high" 且 recommendation 为 "reject"。recognized_character: null、空字符串、"none"、"unknown"、"n/a",以及低/中等 moderation_risk,单独出现时都不足以停止。请在真实人像/风格化路线之前进行此检查。即使是 chibi 版 Batman,只要 avatar_type 为 stylized/illustrated,也仍然是 Batman。
  • 真实人物/AI 生成的写实人像 -> 正常继续。
  • 风格化/插画 -> 显示警告,说明风格化头像在 Seedance 相似度和审核方面可能不太可靠;然后仅在用户提供或接受该头像时继续。
  • 商标保护/受版权保护 -> 生成前停止。显示以下消息:Your founder photo appears to be a trademarked character ([X]). Most video providers will moderate this and refuse to generate. Pass --photo <real-looking-photo-url> to override. 对于此技能,--photo <real-looking-photo-url> 是认可的具体标志;也可以提及跨技能的 --avatar <real-looking-photo-url> 表述,因为用户可能熟悉这种约定。

必需输入(规范契约)

Stage 0 之后,下游步骤会使用以下字段:

  • url — 产品网站(https://)。用于步骤 [1] 的简报。
  • brand_kit_path — 品牌工具包文件夹。必需。片尾卡和下三分之一标题在存在 brand.json 时会使用它,否则会使用 brand.md、tokens/tokens.json,以及来自 build-a-brand 导出的 Logo 资源。参见步骤 [4.5]。
  • founder_name + founder_role + founder_photo — 接收信息时必需。步骤 [4] 会在任何 SeeDance 调用之前,将 founder_photo 规范化为 founder_photo_url 和 character_url。
  • assets — 可选数组,格式为 { url, role?, caption? }。默认使用品牌工具包捕获的屏幕截图;如果品牌工具包没有屏幕截图,请在步骤 [2] 之前捕获产品网址,并将返回的 image_url 保存为真实的产品 UI 资源。role 是提示字符串,用于将资源映射到脚本节拍(hero、feature_a、cta 等)。
  • location_image_url — 可选。默认使用在 state.brand.colors.accent 中生成的纯色背景。
  • music_url — 可选。默认为 generate(在步骤 [7] 中生成 Kling 60 秒背景音乐)。
  • aspect_ratio — 默认为 16:9。
  • voice_style — 可选,默认为 brief.tone。
  • product_type — 可选,在步骤 [2] 中自动推导。

状态

工作时维护一个简单的 state 对象,并将每个 CDN URL 都保存在其中,以便恢复未完成的运行。将 task_status 值 completed 视为成功终止状态(failed 和 cancelled 为失败终止状态),然后在存在 result.structuredContent 时解包该值。最终视频保存在 Pika 的 CDN 上;除非 MCP compose 不可用且你明确触发步骤 [8b] 中的本地下三分之一标题回退方案,否则无需本地工作区。

长时间运行的 task_status 轮询

当任何长时间运行的生成或编辑调用返回 task_id(无论是否附带初始状态),包括 {task_id}、{task_id, status: "queued"},或初始状态为 queued、running 或 processing 时,立即在 state 中记录任务 ID 和开始时间。

  • 紧密循环调用 task_status({task_id}),直至任务进入终态(completed | failed | cancelled)。不要手动休眠,也不要使用 Bash 轮询;工作进程会让每次状态调用保持打开。
  • 当状态为 queued、running 或 processing 时,每 60 秒输出一行可见的进度信息:Seedance i2v queued for {N}m {S}s... still processing。轮询音乐、字幕、渲染、拼接、混音或编辑任务时,替换其中的提供方/阶段标签。
  • 状态为 completed 时,提取返回结果中的 URL,并将其保存到 state。
  • 状态为 failed 或 cancelled 时,向用户报告失败,并提供 task_id、状态和最后一条状态消息。
  • 从最初提交任务起总计 15 分钟后,如果任务仍未进入终态,则调用 task_cancel({task_id}),然后向用户报告失败。如果取消操作报告任务已进入终态,再调用一次状态查询,并报告该终态结果。
  • 原任务仍处于 queued、running 或 processing 状态时,不要重复提交请求。

流程概览

[Stage 0] intake          you (Claude): ask user for url + brand-kit (path or build) + founder (name/role/photo) + optional extras
  → [0.5] brand-kit auto-build (only if user said "build")
                          invoke `build-a-brand`; in non-interactive mode use `build-a-brand --quick`
  → [1] analyze_brief             pika MCP: product name + tagline + features + tone + CTA
  → [2] resolve product UI assets pika MCP: use supplied/brand-kit screenshots, or capture_website(product URL)
  → [2] analyze_media × N         pika MCP: understand what each real asset shows
  → [3] write script              you (Claude): 4 acts × 15s; map assets to acts
  → [4] founder/location refs     pika MCP: upload or generate founder ref; carry supplied custom location
  → [4.5] brand-kit ingestion     parse brand.json OR brand.md + tokens → state.brand; generate default brand-accent location if needed
  → [5] generate_reference_video × 4 IN PARALLEL  pika MCP: SeeDance acts, asset images as refs
  → [5.5] digital UI overlays     pika MCP: composite real product UI / wordmark onto digital reveal acts + OCR QA
  → [6] edit_concat acts          pika MCP: 60s stitched base (dialogue-only audio)
  → [7] generate_music            pika MCP: Kling 60s soft instrumental background bed
  → [8] captions / lower-third    pika MCP: add_captions for subtitles; render lower-third as transparent .mov, then overlay it with edit_video_compose when lower-third is enabled.
  → [9] render_html_animation     pika MCP: 5s end card — author inline HTML, brand-kit fonts inlined, aspect matches body, no corner clutter, CSS @keyframes (NOT GSAP)
  → [10] edit_concat + audio_mix  pika MCP: concat body + end card, then mix music over the full ~65s
  → [10.5] final duration probe   pika MCP: analyze final_url and enforce the 55s duration floor before delivery
  → [11] final_url                save the MCP returned final_url; upload only if a local fallback created the final MP4
  → [12] deliver

操作说明

让主工作流专注于步骤顺序。历史服务器验证详情见 references/ops-notes.md;这里只保留当前有效的约束:

  • 每个 SeeDance 片段使用唯一的 seed(101、202、303、404)。相同的生成参数可能会重放缓存的失败结果。
  • Kling 音乐背景生成使用 provider: "kling-audio"、mode: "text_to_audio"、background: true 和 duration_seconds: 60;MCP 工作进程会生成一个 10s 的 Kling 种子片段,并在本地延长。
  • 如果 SeeDance 拒绝真人创始人照片,应使用更强的风格化处理重新生成创始人参考图,而不是重试同一张被拒绝的参考图。
  • 对于本地品牌套件中的 Logo,只上传适合 Logo 的栅格素材(image/png、image/jpeg 或 image/webp)。不要将 SVG 发送到 upload_asset;请从 build-a-brand 选择 PNG 导出文件,或先将其栅格化。
  • 在片尾 HTML 中,CDN 托管的 Logo/照片素材使用 CSS background-image: url(...);<img crossorigin> 会被 CDN 的 CORS 阻止。
  • 字幕、下三分之一字幕合成、拼接和混音使用服务器端确定性工具。仅当 state.lower_third = true 且 edit_video_compose 不可用时,才将本地 ffmpeg 作为回退方案。
  • 将每个 15s 片段拆解为 3 个带时间码的子镜头。单镜头片段会显得呆板。
  • 每个片段都以匹配风格的地点构图开场,并在全部 4 个片段提示词中重复使用相同的 WARDROBE LOCK: 句子。

[1] 分析需求

analyze_brief(
  sources=[{ type: "url", url: <product_url> }],
  context: "Founder-style 60-second product video. Need: product name, one-line tagline, 3-5 key features, target audience, brand tone, and a call-to-action."
)

将结果保存为 brief。之后需要始终参考 brief.product_name、brief.tagline、brief.key_features、brief.tone 和 brief.call_to_action。

[2] 解析产品 UI 资产,然后分析各项资产并推导 product_type

分析资产前,先规范化 assets,确保产品展示镜头有真实的视觉参考:

  1. 优先使用调用方提供的任何 assets。
  2. 如果没有提供,则在存在 brand.json.screenshots 时读取其中的截图。
  3. 如果 brand.json 中没有截图,则在品牌素材包中查找明显的栅格截图或产品图片(screenshots/、assets/、product/,或文件名类似 hero、screen、app、dashboard、product 的图像)。
  4. 完成上述检查后,如果 assets 仍为空,则对产品 URL 调用 capture_website:
capture_website(
  url: <product_url>,
  mode: "screenshot",
  mobile: false
)
# Save result.image_url as assets[0].url with role="website_capture".

如果产品可能以移动端为主,还要再执行一次带 mobile: true 的捕获,并在有可用 URL 时保留两个 URL。继续之前,将这些内容保存为真实的产品 UI 资产。

除非调用方明确设置了 product_type: "service" 并接受仅展示环境的视频,否则在至少有一项真实产品 UI/产品图像资产之前,不得继续编写脚本、调用 generate_reference_video 或进行任何付费 SeeDance 调用。如果捕获失败或未返回 image_url,请提示:Could not capture <url>. Please provide screenshots or hosted product assets; founder-product-video will not silently ship without real product UI.

对 assets 中的每一项运行 analyze_media,提取内容、视觉风格和资产类型。在一次工具批处理中并行运行:

analyze_media(
  media: <asset.url>,
  query: 'Describe this product image briefly. Return STRICT JSON:
  {
    "content_description": "1-line summary of what is visible",
    "asset_type": "digital_screen | physical_apparel | physical_object | consumable | infographic | other",
    "key_elements": ["3-5 specific UI elements / features / objects in the image"],
    "visible_copy": "any text visible — heading, button label, tagline, t-shirt graphic text (or empty string)",
    "primary_colors": ["#hex", "#hex", "#hex"],
    "vibe": "1-line visual feeling",
    "best_for_act": "hook | problem | solution | proof"
  }
  Return ONLY the JSON.'
)

asset_type 解码器:

  • digital_screen — 应用 UI/网站截图/SaaS 控制面板/移动应用捕获
  • physical_apparel — T 恤、连帽衫、帽子等所有可穿戴物品(模特 + 服装)
  • physical_object — 小工具、配件、包装商品等所有可手持的物品
  • consumable — 食品、饮料、补充剂(可使用/食用/饮用的物品)
  • infographic — 图表、示意图、数据可视化、插图
  • other — 其他任何内容;请描述并选择最合适的类型

保存为 asset_analyses[i]。

分析完成后,构建:

usable_product_assets = asset_analyses
  .map((analysis, i) => ({
    asset_index: i,           # original assets[] index to use in script.shots[].asset_index
    asset_url: assets[i].url, # public URL passed to reference_images later
    asset_type: analysis.asset_type,
    analysis
  }))
  .filter(entry.asset_type in [
    "digital_screen",
    "physical_apparel",
    "physical_object",
    "consumable"
  ])

如果 usable_product_assets 为空,且尚未尝试通过 URL 捕获,则对产品 URL 调用 capture_website(mode:"screenshot"),将返回的 image_url 附加到 assets,对该捕获结果运行 analyze_media,将分析结果保存在对应的新索引处,然后重新构建 usable_product_assets。因此,捕获的截图必须有自己的 asset_index;不得在产品展示中复用 Logo/主视觉图/信息图的索引。

不要仅凭 Logo、主视觉图、信息图、抽象品牌素材或 other 资产自动推导 product_type = "service"。这些都不是可用于真实产品展示的视觉依据。如果捕获后 usable_product_assets 仍为空,则除非调用方明确设置了 product_type: "service" 并接受仅展示环境的视频,否则请停止。提示缺少资产的错误,不要直接套用服务展示模式。

推导 product_type

查看 usable_product_assets 中占主导地位的 asset_type:

product_type = mode(usable_product_assets[i].asset_type) → mapped to {
  digital_screen → "digital"
  physical_apparel → "physical_apparel"
  physical_object → "physical_object"
  consumable → "consumable"
}

如果用户明确传入了 product_type,则使用该值并跳过自动推导;只有在明确选择/接受时,service 才是有效值。product_type 的值决定了步骤 [3] 中选择哪些镜头,以及步骤 [5] 中创始人如何展示产品。请务必正确设置,否则视频中会出现错误的屏幕内容。

产品类型 → 展示方式(本技能中最重要的表格)

product_type(在步骤 [2] 中设置)决定要选择哪些镜头,以及如何在每个镜头中展示资产。SeeDance 提示词中的展示环节因产品而异;如果用错,T 恤品牌的创始人就会拿着手机。

对于 digital 产品,SeeDance 提示词只负责创始人、镜头移动、手机动作,以及空白/中性屏幕占位符。**不要要求 Seedance 或视频模型渲染可读的品牌字标或产品 UI 文本。**实际截图、产品 UI 和准确的品牌拼写会在步骤 [5.5] 中合成进去。

product_type展示镜头展示环节(用于 SeeDance 提示词)哪些段落需要使用资产
digitalC-phone、E-phone“创始人将手机举向镜头;手机屏幕为预留给真实 UI 叠加层的空白中性占位符;不要渲染可读的 UI 文本或品牌字标”仅镜头 C 和 E
physical_apparelG-hold、G-wear、E-detail“创始人将一件炭灰水洗图案 T 恤举向镜头;衬衫设计与 @ImageN 完全一致——准确匹配印花/图案,不要自行创作”或“创始人穿着 @ImageN 中的 T 恤——准确匹配印花”所有能看到 T 恤的镜头(C/E/F +「穿着」变体)
physical_objectC-hold、E-detail、F-twoshot“创始人将 [product name] 举向镜头;产品与 @ImageN 完全一致——匹配形状、颜色和品牌标识”展示产品的镜头
consumableC-hold、E-detail、H-using“创始人拿着/使用 [product];包装/产品与 @ImageN 完全一致”展示产品的镜头
serviceA、B、D、F(环境)无特定产品展示——聚焦创始人和环境所有镜头都不引用资产

对于实体产品,每个产品出现在画面中的镜头都应将对应资产作为参考图传入;否则 SeeDance 往往会凭空生成一个外观普通的产品。对于服饰,如果创始人穿着 T 恤,且脚本说“我们制作 T 恤”,那么即使在非展示镜头中,创始人所穿的 T 恤也需要引用某个资产。将这些段落对应的资产 URL 传入 reference_images,并使用类似“创始人穿着 @Image3 中的 T 恤——印花完全匹配”的提示词。

[3] 编写脚本 + 角色声音 + 每镜头资产 + 每句台词的节拍(由你完成——不调用模型)

三个子项都由你(Claude)通过一个内联 JSON 编写:

  1. character_voice_profile — 用 3-4 行描述角色的默认表达方式(贯穿每个段落,保持一致)
  2. 每个镜头的 asset_index + reveal_beat — 该镜头中可见的资产,以及它如何展示
  3. 每个镜头的 beats[] — 逐句编写表演指导,包含 emotion + physical,以及句子之间的静默节拍

这正是普通的 AI 对镜头讲话与真正有意图塑造的角色之间的区别。编写前请阅读以下全部四个小节([3.0] 创始人声音、[3a] 角色声音档案、[3b] 节拍、[3c] 转场、[3c.1] 表演力度、[3d] 完整 JSON)。

[3.0] 创始人声音——写推介内容,而不是功能列表

这项技能中最常见的失败情形,就是台词听起来像营销页面上的项目符号列表(“它能推理。写代码。甚至还能写邮件。无需代理。无需选择器。无需维护。接入 LangChain。LlamaIndex。MCP。GitHub 上有两万四千颗星。采用 MIT 许可。达到生产级标准。”)——文案很工整,但这不是创始人对着镜头说话的方式。实地反馈:“脚本听起来像功能列表,不像创始人会在镜头前推介自己的产品。” 真实创始人在镜头前为自己的产品做介绍时,会用:

  • 第一人称表达主人翁意识——“我开发了”“我们发布了”“我们自己也在用”“说实话,我们就是想让它无处不在”
  • 个人切身经历或起源时刻——第一幕应该提到创始人亲身经历过的挫折,而不是抽象地谈产品。“每次我尝试构建 X,都会碰到同一道坎”胜过“X 很难”。
  • 口语化的衔接词——“你看”“说实话”“问题在于”“所以”“其实”,以及表示思考的拖长音“……”。这些词写出来显得可有可无,却是自然口语的呼吸节奏。
  • 以‘赌一把’的方式介绍产品——“如果 X 能直接用起来呢?”“我们问过自己”“整个想法就是”。创始人会把产品描述成自己提出的问题的答案,而不是罗列功能。
  • 一个具体的锚点——一个具体数字、具体时间或具体场景。“去年有 2.4 万名开发者给它点了星”胜过“它很受欢迎”。“凌晨 3 点,布局崩了”胜过“爬虫不可靠”。
  • 带有邀请感的行动号召——“来试试我们”“去体验一下”“我们就是想让它无处不在”。而不是“停止爬取,开始提取。”(这是唐·德雷柏式的广告标语,不是创始人的表达。)

禁用模式(每种模式都曾被用户明确指出,切勿重复):

❌ 禁用模式示例原因
三连否定式口号“没有代理。没有选择器。无需维护。”听起来像营销口号,不像真人说话
断续罗列功能“它能推理、写代码,甚至帮你写邮件。”读起来像功能清单
把集成列表当作推介“接入 LangChain、LlamaIndex、MCP。”顺带提一次集成没问题——但绝不能把它作为三拍式开场钩子
口号式收尾“停止爬取,开始提取。”纯粹的广告文案。创始人应该以邀请收尾,而不是喊口号
把规格当作推介“采用 MIT 许可,可用于生产环境。”规格应该写在 README 里,而不是让创始人在镜头前念出来
在列表中把“只需”当填充词“只需一次 API 调用。只需任意 URL。只需结构化 JSON。”反复说“只需”听起来像刻意强调营销话术,不像自然表达

推荐模式(请改用这些):

✅ 模式示例
从个人经历切入“说实话——每次我尝试构建 X,都会遇到同样的问题……”
“如果……呢”式表达“所以我们开发了 Y。整个想法就是:如果 Z 能直接用起来呢?”
一个具体的数据点“去年我们获得了 2.4 万颗星。大家正在把我们接入各种地方。”
随口提及痛点“给它一个 URL,就能拿到干净的结构化数据。布局变了?没关系。”
以邀请收尾“如果你的 Agent 需要真正看到实时网页——来试试我们。”

结构(分为 4 幕,每幕约 30–40 个词,总计 120–160 个词,口播约 50–60 秒):

  • 第一幕:个人经历 / 痛点。 使用第一人称。提及创始人亲身经历过的具体挫折。清楚点明问题。
  • 第二幕:赌一把。“所以我们开发了 X。我们的想法是——如果 [痛点] 能直接解决呢?”用一句话说明它的实际功能(URL → 数据、提示词 → 图像等)。
  • **第三幕:证明 + 社区。**只提一个具体数字(星标数、客户数、ARR)。随口提到一次集成情况或使用场景。语气要沉稳自信,而不是炫耀。
  • 第四幕:邀请。“如果你 [读者的情况]——来试试我们。[URL]。[一句邀请的话]。”以温暖的语气收尾,而不是喊口号。

**批准脚本前的自测。**大声读出每一幕的台词。如果你作为创始人会不好意思在镜头前说出来,就重写。如果听起来像 30 秒的商业广告配音,就重写。如果某个段落连续出现两个以上由短句片段构成的句点,就重写。

[3a] 推导 character_voice_profile + wardrobe_lock

这两个独立字段都必填:

character_voice_profile(3-4 行)——描述角色如何表达一切:语速节奏、默认表情、标志性手势、手部习惯、停顿方式、何时露出笑容。参考 brief.tone、角色参考图(character_image_url 或你生成的创始人参考图)以及 product_type。这是演员的“情境”——不是他们说什么,而是他们是什么样的人。它贯穿全部 4 幕,让一致性显得刻意而非偶然。

wardrobe_lock(1 句话)——描述角色在每一幕中的穿着。SeeDance 每次生成 15 秒视频时都会重新读取 @Image1,因此可能会为不同幕解读出不同服装。为保持服装一致,wardrobe_lock 这句话会原样重复出现在每一幕的提示词中。仔细查看参考照片中创始人的穿着,并明确描述。例如:“在全部 4 幕中都穿着同一件炭灰色连帽衫,里面搭配深色乐队 T 恤,并戴着黑框眼镜”。如果没有明确的服装锁定,即使第一幕与 @Image1 相符,后续幕也可能凭空换上不同服装。

语气模板起始项(编排器根据语气简报选择或自定义):

brief.tone默认节奏表情手部动作停顿
casual对话般自然,像是在咖啡馆向朋友解释默认带着一丝坏笑,揭晓重点时会挑眉强调重要观点时摊开手掌,思考时手托下巴以持续的眼神交流代替填补沉默
playful轻快、短促,富于表现力眼神中透着顽皮,常挑眉,讲完妙语后隔一拍才露出笑容肩膀轻轻弹动,数数时动作活泼短暂停顿,伴以会意的眼神
professional节奏适中,表达审慎温和而直接的眼神交流,笑容克制手势有意为之,而非一直动作;偶尔单手掌心向上从容地沉默,不刻意填补空白
technical分析式表达,节奏稍慢默认神情专注分析,思考时目光游移,讲到重点时再看向对方思考时手托下巴,指向想象中的示意图思考式停顿,目光移向左上方
disruptive / edgy节奏短促,句子简短,中间突然停顿默认神情冷面,偶尔露出顽皮笑容,随后又消失身体保持静止,由面部表情来表现突然停顿,头部微微倾斜

示例——开发者工具创始人(轻松语气,3D Pixar 风格的 20 岁女性):

“自信而随和,就像在咖啡馆向朋友介绍产品。默认带着一丝坏笑。揭晓关键内容时会挑眉。思考时手托下巴,在强调‘认识 A P I’时摊开手掌。停顿时保持眼神交流,而不是填补沉默。讲完妙语后面无表情地收尾,让一丝微笑隔一拍才浮现。”

示例——街头服饰创始人(活泼/不羁语气):

“犀利而冷幽默。说话很快,句子简短,时常突然停顿。默认微微坏笑,单边挑眉。提到痛点(‘无聊’、‘千篇一律’)时会翻白眼。讲完妙语后会露出顽皮的笑容,但马上收起。双手大多保持静止——由面部表情来表现。”

[3b] 逐行 beats[]——逐句指导,而非逐幕指导

每个镜头的对白都会拆分成 beats。每个 beat 都是一句简短的话(或刻意安排的沉默),并附有各自的 emotion + physical 指导。beat 之间的沉默也是表演的一部分——用持续的目光、细微表情和手势转换来填充。

带有 text: "(beat)" 的 beat 表示静默(没有口语文本)——它只描述句子之间自然停顿时画面中发生的事。在需要留出片刻停顿来强调重点的对白 beat 之间使用它们。

在步骤 [5] 中构建 SeeDance 提示词时,beats 会成为逐镜头的表演指导(去掉 (beat) 标记后的对白文本会成为 <<<voice_1>>> 载荷)。

[3c] transition_from_prev — 编排同一片段中镜头之间的连续运镜

SeeDance 的根本限制:每次 15s SeeDance 生成只会渲染一个虚拟环境和一台虚拟摄像机。当多镜头提示词写明“镜头 C,然后镜头 A”,却没有指定两者之间的连续运镜时,SeeDance 默认会对同一机位进行重新取景(缩放或裁剪)。结果看起来像跳切式变焦,而不是真正的切镜——背景相同,角色大小却不同。

解决方法:一幕中除第一个镜头外,每个镜头都必须声明一个 transition_from_prev 字段,用一句话描述将画面从上一个镜头的构图带到当前构图的连续运镜。这样 SeeDance 就必须渲染出真实的空间移动,让片段中角色身后的房间不同区域依次显现。

模式:说明摄像机的起始位置,说明结束位置,再说明连接两者的运镜方式。有效的移动动词包括:推轨、拉远、推进、环绕、弧线移动、滑动、升降、上摇、下摇、向左/右漂移。

示例:

transition_from_prev效果
"摄像机向后拉并向左弧线移动,露出她身后的砖墙和站立式办公桌"真实的空间变化——背景中显现了不同区域
"越过手机屏幕,推进到她脸部的近景——房间在她身后虚化"使用焦点转换和推轨的连续运镜
"摄像机保持距离,以稳定速度顺时针绕着她滑动,带出另一侧的新背景,其中有白板和绿植"环绕运镜展现新的背景
"从她拿着手机的手部镜头拉远至中景,然后向右漂移,移向窗边的光线"分两步完成的连续运镜
❌ "切到中景" / ❌ "现在我们看到她的中景"这些描述的不是运镜——SeeDance 会退回到同一机位重新取景

一幕中的第一个镜头不需要 transition_from_prev——它负责确立构图。该幕中后续的每个镜头都需要填写。

**明确提示时,SeeDance 可以在单个 15s 片段中进行硬切。**在带时间码的子镜头之间写入 Hard cut:(而不是 Transition:),表示构图有明显变化——SeeDance 会遵循指示,渲染真实切镜,而非重新取景。只有当你希望摄像机在不同构图之间平滑移动时,才使用 Transition:。模式:硬切呈现真实剪辑作品的感觉(构图不同、机位角度不同、表演状态不同);转场则像一段连续移动的长镜头。

[3c.1] 表演活力底线——每个节拍都需要明确的身体动作

常见的失败模式:节拍只写面部细微表情(“轻轻点头”“挑眉”“目光停留在镜头上”)。SeeDance 会把画面渲染成几乎静止的创始人——眼睛几乎不动,也没有存在感。结果看起来“呆板、僵住、毫无热情”。

规则:每个节拍的 physical 字段至少需要包含以下一项:

  • 手部或手臂动作(摊开手掌、用手指数数、不以为然地甩手、指向自己/镜头、手放胸前、大幅挥臂、手抵太阳穴思考)
  • 躯干变化(身体前倾、后仰、稍微转身、移动肩膀)
  • 幅度大于细微抽动的头部动作(左右转头再转回、倾斜 8° 以上、缓慢摇头、随节奏点头)
  • 配合眉毛动作的定向眼神变化(例如先向下看,再迅速抬眼看向镜头)

只有以下情况可以仅描写面部动作:

  • 口头句子之间无声的 (beat) 标记(这些本来就应该保持静止——凝视停留正是重点)
  • 一幕结尾的收束节拍,且此时摄像机已经在移动(由摄像机来完成动作)

编写 SeeDance 提示词时,确保汇总后的“Acting beats”部分包含足够丰富的身体动作——如果逐项检查时发现连续五个节拍都只写了“轻轻点头”或“微微一笑”,没有其他动作,那么创始人看起来就会很僵硬。请改写并加入幅度更大的动作。

[3d] 脚本 JSON
{
  "product_type": "<from step [2]>",
  "character_voice_profile": "Casual confidence, like explaining to a friend at coffee. Slight smirk default. Eyebrow flicks on key reveals. Hand goes to chin when thinking, opens out flat on big claims. Pauses with held eye contact rather than filling silence. Lands punchlines deadpan, lets a small smile arrive a beat after.",
  "segments": [
    {
      "act": 1,
      "shots": [
        {
          "type": "A",
          "asset_index": null,
          "beats": [
            { "text": "Assistants are brilliant.", "emotion": "declarative respect — say it like she means it", "physical": "soft direct eye contact, slight nod" },
            { "text": "(beat)", "physical": "subtle smirk arrives, eyes hold camera" },
            { "text": "But it's also kind of...", "emotion": "playful pivot, ellipsis hangs", "physical": "slight head tilt right, eyes drift up briefly on the ellipsis" },
            { "text": "shapeless.", "emotion": "deadpan landing", "physical": "eyes return to camera, single dismissive shrug" }
          ]
        },
        {
          "type": "B",
          "asset_index": null,
          "transition_from_prev": "Camera pushes in slowly from the medium framing into a tighter close-up, drifting slightly off-axis to her right so a different slice of the brick wall and window light is visible behind her",
          "beats": [
            { "text": "No face. No voice. No personality of its own.", "emotion": "staccato dismissal", "physical": "small head shake on each, eyebrow flick on 'personality'" },
            { "text": "(beat)", "physical": "held look, eyes lock camera, soft smile starts to arrive" },
            { "text": "Just an empty assistant waiting for orders.", "emotion": "flat, slightly resigned deadpan", "physical": "neutral face" },
            { "text": "(beat)", "physical": "soft confident smile arrives, lean forward begins" },
            { "text": "That's about to change.", "emotion": "grounded conviction, the turn", "physical": "lock eyes, single confident nod on 'change'" }
          ]
        }
      ]
    },
    {
      "act": 2,
      "shots": [
        {
          "type": "C",
          "asset_index": 0,
          "reveal_beat": "The character holds her phone up toward camera at chest height, screen facing the viewer. The screen is a clean blank neutral placeholder reserved for the real product UI overlay in step [5.5]; do not render readable UI text, brand wordmark, or fake app chrome.",
          "beats": [
            { "text": "Meet the A P I.", "emotion": "introduction with quiet pride", "physical": "phone lifts to camera, eyes flick from screen to lens" },
            { "text": "One workflow that gives your product a face, a voice, and a story.", "emotion": "warm steady build", "physical": "free hand counts the three on fingers — face, voice, story" }
          ]
        },
        {
          "type": "A",
          "asset_index": null,
          "transition_from_prev": "Camera pulls back from the phone and arcs slightly left, the phone lowers out of frame as we end on a medium shot of the character with the desk and whiteboard now visible behind her",
          "beats": [
            { "text": "And the ability to make videos, images, audio.", "emotion": "expanding the promise", "physical": "open-palm gesture sweeps wider on each item" },
            { "text": "Right inside the chat.", "emotion": "the grounding kicker", "physical": "hand lands flat, eyebrows up, slight smile arrives" }
          ]
        }
      ]
    },
    {
      "act": 3,
      "shots": [
        {
          "type": "D",
          "asset_index": null,
          "beats": [
            { "text": "Setup takes thirty seconds.", "emotion": "matter-of-fact reassurance", "physical": "walks past a desk, glances at a laptop briefly" },
            { "text": "Open the dashboard, paste the URL, sign in.", "emotion": "quick rhythmic checklist", "physical": "counts three on fingers as she walks" }
          ]
        },
        {
          "type": "E",
          "asset_index": 1,
          "reveal_beat": "Close-up of hands holding phone. The screen is a clean blank neutral placeholder reserved for the real product UI overlay in step [5.5]; do not render readable UI text, brand wordmark, or fake app chrome.",
          "transition_from_prev": "Camera dollies in fast past her shoulder to land on a tight close-up of her hands and the phone, the loft background drops fully out of focus",
          "beats": [
            { "text": "Your app becomes a guide.", "emotion": "the soft surprise reveal", "physical": "small smile at the phone, then up to camera, eyes warm" }
          ]
        },
        {
          "type": "A",
          "asset_index": null,
          "transition_from_prev": "Camera pulls back and tilts up from the phone to find her face in a medium shot, the brick wall and afternoon light now visible behind her on a different side of the loft than Shot D",
          "beats": [
            { "text": "Or whoever you build.", "emotion": "casual aside", "physical": "small shrug, slight smirk" },
            { "text": "(beat)", "physical": "held look, smirk fades into warm sincerity" },
            { "text": "Now talk to her like a person.", "emotion": "the real point — quiet conviction", "physical": "single nod on 'person', eyes hold" }
          ]
        }
      ]
    },
    {
      "act": 4,
      "shots": [
        {
          "type": "F",
          "asset_index": null,
          "beats": [
            { "text": "Skills bundled in.", "emotion": "casual confidence, intro to a list", "physical": "slight tilt of the chin, knowing look" },
            { "text": "Podcasts. Explainer videos. U G C ads.", "emotion": "rhythmic three-beat list", "physical": "small nod on each, eyebrow flick on 'U G C'" },
            { "text": "All from chat.", "emotion": "the grounding tag", "physical": "open-palm gesture lands flat, slight smile arrives" }
          ]
        },
        {
          "type": "B",
          "asset_index": null,
          "transition_from_prev": "Camera pushes in slowly from the wider brand-context framing into an intimate medium close-up; the environment recedes into soft bokeh, the character fills more of the frame",
          "beats": [
            { "text": "So stop wrestling with generic A I.", "emotion": "direct address, low-key challenge", "physical": "raised eyebrow, slight head tilt" },
            { "text": "(beat)", "physical": "held look, smirk grows" },
            { "text": "Give it a real presence.", "emotion": "the brand line, said with certainty", "physical": "lean slightly into camera, lock eyes" },
            { "text": "Start at example dot com slash demo.", "emotion": "warm CTA, the invitation", "physical": "soft confident smile, single closing nod on 'demo'" }
          ]
        }
      ]
    }
  ]
}

每个镜头的素材分配规则:

  1. 对于数字产品:只有镜头 C 和 E 会分配 asset_index(展示手机的时刻)。这些是供步骤 [5.5] 使用的叠加指针,不会纳入 Seedance 参考图像数组。其他镜头会展示创始人,不使用特定的 UI 参考。
  2. 对于实体产品:只要产品出现在画面中,该镜头就会分配 asset_index。素材是该产品外观的事实依据。不同段落可以在多个镜头中重复使用同一素材,也可以在每个镜头中展示不同素材来演示产品的多样性。
  3. 对于服务类产品:任何位置都不分配 asset_index,脚本依靠对话和环境呈现。

每个非空的 asset_index 都必须来自 usable_product_assets[*].asset_index。切勿将仅含 Logo、仅含主视觉、信息图、抽象品牌或 other 素材的索引分配给产品展示镜头。在对话中提及产品细节时,优先使用 usable_product_assets[*].analysis.key_elements 和 usable_product_assets[*].analysis.visible_copy,让口头介绍与屏幕上展示的真实产品素材相符。

每个段落的参考图像数组 = 该段落所有镜头中符合 Seedance 要求的素材 URL 的并集。数字产品的 digital_screen 素材不符合 Seedance 要求;它们仅作为步骤 [5.5] 的叠加素材。在 SeeDance 提示词中,根据素材在数组中的位置引用非数字素材,例如 @Image3、@Image4(位置从 3 开始,位置 1 和 2 始终分别是角色和场景参考图)。编排器会在步骤 [5] 构建提示词时计算此映射。

对话规则——4 个段落的对话总时长必须控制在 55–60 秒(约 150 wpm = 总计约 150 个词,每段约 37 个词)。简短有力,便于口语表达。避免使用破折号(创始人不会这样说话)。使用自然的缩略形式。提及用户产品的实际功能(取自 usable_product_assets[*].analysis.key_elements 和 usable_product_assets[*].analysis.visible_copy),不要编造功能。

TTS 发音改写

SeeDance 的原生口型同步 TTS 会照字面读出 <<<voice_1>>> 中的文本——它无法理解「Ari」是一个名字、「Vercel」的发音是「ver-SELL」、「UGC」是一个需要逐字母读出的缩写,或「example.com」是一个 URL。请按你希望的发音改写对话文本,然后提交。应用以下替换:

模式错误(照字面读)正确(针对 TTS 改写)
以 -i 结尾的名字"Ari" → "ah-REE""Airy"(或 "Tess" / "Mae" / "Sam"——按读音拼写)
拼写不常见的名字"Aoife" → 发音混乱"Eefa"(按读音拼写)
来自 state.brand.name 或 brief.product_name 的非语音拼写产品名 / 品牌名"Vercel" → "Verkon";"Linear" → "Lineer"创建仅用于 TTS 的语音拼写别名,例如 "ver-SELL",并在对话 / <<<voice_1>>> 中提到品牌时使用该别名。
需要逐字母读出的缩写"UGC" → "uhg" / "ugg";"MCP" → "mehp" / 不发音"U G C" / "M C P"(字母之间用单个空格隔开)
读作单词的缩写"NASA" → "nasa" ✅(已经正确);"IKEA" → "ikea" ✅保持不变
域名中的点"example.com" → "examplecom""example dot com"
URL 中的斜线 / 路径"example.com/API" → "examplecom-api""example dot com slash A P I"
符号"$50" → 不发音;"@user" → "at user" 或不发音"fifty bucks" / "at-sign user"
格式不常见的数字"2026" → 含义模糊年份用 "twenty twenty-six";整千数用 "two thousand"

不确定品牌如何读出缩写(NASA 还是 N.A.S.A.)或不常见的产品名时,请查看品牌官网 / 视频。对于不明确的缩写,默认逐字母读出;对于非语音拼写的名称,使用简单的语音拼写别名。对于包含品牌名的域名,组合使用两种改写:在 <<<voice_1>>> 负载中,Vercel.com 应改为 ver-SELL dot com。

示例——原始脚本与适用于 TTS 的改写:

Original:  "UGC ads. All from chat. Launch the API. Start at example.com/API."
TTS-safe:  "U G C ads. All from chat. Launch the A P I. Start at example dot com slash A P I."

Original:  "Your app becomes Ari."
TTS-safe:  "Your app becomes Airy."

Original:  "Vercel ships at vercel.com."
TTS-safe:  "ver-SELL ships at ver-SELL dot com."

仅在对话文本中保留这些改写——脚本 JSON 的 dialogue 字段会原样传入 SeeDance 提示词,再传入每个 <<<voice_1>>> 块。视觉界面保留规范的原始拼写:state.brand.name、brief.product_name、产品 UI 叠加层、文字标志、片尾卡片文本、URL、文件名和 QA 预期均不得改动。切勿将确定性的视觉文本替换为语音拼写别名。

镜头类型参考

每种镜头会根据 product_type 提供不同变体。选择匹配的变体。

⚠️ 避免使用 SeeDance 会按字面理解的电影行业镜头术语。 SeeDance 会将命名的镜头类型视为字面指令,包括术语所暗示的主体。具体来说:

  • ❌ “双人镜头” → 会在画面中添加第二个人(该术语在电影中指“包含两个主体的镜头”,但 SeeDance 只会理解成“两个”+“人”)。
  • ❌ “三人镜头”——同样会踩坑。
  • ❌ “过肩镜头” / “OTS” → 会在前景添加一个虚幻的肩膀/后脑勺,让角色与之互动。随后角色会朝着那个虚幻的人表演,而不是朝向镜头。
  • ❌ “主镜头”——可能会被误解为“主人/他们的老板”。
  • ✅ “中景”、“特写”、“远景”是安全的;这些词在日常用法中很常见。

每种情况下的解决方法都是用白话描述镜头看到了什么,而不是使用会暗示额外主体的电影术语。示例:

  • “过肩揭示镜头” → “角色将手机举到胸前,朝向镜头,屏幕面向观众”
  • “双人镜头” → “广角取景,让角色与[产品/Logo/环境]一同入镜”
  • “主观视角” → “从角色视线高度拍摄的低机位镜头”
镜头所有变体摄像机
A中景,腰部以上,角色居中。(画面中没有产品,或者如果是 physical_apparel:角色穿着品牌的其中一件衬衫——将素材作为参考传入,并添加 reveal_beat。)缓慢、轻微地向前推轨
B中近景,胸部以上,营造亲密感。(没有产品,或者如果是 physical_apparel:衬衫从领口处可见,并将素材作为参考。)轻柔的手持呼吸感运动
C手机/产品展示——正对镜头。 digital → 角色将手机举到胸前,朝向镜头,屏幕面向观众,屏幕上使用空白中性占位画面,以便在步骤 [5.5] 中叠加真实 UI。(不要使用“过肩镜头”——该术语会触发虚幻人物。)physical_apparel → 角色将 T 恤举到镜头前,印花面向观众,并与 @ImageN 匹配。physical_object → 角色将产品举到镜头前。consumable → 角色将包装举到镜头前。缓慢推近手持物品
D远景+环境,全身入镜,置身于开阔空间。(没有特定的产品展示时刻。)缓慢跟拍,呈现视差纵深
E特写展示。 digital → 特写拍摄双手拿着手机,屏幕上使用空白中性占位画面,以便在步骤 [5.5] 中叠加真实 UI。physical_apparel → 特写拍摄双手拿着衬衫布料,清晰展示设计。physical_object → 特写拍摄手中的产品,展示细节。consumable → 特写拍摄使用/食用/饮用产品。轻微拉焦,缓慢上摇
F品牌情境镜头。 采用更宽的取景,让角色与产品/环境情境一同入镜。digital → 角色置身于具有品牌风格的环境中,画面中没有可读的产品 UI 或文字商标。physical_apparel → 角色穿着品牌 T 恤,印花在画面中部清晰可见。physical_object → 角色与放在桌上/架子上的产品一同入镜。缓慢向后拉,轻柔地拉远

[4] 创始人 + 自定义地点参考图

在调用 SeeDance 前准备好 character_url:

  • 如果 founder_photo 是 HTTPS URL,则设置 founder_photo_url = character_url = founder_photo。
  • 如果 founder_photo 是本地路径,则使用 upload_asset 上传,然后设置 founder_photo_url = character_url = public_url。
  • 如果 founder_photo 是 generate,则调用 generate_image 并使用返回的 URL:
generate_image(
  prompt: "<founder vibe>. Professional founder portrait, clean studio lighting, sharp focus on face, confident expression, suitable as character reference for video generation.",
  aspect_ratio: "3:4",
  resolution: "2K"
)

仅当用户提供了自定义地点时才处理地点:

  • 如果 location_image_url 是 HTTPS URL,则设置 location_url = location_image_url。
  • 如果它是本地路径,则使用 upload_asset 上传,并设置 location_url = public_url。
  • 如果它是文本描述,则使用 generate_image 生成自定义地点参考图。
  • 如果未提供自定义地点,则此处不做任何处理。[4.5] 会在 state.brand 存在后生成默认品牌强调背景。

将生成的 URL 保存到 state 中。如果 SeeDance 之后因内容政策拒绝创始人参考图,请参阅“已知基础设施问题”——使用更强的风格化效果重新生成。

[4.5] 品牌套件导入(始终执行 — Stage 0 保证提供 brand_kit_path)

Stage 0 要求提供 brand_kit_path——由用户提供,或先通过 build-a-brand 构建。解析一次,并在片尾卡和下三分之一字幕中重复使用。如果交互模式下缺少文件夹,请先让用户提供或重新构建品牌套件,再继续。在非交互式快速通道中,先尝试 build-a-brand --quick 分支;如果无法生成套件,则仅停止一次,并列出一份精简的缺失字段清单。

如果存在 brand.json,则优先使用。否则,从 build-a-brand 导出内容中提取:

  • brand.md 中的名称、标语、品牌语调、字体名称和 Logo 描述。
  • tokens/tokens.json 中的颜色和字体令牌。
  • logo/ 资产中的字标、符号/图标和组合标识。

提取到 state.brand 中:

state.brand 字段来源备注
namebrand.json.name 或 brand.md 快速参考品牌显示名称
wordmark_pathlogo.wordmark.path 或 logo/wordmark/*.{png,jpg,jpeg,webp} 中最佳的栅格图像使用 upload_asset 上传本地栅格资产,将 public_url 保存为 state.brand.wordmark_url;不要上传 SVG
icon_urllogo.icon_mark.path 或 logo/symbol/*.{png,jpg,jpeg,webp} 中最佳的栅格图像使用 upload_asset 上传本地栅格资产,将 public_url 保存为 state.brand.icon_url;不要上传 SVG
colors.primary调色板角色 ink_primary、surface_dark 或 tokens.color.text文本和边框颜色
colors.surface调色板角色 surface_page_bg、surface_white 或 tokens.color.background页面/背景颜色
colors.accent调色板中的 CTA/品牌主色,或 tokens.color.primary片尾卡 CTA 胶囊背景 + 下三分之一字幕强调色
colors.highlight调色板或令牌中的次要浅色/高亮色下三分之一字幕边框/高亮色
fonts.display_family字体排版显示令牌或 brand.md如果有则按原样使用;否则回退到 Space Grotesk
fonts.text_family字体排版正文/文本令牌或 brand.md回退到系统无衬线字体
fonts.mono_family如果存在,则使用字体排版等宽令牌回退到 Space Mono

品牌套件资产为本地文件时,必须执行上传步骤。 如果没有公开的字标/图标 URL,render_html_animation 渲染的 HTML 就无法访问这些资产。仅使用栅格 Logo 文件,通过 MCP upload_asset 流程上传,并将返回的 public_url 值保存到 state.brand。upload_asset 不接受 image/svg+xml;如果最佳 Logo 是 SVG,请选择品牌套件中配套的 PNG 导出文件,或将 SVG 内联到 HTML <svg> 块中,通过 html_to_png 将其栅格化为 PNG,并使用返回的 PNG public_url。

品牌强调色背景的默认位置 — 如果 Step [4] 未设置 location_url,则使用 html_to_png 和 state.brand.colors.accent 渲染纯色 PNG。匹配所请求的视频宽高比,避免后续裁切参考图:

aspect_ratio背景尺寸
16:91920×1080
9:161080×1920
1:11080×1080

将返回的 file_url 保存为 location_url。这会营造简洁的影棚拍摄质感——角色置于品牌专属强调色的平整无缝墙面前,没有家具或背景细节。与 AI 生成的办公室布景相比,这种方式更可靠,且能稳定渲染 SeeDance。

html_to_png(
  html: "<body style='margin:0;background:{accent}'></body>",
  format: "png",
  mode: "sync",
  raster_options: { viewport_px: { width: W, height: H }, device_scale: 1 }
)
# Save result.file_url as location_url

[5] 并行生成 4 个 SeeDance 镜头

关键:[5] 步骤需要使用 generate_reference_video(多参考图)。此技能提示词模板中的 @Image1 / @Image2 / @Image3 标记只有通过 generate_reference_video 才会解析。如果误调用 generate_video(单图 i2v),@ImageN 标记会被静默忽略,Seedance 只会根据提示词文本自行臆造 UI,通常还会拼错产品名称。在启动任何付费视频生成前,请停止并修正工具调用。

对于 product_type: "digital",此步骤现在用于生成风格和手势,而不是最终的可读 UI 步骤。不要要求 Seedance 拼写产品名称、渲染可读的品牌字标或复现产品屏幕文案。手机展示画面必须使用空白的中性屏幕占位内容,因为真实产品 UI 会在 [5.5] 步骤中合成。不要在 reference_images 中传入 digital_screen 素材;任何 digital_screen 素材索引都仅是 [5.5] 步骤的叠加指针,即使混合或明确的非数字运行中也包含实体素材。

对于每个镜头组,收集该镜头组所有镜头中 asset_index 值的并集,以构建 reference_images 数组:

act_asset_indices = unique(shot.asset_index for shot in act.shots if shot.asset_index !== null)
act_asset_entries = usable_product_assets.filter(entry.asset_index in act_asset_indices)
if act_asset_entries.length !== act_asset_indices.length: stop; a shot references an unusable/missing asset_index
seedance_asset_entries = act_asset_entries.filter(entry => entry.asset_type !== "digital_screen")
act_asset_urls    = [entry.asset_url for entry in seedance_asset_entries]
reference_images  = [character_url, location_url, ...act_asset_urls]

素材条目在 reference_images 中的位置决定其 @ImageN 标记(位置 1、2 分别对应角色和场景;可用的产品素材从位置 3 开始)。编写提示词时,将每个非数字镜头的 asset_index 映射到对应的 seedance_asset_entries 位置。对于任何 digital_screen 素材,不要在 Seedance 提示词中引用 @ImageN 标记;请使用空白手机屏幕占位内容,并让 [5.5] 步骤使用原始的 act_asset_entries 条目。

提示词模板

通过 @Image1 引用角色,不要在描述性提示词中描述角色。 如果提示词同时写着“年轻的创意街头服饰品牌创始人”,而 @Image1 是角色参考图,这两种描述可能会互相冲突——SeeDance 可能会试图同时满足两者,从而凭空生成第二个人物。地点和 @Image2 也适用相同规则。让参考图承载视觉身份。

每个 act 的提示词从上到下分为三个层次:

  1. 角色 + 地点身份(开头一行始终相同)。
  2. 角色声音——act 提示词逐字重复 script.character_voice_profile。这能让演员的个性贯穿每个镜头。
  3. 每个镜头的区块——每个镜头先写构图(如果已定义,则写 reveal_beat),接着列出根据镜头的 beats[] 构建的逐句“表演节拍”,然后在 <<<voice_1>>> 中放入对白。

⚠️ 开场句、WARDROBE LOCK:、Background context:、<<<voice_1>>>、Transition: / Hard cut:,以及结尾句 Native lip-synced dialogue audio, no music overlay. 都是不可或缺的——底部的 ## Load-bearing phrases 中记录了每一项及其可避免的具体问题。改写其中任何一项都会悄然破坏整个方案(背景变成字面场景、歌词被唱出来、跳跃式缩放、服装变化等)。这些内容必须原样保留;衔接性的文字可自行撰写。

模板:

The character (matching @Image1) in a setting whose visual style, palette, lighting and materials match @Image2.

CHARACTER VOICE: {script.character_voice_profile}
WARDROBE LOCK (verbatim across all 4 acts): {script.wardrobe_lock}

Shot {first}: {if shot.reveal_beat exists: shot.reveal_beat ELSE: composition + camera from Shot table}. Background context: {distinct physical position in the space — which wall / window / feature is behind the character}.
Acting beats:
  • "{beat[0].text}" — {beat[0].emotion}; {beat[0].physical}.
  • (silence) — {silence beat physical}.
  • "{beat[N].text}" — {beat[N].emotion}; {beat[N].physical}.
<<<voice_1>>>{joined beat texts excluding (beat) markers, with periods and commas as written}<<<voice_1>>>

[If 2+ shots in this act:] Transition: {shot[1].transition_from_prev}.
Shot {second}: {composition or reveal_beat}. Background context: {a DIFFERENT physical position from Shot {first} — different wall / different angle / different background feature}.
Acting beats: ...
<<<voice_1>>>...<<<voice_1>>>

[If 3 shots:] Transition: {shot[2].transition_from_prev}.
Shot {third}: ... Background context: {a THIRD distinct physical position — must be visually different from Shots {first} and {second}}.

Native lip-synced dialogue audio, no music overlay.

模板说明:

  • 开头写 "The character (matching @Image1) in a setting whose visual style ... match @Image2"——绝不要写 "inside the location matching @Image2"。如果写了 "inside the location",SeeDance 会将 @Image2 中的背景照搬出来——参见 Known infra quirks。
  • 不要在文字中描述角色——SeeDance 会从 @Image1 读取视觉身份。例外情况:通过 WARDROBE LOCK 行明确锁定服装(例如 "wearing the same charcoal hoodie over a dark band tee throughout")。仅凭 @Image1 无法锁定不同 15 秒生成片段之间的服装。
  • 不要添加与参考图相矛盾的美学形容词。如果 @Image1 是 3D 皮克斯风格的角色,就不要在提示词中任何位置添加 "photorealistic"。
  • CHARACTER VOICE + WARDROBE LOCK 这两行在每个提示词中仅出现一次,放在镜头之前。 它们能为 SeeDance 设定演员的整体风格和服装连贯性。
  • 每个镜头区块都包含一行 Background context:,用于描述空间中一个不同的具体位置——与此 act 中其他镜头所在的位置不同,最好也与其他 act 不同。这样可以促使 SeeDance 呈现丰富的场景变化,同时保持由 @Image2 锚定的品牌美学。
  • (beat) 标记必须放在 <<<voice_1>>> 内容之外。 它们只是表演指示——对白文本中句子之间的自然停顿就是它们发生的位置。
  • act 中除第一个镜头外,每个镜头都要添加一行 Transition: …,内容根据 shot.transition_from_prev 构建。该行描述不同取景之间的镜头移动,促使 SeeDance 呈现真实的空间移动(角色身后的房间不同区域),而不是缺乏动机、看起来像跳跃式缩放的重新取景。
示例——physical_apparel,Act 2(包含声音 + 节拍)

Act 2 包含镜头 [C, A]。镜头 C 的 asset_index: 0,并且有一个关于搜索历史 T 恤的 reveal_beat。镜头 A 没有 asset_index。资源 0 = @Image3。角色声音档案是步骤 [3a] 中的街头服饰品牌创始人示例。

The character (matching @Image1) in a setting whose visual style, palette, lighting and materials match @Image2.

CHARACTER VOICE: Sharp dry wit. Talks fast in clipped sentences with sudden pauses. Default slight smirk with one raised eyebrow. Eye-rolls on the pain points. Mischievous grin breaks through on punchlines but disappears immediately. Hands stay mostly still — the FACE does the work.
WARDROBE LOCK: wearing the same charcoal-washed brand graphic tee under an unbuttoned indigo-denim chore jacket throughout all 4 acts.

Shot C: The character lifts a charcoal-washed graphic tee toward camera, holding it flat at chest height. The shirt design exactly matches @Image3 — 'I SAW YOUR SEARCH HISTORY' with shocked cat illustration in bold white type. Match the print exactly, do not invent. Camera: slow lateral arc pan around toward eyeline. Background context: standing near the apparel rack against the brick wall on the right side of the loft, soft midday window light from camera-left.
Acting beats:
  • "You know that thing you almost typed?" — knowing low-key accusation; raised eyebrow on 'almost typed', slight head tilt.
  • "That weird search?" — held look, eyebrow stays up, hint of smirk arrives.
  • (silence) — beat lands, smirk grows, eyes flick to lens.
  • "Your cat saw it." — mischievous deadpan; lifts shirt slightly higher, single confident nod.
<<<voice_1>>>You know that thing you almost typed? That weird search? Your cat saw it.<<<voice_1>>>

Transition: Camera pulls back from the held shirt and arcs slightly left, the shirt lowers out of frame as we end on a medium shot with the apparel rack and brick wall now visible behind her.
Shot A: Medium shot, waist up, the character centered, looking at camera. Camera: slow subtle push-in dolly.
Acting beats:
  • "We turned it into a t-shirt." — matter-of-fact reveal; eyebrows up, slight smile arrives.
  • " — graphic tees with attitude." — the brand-line punctuation; smirk lands on 'attitude', eyes hold.
<<<voice_1>>>We turned it into a t-shirt — graphic tees with attitude.<<<voice_1>>>

Native lip-synced dialogue audio, no music overlay.
跨镜头保持实体产品一致

对于 physical_apparel,如果角色在多个 act 中都穿着品牌产品(例如,没有特定产品展示但角色仍穿着品牌 T 恤的 act),请挑选一件主打 T 恤素材,并将其也传给这些 act,同时在提示词中写上类似 "the character is wearing the t-shirt from @Image3 — print matches exactly" 的内容。否则 SeeDance 会自行生成一件看起来很普通的 T 恤,无法实现素材覆盖目标。

并行生成全部 4 幕——每幕 3 个子镜头

在一次工具批次中并行生成全部 4 幕。每幕提示词都应包含 3 个带时间码的子镜头;无论提示词多详细,单镜头 15 秒片段都会渲染成静止画面,创始人的动作看起来像被冻结了一样。如果生成结果看起来“非常静止,没有肢体语言,镜头运用乏味”,解决方法是在提示词中将每一幕拆分为 3 个带时间码的子镜头。

默认拆分方式:每幕 3 个子镜头,根据对白密度分配时长(例如 (0-4s)、(4-9s)、(9-15s))。

每个子镜头都需要:

  1. 不同的镜头构图——相邻的两个子镜头不能使用相同的景别。混合使用中景/特写/全景/低角度镜头。观众会将多样性视为制作水准。
  2. 不同的镜头运动——推近、拉远、横向弧线移动、环绕、手持、固定镜头、焦点转换。不能全都是“缓慢推近”。
  3. 空间中的不同身体位置——参见“已知基础设施问题”中的 Location-reference 规则。每个镜头都必须描述角色身后可见的不同墙壁/窗户/特征,让 SeeDance 在空间中移动,而不是复现同一个一模一样的背景。
  4. 每个节拍都要有充满活力的身体动作——参见上文的 [3c.1]。手势、身体前倾、转头、耸肩。不能只有面部动作。
  5. 该时间段对应的对白片段,并在镜头的提示词块中用 <<<voice_1>>>...<<<voice_1>>> 标记包裹。

SeeDance 调用模式:

generate_reference_video(
  provider: "seedance",
  resolution: "1080p",
  aspect_ratio: "16:9",
  duration: 15,
  seed: 101,                   # unique per act (101, 202, 303, 404) — busts the idempotency cache
  sound: true,                 # native lip-sync from each <<<voice_1>>> block
  reference_images: [character_url, location_url, ...assets_for_this_act],
  prompt: <full prompt — see template in section above, 3 time-coded sub-shots inline>
)
# ... × 4 acts, all in the same message ...

注意:

  • 在 SeeDance 上,每幕生成约需 3-8 分钟。如果生成以异步方式完成,请持续查询 MCP 工具返回的状态句柄,直到该幕达到终止状态。
  • 完整提示词(开场白 + CHARACTER VOICE + 3 个带 Acting beats 的子镜头 + 每个镜头各自的 <<<voice_1>>> + 转场行)放入单个 prompt 参数中。SeeDance 没有 shots:[] 数组——多镜头结构通过文字描述。
  • 使用唯一种子(101、202、303、404),避免外观相同的调用被哈希为同一个缓存任务 ID。seed 参数仅适用于 seedance。

按提交顺序将返回的 4 个 URL 保存为 act_urls = [act1, act2, act3, act4]。

[5.5] 确定性数字界面叠加层

此步骤在四个 Seedance 分镜段均可用后、步骤 [6] 之前运行。为提高效率,请先运行下方的跨分镜段身份 QA,并使用最终通过验收的 act_urls;如果身份 QA 后续重试了某个分镜段,请丢弃旧的叠加层输出并重新运行此步骤。此步骤旨在让数字产品展示以像素为依据:观众看到的手机/产品屏幕画面来自真实捕获的屏幕截图或渲染的字标,而非 Seedance。

如果 product_type !== "digital",请设置 ui_grounded_act_urls = act_urls 并继续。

如果 product_type === "digital":

  1. 从所有类型为 C 或 E 的脚本分镜中构建 digital_reveal_shots。每个脚本中的 C/E 类数字产品展示分镜都必须有非空的 asset_index,且该索引必须指向 usable_product_assets 中的 digital_screen 条目。如果任何脚本中的 C/E 类数字产品展示分镜的 asset_index: null,请停止并展示该脚本分镜;不要继续进行 Seedance 拼接,也不要复制原始 act_urls。根据通过验证的展示分镜构建 digital_reveal_plan。每个计划中的叠加层都保存以下内容:

    • act、shot、asset_index、asset_url
    • 来自 usable_product_assets[*].analysis.visible_copy 的 visible_copy
    • brand_name = state.brand.name
    • 预期文本列表:精确的 brand_name,以及对推介内容重要且简短易读的 visible_copy 语句

    如果 digital_reveal_plan 为空,请停止并展示脚本分镜及 usable_product_assets;不要在没有真实 UI 的情况下悄悄发布数字产品视频。如果任何脚本中的 C/E 类数字产品展示分镜指向缺失或非 digital_screen 资源,请在合成前停止。如果数字产品展示缺少对应的叠加层,不要复制原始 act_urls;只有不含数字产品展示分镜的分镜段才可以原样通过。

  2. 对每个唯一的 asset_url,使用 render_html_animation 渲染一个 15 秒的叠加层片段;需要 alpha 通道时使用 format: "mov"。将返回的 URL 保存为 ui_overlay_clip_url。

    • HTML 应将真实屏幕截图/捕获的 UI 放在具有正确宽高比的圆角手机屏幕边框内。
    • 如果真实屏幕截图中的品牌字标缩放后太小而无法辨认,请添加使用 state.brand.name 的精确确定性字标行;不要臆造更短的别名。
    • 叠加层背景应保持透明或在视觉上与背景隔离,以便将其作为确定性手机/UI 叠加层覆盖到生成的分镜段上。
  3. 使用 edit_video_compose 将叠加层合成到每个计划中的分镜段:

edit_video_compose(
  base_video_url: act_urls[act - 1],
  overlays: [{
    video_url: ui_overlay_clip_url,
    position_px: <safe phone-screen or panel placement>,
    width_px: <large enough for OCR-readable brand/product UI>
  }]
)

生成的手机目标稳定时,请使用手机屏幕位置。如果手机目标不够稳定,无法干净地覆盖,请使用稳定的叠加面板位置,且不要遮挡创始人的脸部或字幕区域。将每个编辑后的结果保存到 ui_grounded_act_urls[act - 1];未更改的分镜段从 act_urls 复制。

  1. 如果合成后仍需要简短准确的品牌名称,请对该分镜段调用 edit_text_overlay,并设置 text: state.brand.name。这仅用于确保品牌名称拼写准确,不用于添加字幕。将更新后的 URL 保存回 ui_grounded_act_urls[act - 1]。

  2. 拼接前,使用 extract_frame 和 analyze_media 对每个添加了叠加层的展示分镜段进行 OCR QA:

extract_frame(video_url: ui_grounded_act_urls[act - 1], time_s: <midpoint of the reveal shot>)

analyze_media(
  media: overlay_qa_frame_url,
  query: "OCR/read all visible text on the product UI or wordmark. Return JSON only: {
    \"brand_name_visible\": \"yes\" | \"no\" | \"unclear\",
    \"brand_name_exact\": \"yes\" | \"no\" | \"unclear\",
    \"visible_copy_ok\": \"yes\" | \"no\" | \"unclear\",
    \"garbled_text\": string[],
    \"misspellings\": string[],
    \"verdict\": \"clean\" | \"degraded\" | \"catastrophic\"
  }. The exact expected brand name is ${brand_name}. The exact expected visible_copy is ${visible_copy}; visible_copy_ok: "yes" only when the important expected UI copy is present/readable, or when no short visible_copy was provided. Examples like Lineer, Figoff, random letters, malformed UI copy, or AI-imagined UI copy that replaces the expected visible_copy are garbled/misspelled."
)

只有 brand_name_visible: "yes"、brand_name_exact: "yes"、visible_copy_ok: "yes" 且 verdict: "clean" 时才能继续。如果 OCR 显示品牌名称缺失、拼写错误或乱码,预期的可见文案缺失或被替换,或 verdict 为 degraded/catastrophic,请停止并展示 overlay_qa_frame_url、ui_overlay_clip_url、预期的 brand_name、预期的 visible_copy 及 QA JSON。不要将原始或由 AI 臆想的手机文字带入步骤 [6]。

第 [6] 步之前的跨片段身份质检

在执行 edit_concat 之前,先针对同一组可比较的视觉素材进行跨片段身份检查。目的是在问题片段仍可重新生成时发现创始人换人,而不是等 60 秒正片拼接完成后才发现。

  1. 从每个片段的三个子镜头时间窗中各提取一帧。每个片段只取中间的一帧并不足够;创始人可能在第一个或最后一个子镜头中换人,但检查仍可能通过。
identity_frame_times_s = [2, 7, 12]
for each act_urls[i]:
  for each time_s in identity_frame_times_s:
    extract_frame(video_url: act_urls[i], time_s)
# Save as act_identity_frames = [
#   { label: "act 1 shot 1", act: 1, shot: 1, time_s: 2, url: ... },
#   ...
#   { label: "act 4 shot 3", act: 4, shot: 3, time_s: 12, url: ... }
# ]
  1. 使用 html_to_png 渲染一张身份联系表。每张远程图片都使用 CSS background-image: url(...)。这张联系表必须在一张图片中包含十三个带标签的面板:founder reference(founder_photo_url / character_url),然后是 act 1 shot 1、act 1 shot 2、act 1 shot 3,依次直到 act 4 shot 3。将返回的文件保存为 identity_contact_sheet_url。
html_to_png(
  html: "<html>... founder reference ... act 1 shot 1 ... act 1 shot 2 ... act 1 shot 3 ... act 2 shot 1 ... act 3 shot 1 ... act 4 shot 3 ...</html>",
  format: "png",
  mode: "sync",
  raster_options: { viewport_px: { width: 2200, height: 1600 }, device_scale: 1 }
)
  1. 对 identity_contact_sheet_url 调用一次 analyze_media:
analyze_media(
  media: identity_contact_sheet_url,
  query: "Return JSON only: {
    \"same_founder_as_reference\": \"yes\" | \"unclear\" | \"no\",
    \"same_founder_across_acts\": \"yes\" | \"unclear\" | \"no\",
    \"wardrobe_consistent_with_lock\": \"yes\" | \"unclear\" | \"no\",
    \"bad_act_numbers\": number[],
    \"bad_frame_labels\": string[],
    \"identity_observations\": string[],
    \"verdict\": \"clean\" | \"degraded\" | \"catastrophic\"
  }
  Compare the founder reference panel against all twelve act panels: act 1 shot 1 through act 4 shot 3. Check face, hair, age, body type, and wardrobe; do not treat normal pose, expression, camera angle, or lighting changes as identity drift."
)

如果无法渲染联系表,请停止并报告联系表渲染失败;不要在身份未经验证的情况下继续。只有身份质检结果全部为 yes / yes / yes 时才能继续。如果质检返回 same_founder_as_reference: "no" 或 same_founder_as_reference: "unclear"、same_founder_across_acts: "no" 或 same_founder_across_acts: "unclear"、wardrobe_consistent_with_lock: "no" 或 wardrobe_consistent_with_lock: "unclear"、bad_act_numbers 非空、bad_frame_labels 非空,或 verdict: "degraded" 或 verdict: "catastrophic",则不要继续拼接。只针对问题片段重试一次,使用相同的提示词和相同的 reference_images,并使用新种子(original_seed + 1000),再额外添加一句提示词:Identity continuity is mandatory: the on-camera founder remains the same person as @Image1 for the entire act. 重试后,提取重试片段的全部三个帧时间点,重建完整联系表,并重新运行同一质检。如果问题片段重试后有任何 act_urls 条目发生变化,请丢弃 ui_grounded_act_urls 和之前所有叠加层/OCR 证据,针对最终的 act_urls 重新运行第 [5.5] 步,然后在第 [6] 步之前重新运行其 OCR 质检。如果重试后跨片段身份质检仍未通过,请停止并报告 identity_contact_sheet_url、问题片段 URL、bad_frame_labels 和质检 JSON;不要交付创始人不同的拼接视频。

时长下限与部分片段恢复

第 [6] 步之前必须准备好全部 4 个 act_urls。不要拼接不完整的片段列表。 三个已完成片段加上片尾卡会生成约 50 秒的视频,未达到 55 秒时长下限,不得报告为成功的创始人视频。

如果某个 SeeDance 片段进入失败终止状态、变为 cancelled,或根据长时间运行的轮询约定进入终止状态或成功取消,而其他片段已完成:

  • 使用相同的提示词、reference_images、duration、sound、resolution 和 aspect_ratio 重试缺失片段一次,但使用新种子(original_seed + 1000)。不要重新运行已成功的片段。
  • 如果重试完成,将该 URL 放入原片段位置,并继续使用 act_urls = [act1, act2, act3, act4]。
  • 如果重试无法完成,请停止并报告上游 SeeDance 超时。可以返回已完成片段的 URL 作为诊断预览,但不得将不完整拼接作为 final_url 交付,不得称其为可用于生产环境的成品,也不得继续执行第 [6] 步。

如果片段任务原本仍处于 queued、running 或 processing 状态,不要重试停滞的片段。继续轮询并显示进度,然后在总时限达到 15 分钟时调用 task_cancel({task_id}),再进行一次缺失片段重试。

[6] 将片段拼接为 60 秒基础视频

edit_concat(video_urls=ui_grounded_act_urls)

保存为 base_url(60 秒、16:9、原生对白音频)。对于非数字产品,ui_grounded_act_urls 等于 act_urls;对于数字产品,它包含第 [5.5] 步中已叠加界面的展示片段。如果存在数字 UI 叠加层方案,不要将原始 act_urls 输入拼接工具。

[7] 生成背景音乐——纯器乐,目标时长约 60 秒

模式固定,声音风格由各品牌自行决定。 使用 Kling audio,因为它支持 background: true,而 MCP 工作线程现在可以处理长音轨延展:先生成一段 10 秒的 Kling 音频种子,再通过 ffmpeg 循环/交叉淡化,在本地延展至所需的 60 秒。提示词中使用什么流派、乐器配置和情绪由你决定——选择符合品牌调性、创始人表达风格和产品特点的风格。切勿逐字照搬下面的钢琴示例;那只是一种可能的声音,不是模板。

固定模式(不要更改):
  • provider: "kling-audio"
  • mode: "text_to_audio"
  • background: true
  • duration_seconds: 60
  • 不要添加 lyrics 字段。Kling 只使用提示词。
  • 不要调用第二个服务提供方,也不要手动拼接音频。MCP 工作线程负责单种子延展流程。
  • prompt 必须不超过 200 个字符。Kling 会对更长的提示词返回校验代码 1201,因此风格描述要简短。
创意决策(每个视频单独决定——根据 brief.tone、脚本氛围和产品背景进行选择):

不同品牌的音乐风格示例。请勿照搬;应匹配你所服务品牌的氛围:

品牌调性流派方向音色配置
技术 / 开发工具 / B2B SaaS企业级电影配乐铺底,平静如 Apple 发布会温暖的毡制钢琴、轻柔合成器铺底、稀疏的低频节奏,80–90 BPM
活泼 / 街头服饰 / 消费品lo-fi 嘻哈、轻松节拍带尘感的鼓点、爵士和弦重音、黑胶噪声,70–85 BPM
颠覆性 / 前卫 / 金融科技 / 加密货币极简电子乐、暗黑合成器浪潮模拟合成器贝斯、侧链铺底、半拍底鼓,90–100 BPM
时尚 / 奢华 / 生活方式极简 House、现代时尚电影配乐滤波 House 铺底、轻柔的四拍底鼓、French Touch 和弦,100–110 BPM
健身 / 活力 / 运动推进感十足的电子脉冲、健身训练风格脉冲合成器贝斯、渐强琶音、八分音符踩镲,110–125 BPM
餐饮 / 酒店业 / 咖啡馆温暖原声、独立民谣指弹原声吉他、轻刷小鼓、轻柔立式贝斯,80–95 BPM
电影感 / 品牌故事 / 纪录片管弦乐配乐、充满希望的渐强弦乐铺底、轻柔钢琴主奏、渐强铜管、逐步加快节奏
游戏 / 开发工具 / 创作者工具芯片音乐与现代风格融合、复古像素风方波主旋律、现代合成器铺底、利落小鼓,105–120 BPM

拿不准时:查看 brief.tone(技术、随性、活泼、专业、颠覆性),选择与创始人的声音特征和脚本情绪曲线相配、听起来不突兀的风格。匹配能量,不要与之对抗。

标准调用(将你的创意方向替换到 prompt 中,且不超过 200 个字符):
generate_music(
  provider: "kling-audio",
  mode: "text_to_audio",
  background: true,
  duration_seconds: 60,
  prompt: "<=200 chars: soft instrumental background bed; <register>, <main instrument>, <mood>, <BPM>; no vocals; leave room for narration>"
)

工作原理(关键环节):

  • Kling 生成一个 10s 的种子音频:付费服务商调用耗时较短,并支持在后台运行。
  • 工作器在本地扩展音频:MCP 使用本地 ffmpeg 循环播放/交叉淡化这个 10s 的种子音频,直至达到 duration_seconds: 60,然后返回扩展后的 CDN audio_url。
  • prompt 字段承载风格概述。加入 "soft instrumental background bed"、"no vocals" 和 "leave room for narration",确保混音不会盖过创始人的对白。保持在 200 个字符以内;如果 Kling 返回 1201,请缩短同一风格描述,而不是重试过长的 prompt。

将其保存为 music_url。读取 result.duration_seconds:

  • 如果 >= 55s → 进行混音。预期情况下,Kling 工作器会扩展音频。
  • 如果 < 55s → 不要默默接受时长过短的背景音。使用相同的 kling-audio 调用重试一次;如果返回的音频仍然过短,就停止并显示工具结果,因为工作器扩展流程未满足约定。

禁止的反模式(每种都曾在实际使用中导致失败):

  • ❌ 将 provider: "minimax-music" 用作默认生成的背景音——MiniMax 不支持 background: true,并且可能让旋律盖过旁白。
  • ❌ 在技能中手动循环拼接 10s 音频——MCP 工作器已经会在本地扩展一个 10s 的 Kling 种子音频。
  • ❌ 只在 prompt 文本中注明时长("60 second instrumental")——请使用 duration_seconds: 60。
  • ❌ 添加 lyrics 字段——此流程仅支持 Kling prompt。
  • ❌ 为每个品牌都照搬相同的钢琴与合成铺底示例——配方只是模式,不是固定音色。请根据品牌选择合适的音域。

[8] 合成层 — lower-third + 字幕

流程顺序说明——音乐混音在步骤 [10] 中进行,即片尾卡拼接之后。若在拼接片尾卡之前就将音乐混入正片,片尾卡将没有声音(音乐轨道会在剪切处结束)。始终按以下顺序操作:正片叠加层 → 片尾卡 → 拼接 → 然后再将音乐混入完整视频。

优先使用 MCP 工具。add_captions 会在服务端处理字幕时间轴和烧录;render_html_animation 用于制作 HTML 动效;edit_video_compose 用于添加透明 lower-third 叠加层。

默认流程
请求的图层默认操作
无 lower-third、无字幕body_with_overlays_url = base_url
仅字幕调用 add_captions(video_url: base_url, caption_mode:"auto", style:"classic", position:"bottom", font:"inter");将返回的 url 保存为 body_with_overlays_url
仅 lower-third通过 render_html_animation 渲染 lower-third .mov,然后调用 edit_video_compose;将返回的 url 保存为 body_with_overlays_url
lower-third + 字幕先渲染并合成 lower-third,然后对合成后的检查点 URL 调用 add_captions

如果 state.lower_third 为 false 或未设置,则跳过 [8a] 和 [8b]。这样默认流程就完全由 MCP 原生工具处理。

不要调用本地 Whisper/字幕脚本,也不要通过串联 edit_text_overlay 添加字幕。若必须保留原始脚本中的精确拼写,只有在已从可信来源获得精确的字幕时间段时,才传入手动的 subtitles[];否则优先使用 add_captions 的自动处理流程。

[8a] 渲染下三分之一画面(仅当 state.lower_third = true 时)

除非 state.lower_third = true,否则跳过此子步骤。通过 render_html_animation 渲染,并设置 format: "mov"(ProRes 4444,采用 yuva420p,可保留 Alpha 通道)。不要使用 format: "webm"——HyperFrames 目前会将 webm 输出为 VP9 pix_fmt=yuv420p,且不含 Alpha 通道,因此“透明”区域会变成纯黑像素,合成后的下三分之一画面会在胶囊形区域外显示黑框。目前,.mov ProRes 路径是唯一可靠的 Alpha 通道处理方式。

  • 原生尺寸:800×220(与 1280×720 画面中的放置尺寸相匹配,因此不会产生缩放瑕疵)
  • 胶囊形区域:背景使用 state.brand.colors.primary(默认值 #0d0d0d),边框使用 state.brand.colors.highlight(默认值 #fefbcf),投影使用 state.brand.colors.accent(默认值 #cfc3ff),边框圆角为 18px
  • 双行文本:founder_name(Space Grotesk 800,80px,白色)+ founder_role(Space Grotesk 500,28px,奶油黄)
  • 胶囊形区域内不要放置徽标——品牌标志放在片尾卡中;下三分之一画面用于介绍人物
  • 仅使用 CSS @keyframes:0–0.6s 从 translateX(-900px) 滑入,约 3s 时轻微脉冲投影,4–5s 滑出。下三分之一画面动画不要使用 GSAP;片尾卡的逐帧定位问题同样适用。
  • 将 URL 保存为 lower_third_url(文件扩展名为 .mov)

如果需要验证 .mov,请检查视频流的像素格式,并确认其中包含 Alpha 通道(yuva...)。如果格式是普通的 yuv...,说明 Alpha 通道已丢失——请切换渲染格式或重新渲染。

[8b] 下三分之一画面叠加层

仅在启用下三分之一画面时使用此步骤。默认使用 MCP 合成路径:

edit_video_compose(
  base_video_url: base_url,
  overlays: [{
    video_url: lower_third_url,
    position_px: { x: 50, y: <video_height - 220 - 100> },
    width_px: 800,
    height_px: 220,
    start_s: 0,
    end_s: 5
  }]
)

将返回的 url 保存为 body_with_lower_third_url。

仅当 MCP 合成不可用时,使用本地备用方案:

  • 仅在此本地合成步骤中下载 base_url 和 lower_third_url。
  • 在 x=50、y=video_height - 220 - 100 处叠加 800×220 的下三分之一画面,并设置其在 t=0..5s 期间启用。
  • 保留原始主体音频,不重新编码,以确保唇形同步精准。
  • 本地检查点使用视觉无损的 H.264 设置。
  • 使用 upload_asset 上传检查点,并将返回的 public_url 保存为 body_with_lower_third_url。

如果还需要字幕,请调用 add_captions(video_url: body_with_lower_third_url, ...),并将返回的 url 保存为 body_with_overlays_url。否则,令 body_with_overlays_url = body_with_lower_third_url。

[8c] 通过 MCP 添加字幕

默认调用:

add_captions(
  video_url: <base_url or body_with_lower_third_url>,
  caption_mode: "auto",
  style: "classic",
  position: "bottom",
  font: "inter",
  font_color: "#ffffff",
  highlight_color: state.brand.colors.accent or "#cfc3ff",
  outline_color: state.brand.colors.primary or "#111111",
  font_size: 42
)

将返回的 url 保存为 body_with_overlays_url。返回的 transcript 可用于 QA,但视频 URL 才是流水线产物。

[9] 动画片尾卡(5s)——编写内联 HTML,通过 HyperFrames 渲染

此处不使用 generate_slide_animation。该工具会将 HTML 编写工作委托给幻灯片卡片大模型,后者经常添加角落杂乱元素(左上角的字标、右下角的 URL)、选择错误的画面比例,并生成无法通过 HyperFrames 逐帧定位可靠播放的动画。我们改由编排器直接编写片尾卡 HTML,并通过 render_html_animation 渲染。下三分之一画面也使用同一引擎。

硬性规则——经实测验证,不得偏离

这些不是风格偏好。每一条都经过实际渲染、提取帧并与预期进行比较后得出,并发现了相应的具体故障。撤销其中任何一条都会导致已知问题重现。

  1. **画面比例必须与主体视频一致。**读取 aspect_ratio(默认值为 16:9)。计算 #stage 的 data-width × data-height:16:9 → 1920×1080、9:16 → 1080×1920、1:1 → 1080×1080。硬编码错误的方向会导致拼接后画面出现侧边栏,主体视频和片尾卡会并排播放,而不是按顺序播放。

  2. 不要在角落堆放元素。 左上角不要放文字标识,底部不要放 URL,标题旁不要放圆角方形图标。片尾卡只应包含一条居中的消息和 CTA。品牌标识由字体和配色体现;显式放置 Logo 会与标题争抢注意力,显得杂乱。(如果用户明确要求放置 Logo,请将其融入居中的内容组合中,绝不要放在角落。)

  3. 入口动画使用 CSS @keyframes,不要使用 GSAP tl.from()。 HyperFrames Chrome 通过 BeginFrame 逐帧跳转;GSAP 的 tl.from() 会在首次播放时延迟记录初始状态,在仅跳转播放的情况下不会触发——每一帧都会渲染静态的最终状态,没有入口动画。CSS @keyframes 与 Chrome 的合成器时钟绑定,可逐帧确定性地播放。通过 #stage / #card 的 data-duration 属性声明时长;不要为了设定时间而额外添加 GSAP 脚本。使用 GSAP 时,重复捕获的帧在 t=0 和 t=2s 时完全相同;改用 CSS @keyframes 即可解决此问题。

  4. 所有入口动画都必须在 t = duration - 0.5s 前结束。 保留半秒,让最终状态在切换前清晰可读。若 duration: 5s,则所有动画的 animation-delay + animation-duration <= 4.5s。

  5. 动画元素使用绝对定位,不要使用 flex。 在 HyperFrames Chrome 中,flex 布局在第 0 帧时无法完全稳定,这会加剧上述 GSAP-from() 问题——元素会在动画中途弹出,因为 flex 还在进行第二轮布局。纯绝对定位可从第 0 帧起提供稳定且确定的布局。

  6. 为每个 @font-face 指定唯一的 font-family 名称;不要依赖字重匹配。 声明两个 @font-face { font-family: "telka"; ... font-weight: 700/500; } 块,理论上可让 CSS font-weight: 500 选中 500 字重的字体,但在 HyperFrames Chrome 中,某些字重的匹配并不可靠。请使用不同的字体族名称:"telka-ext-900"、"telka-700"、"telka-500"。字重匹配失败时,标语可能会使用衬线字体回退;将标语改为显式加载的字体族即可避免此问题。

  7. telkaextended-900-normal.woff2 和 telka-700-normal.woff2 已确认可在 HyperFrames Chrome 中正常工作。telka-500-normal.woff2 已确认无法正常工作——它可通过 fontTools 成功解析(OS/2.usWeightClass=500 正确、cmap 有效、字体族名称正确),但 Chrome 会静默拒绝 @font-face 声明并回退到系统衬线字体。 解决方法:标语也使用 telka-700(同一字体族,字重略粗,但视觉上仍符合品牌风格)。如果未来的片尾卡需要中等字重,请先通过渲染并提取第 30 帧来测试候选 woff2,再发布。不要因为 Telka 700 可用,就认为 “Telka 400” 或 “Telka 300” 也一定可用。

  8. 将品牌套件字体以内嵌 base64 的方式提供。 Pika CDN 不接受上传字体(MIME 类型允许列表有限),也不发送 CORS 标头,因此 @font-face URL 引用在 HyperFrames Chrome 中会失效,字体会静默回退到系统衬线字体。使用 pyftsubset 将每个 woff2 子集化,仅保留标题、标语和 CTA 中的字形,再进行 base64 编码,并以 data:font/woff2;base64,... 的形式嵌入。子集化后的文件通常各为 5–10 KB。

  9. 品牌设计中不要为 CSS font-family 编写回退字体链。 如果品牌字体加载失败,回退字体链会掩盖问题——你可能会误以为交付的是 Telka,实际上用的却是 Helvetica。只使用 font-family: "telka-700"(不指定回退字体)。这样,字体加载失败时 Chrome 会渲染默认衬线字体,问题会一目了然,便于及时修复。

  10. 合成契约——HyperFrames 契约:<div id="stage" data-composition-id="main" data-start="0" data-duration="5" data-width="W" data-height="H"> 包含一个且仅有一个直接子元素 <div id="card" class="clip" data-start="0" data-duration="5" data-track-index="0">,其内包含其他所有内容。可见的定时元素必须包含 class="clip",因为 HyperFrames 会用它控制可见性;而且 clip 必须嵌套在合成根元素内,不能与其并列。多个直接子元素轨道与 #stage 配合时,帧定位效果不佳。(通过参照可正常工作的下三分之一结构修复。)

  11. 运行时就绪钩子——在 </body> 前加入一个小型兼容钩子: window.__hf = { duration: 5, seek: (t) => { document.documentElement.style.setProperty("--hf-time", String(t)); } };。 CSS @keyframes 仍会驱动视觉动画,但该钩子可确保生产环境的帧捕获流程在检测 window.__hf 时已就绪。如果工作器报告 window.__hf not ready after 45000ms,则将该 HTML 视为不适用于 render_html_animation;修复合成契约或钩子,然后重新渲染。不要退回使用静态 PNG。

  12. **渲染后,务必在 t=0、t=1s、t=2s 时提取帧并进行视觉比较。**如果第 0 帧和第 2 帧看起来相同,说明入场动画未运行。如果标语看起来像衬线字体,说明品牌字体未加载。不要只相信 URL。未完成此项检查,不要交付。(加入帧提取前,用户连续三次渲染都发现了这些问题。)

构建步骤
# 1. Decide canvas
W, H = {"16:9": (1920, 1080), "9:16": (1080, 1920), "1:1": (1080, 1080)}[aspect_ratio]

# 2. Pick palette + fonts from state.brand (with fallbacks)
bg      = state.brand.colors.surface  if state.brand else "#ffffff"
ink     = state.brand.colors.primary  if state.brand else "#0d0d0d"
accent  = state.brand.colors.accent   if state.brand else (accent_color or "#0d0d0d")
display_font_path = state.brand.fonts.display_path  # e.g. brand-kit/.../telkaextended-900-normal.woff2
body_font_path    = state.brand.fonts.body_path     # used for tagline + CTA
# If state.brand has no fonts, use the fallback branch below and flag this in the deliver step.

# 3. Subset fonts to only the chars used in title/tagline/CTA
glyphs = set(brief.product_name + brief.tagline + brief.call_to_action + " .,'-/")
if display_font_path and body_font_path:
    # Use a standard fontTools pyftsubset command or equivalent local font-subset utility.
    # Then base64-encode the subsetted woff2 bytes and inline them in @font-face data: URLs.
    display_b64 = "<base64 subsetted display woff2 bytes>"
    body_b64 = "<base64 subsetted body woff2 bytes>"
else:
    display_b64 = body_b64 = None

# 4. Author the HTML inline. Do not load a preset/template file.
#    Include #stage/#card contract, CSS @keyframes, absolute positioning,
#    @font-face data URLs when display_b64/body_b64 exist, title lines,
#    tagline, CTA, palette values, and dimensions W/H.

# 5. Render
end_card_url = render_html_animation(html=filled, fps=30, quality="standard", format="mp4")
布局(居中堆叠——无角落元素)
┌─────────────────────────────────────────────┐
│ ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬ │ ← top accent bar (animated wipe L→R)
│                                             │
│            BIG TITLE LINE 1                 │ ← display font 900, slides up
│            BIG TITLE LINE 2                 │ ← display font 900, slides up (staggered)
│                                             │
│                  ────                       │ ← short accent divider (scaleX in)
│                                             │
│             tagline goes here               │ ← body font 500, fades+rises
│                                             │
│         ╭─ Start with X ─╮                  │ ← CTA pill, accent bg, ink border, back-out pop + breath
│         ╰─────────────────╯                 │
│                                             │
└─────────────────────────────────────────────┘
动画时序参考(5s 片尾卡,CSS @keyframes)

所有动画均通过相应元素上的 CSS animation: name duration easing delay forwards 实现。元素动画前的 CSS 状态即为“from”状态——无需 JS。

t(s)元素动画
0.00–0.85顶部强调条scaleX:0 → 1,cubic-bezier(0.16,1,0.3,1)
0.25–1.00标题第 1 行(#title .l1)y:120, opacity:0 → y:0, opacity:1
0.42–1.17标题第 2 行(#title .l2)同上,错开播放
1.00–1.50分隔线scaleX:0, opacity:0 → 1, 1
1.20–1.75标语y:30, opacity:0 → y:0, opacity:0.9
1.55–2.15CTA 胶囊y:60, opacity:0, scale:0.92 → y:0, opacity:1, scale:1,cubic-bezier(0.34,1.56,0.64,1)(回弹式弹出)
2.60–4.20CTA 胶囊scale:1 → 1.05 → 1,交替播放(轻微呼吸感)
2.80–4.80顶部强调条opacity:1 → 0.55 → 1,交替播放(柔和闪烁)
4.80–5.00保持(最终可读状态)

参考实现模式:使用居中堆叠式 HTML 模板。在编排器中直接编写完整的 HTML,并直接传给 render_html_animation;不要调用打包的辅助脚本,也不要依赖单独的 presets/ 目录。

如果品牌套件缺少字体(state.brand.fonts 为 null),则标语和 CTA 回退使用系统字体 -apple-system, sans-serif,但标题改用系统显示字体字重。不要使用回退字体渲染品牌风格的片尾卡;效果总是不理想。在交付步骤中说明这一点,让用户知道品牌套件不完整。

将返回的 MP4 URL 保存为 end_card_url。end_card_url 必须是 MP4 视频片段,而非静态 PNG,因为步骤 [10] 会将其与主体视频拼接。只有在需要本地视觉 QA 帧或本地回退式拼接时,才下载该文件。

[10] 通过 MCP 组合正文、片尾卡和音乐

使用服务端的确定性编辑工具完成最终组装。当前 MCP 服务的 edit_concat 会在拼接前对不匹配的输入进行标准化,而 edit_audio_mix 会保留原视频音频,同时混入音乐音轨。

assembled = edit_concat(video_urls=[body_with_overlays_url, end_card_url])
assembled_url = assembled.url

if music_url:
  mixed = edit_audio_mix(video_url=assembled_url, audio_url=music_url, audio_volume=0.16)
  final_url = mixed.url
else:
  final_url = assembled_url

拼接完成后再混入音乐,绝不要提前混入,这样配乐才能持续到片尾卡结束。如果 edit_audio_mix 因音乐文件过短或格式错误而失败,请设置 final_url = assembled_url,说明音乐问题,并且在交付前仍要运行步骤 [10.5];不要重新运行耗费大量资源的 SeeDance 片段。

[10.5] 最低成片时长

向用户报告 final_url 前,探测组装结果:

analyze_media(
  media: final_url,
  query: "Return JSON with duration_seconds for this video."
)

将结果保存为 final_duration_seconds。报告 final_url 作为已完成交付内容前,其值必须 >= 55 且 <= 75。 如果 final_duration_seconds 少于 55s,请将本次运行视为组装未完成:不要将该 URL 作为最终结果交付,不要标记技能已完成,并返回上文的缺失片段恢复流程。如果 4 个片段都已就绪,但探测结果仍少于 55s,请停止并报告拼接/提供方截断问题以供调查,不要用无关视频素材补时长。

[11] 最终 URL

将 final_url 保存到 state。如果本地备用组装生成了最终 MP4,请通过 upload_asset 上传该检查点,并将 final_url 替换为返回的 public_url。

飞行后质量门槛

在宣布成功前,对 final_url 调用 analyze_media,并要求其返回结构化判定:

Return JSON only: {
  "verdict": "clean" | "degraded" | "catastrophic",
  "observations": string[],
  "quality_warning": string | null,
  "re_roll_suggestion": string | null
}
Check that `brief.product_name` / `product_name` is spelled correctly anywhere it appears, any phone screen / product screen shows the intended product instead of a hallucinated substitute, required product assets are visible in the expected acts, and the final video has no black frames or partial-act truncation.
  • 如果 verdict 为 clean,正常交付最终 URL。
  • 如果 verdict 为 degraded,交付最终 URL 和 quality_warning,以便用户在发布前进行检查。
  • 如果 verdict 为 catastrophic,不要将视频标记为完成;应报告该判定和 re_roll_suggestion,而不是宣布成功。

[12] 素材包(可选)

首先返回最终 URL。如果用户要求可编辑的源素材,请提供包含以下内容的素材包:

  • final_url
  • act_urls
  • character_url、location_url 以及任何产品/截图素材 URL
  • music_url
  • end_card_url
  • 可选的 lower_third_url / body_with_overlays_url
  • 脚本、品牌速查表和片段到素材的映射

这很重要,原因如下:

  • 用户可以替换某一层(创始人照片、字幕时机、音乐)并重新渲染,而无需重新获取所有素材
  • 品牌素材包是同一品牌未来视频的唯一真实来源;复用它只需复制一个文件夹
  • 单个片段级别的 .mp4 本身也很有价值(例如,用户可能只想剪辑其中一个片段,用于特定渠道)
  • 用户经常会要求将生成的参考素材与视频一并保存,以便复用。现已将此设为默认行为。

[13] 交付

向用户报告 final_url。包括:

  • 仅在用户要求时提供素材包 URL/路径
  • final_duration_seconds 中的总时长(约 65s = 60s 正文 + 5s 片尾卡)
  • 对重新运行有用的中间 URL 或本地文件:base_url、可选的 body_with_overlays_url、music_url、end_card_url、final_url 和每个 act_urls[i]
  • 简报(brief.product_name / brief.tagline),以便用户确认模型选对了产品
  • 用 1 行总结每个片段使用了哪项素材,以便用户确认素材放置位置

验证关卡

步骤检查
简报product_name 非空
资产分析每项资产各有一个 JSON 对象,其中 content_description 和 best_for_act 均非空
脚本4 幕;对白总计 100–180 个单词;每项资产至少被一幕引用,或明确标注为未使用
参考资料character_url 和 location_url 均为 https URL
幕返回全部 4 个 act_urls(每个使用唯一的 seed);对于包含 asset_index 非 null 的镜头的幕,使用 analyze_media 对其中一幕进行视觉检查,以确认资产确实可见,且展示方式符合 product_type(例如,对于 physical_apparel,确认创始人正手持或穿着印有正确图案的实际 T 恤——而不是在手机屏幕上展示)
拼接返回 base_url
音乐返回 URL;通过 kling-audio 背景音乐路径生成的 duration_seconds >= 55;若低于 55,则重试一次,然后停止并反馈
叠加层返回 body_with_overlays_url(或者如果跳过步骤 [8],则 body_with_overlays_url = base_url)
片尾卡返回的 end_card_url 为 MP4;使用 extract_frame/analyze_media 检查前几帧:第 0 帧应显示入场前的空背景,之后第一秒内的一帧应显示部分入场——这可以确认 CSS @keyframes 正在生效,而非静态画面
最终合成edit_concat 返回 assembled_url;有音乐时,edit_audio_mix 返回 final_url,否则 final_url = assembled_url
最终时长交付前,analyze_media 报告 final_duration_seconds >= 55 且 <= 75
本地回退上传仅当使用本地回退合成时:将 final_url 替换为上传后获得的 public_url

故障模式

除“时长下限和部分镜头恢复”中记录的一次缺失镜头重试外,首次验证失败时即停止并反馈。不要自动重试高成本调用(SeeDance 每幕运行 3–8 分钟——反复失败会消耗额度)。

从 analyze_brief / generate_image / generate_reference_video / generate_music / upload_asset 的上游 5xx 错误中恢复

如果任何付费生成、简报分析、音乐、渲染、编辑或资产 MCP 调用返回:

  • code: "provider_5xx" 且 retry_class: "retry_after_backoff"
  • 或来自任何上游提供商(Seedance、Kling、OpenAI、Gemini、存储服务)的 HTTP 502 / 503 / 504

请执行以下操作:

  1. 等待 5 秒。
  2. 使用完全相同的参数再次调用完全相同的 MCP 工具。不要改写简报、产品名称、创始人照片、幕提示词、seed、参考图片顺序、音乐提示词或上传载荷。
  3. 如果重试仍返回 5xx,则中止并向用户反馈:“提供商连续两次返回瞬时上游错误。请在 1–2 分钟后重试;此问题通常会自行消失。”

最多重试一次。此流程用于处理提供商的瞬时故障;5xx 后更改创意输入会生成不同的素材,并可能造成重复支出。

从上游 4xx / moderation_blocked 错误中恢复

如果在创建创始人/地点/产品参考素材时,generate_image 返回上游 4xx 或 moderation_blocked:

  1. 不要使用相同提示词重试;审核拦截和大多数 4xx 验证失败都是确定性的。
  2. 如果该资产对用户而言并非关键,仅当替代方案仍符合简报时,才尝试一次备用提供商。对于创始人身份照片,任何备用提供商都不得更改用户身份;请改为请求更安全的/由用户提供的参考素材。
  3. 如果备用提供商也失败,或会更改产品/创始人身份,请向用户反馈:“图像提供商拒绝了此参考提示词。请提供其他参考图像,或选择辨识度较低/风格化程度较低的方向。”

对于 Seedance 幕的审核拦截,仅在适用时遵循时长下限/缺失镜头恢复流程。不要盲目反复重试镜头生成。

从上游 429(速率限制)恢复

如果任何上游返回 HTTP 429 并提供退避提示:

  1. 等待提示的退避时间;如果未提供提示,则等待 30 秒。
  2. 使用完全相同的参数重新调用完全相同的 MCP 工具。
  3. 最多重试一次。如果仍然返回 429,则中止并显示速率限制消息。
capture_website 返回空结果 / 页面未加载

此技能通常使用 analyze_brief 提取产品信息,但 URL 简报辅助工具可能会调用 capture_website。如果 capture_website 返回 200,但 action_bboxes 为空或 recording_viewport 为 0x0:

  1. 不要重试;页面未能在捕获环境中渲染。
  2. 显示:“无法捕获 。该页面可能被屏蔽、设有付费墙或需要身份验证。请改为提供产品简报、屏幕截图或托管资源。”
upload_asset 网络 / 身份验证失败

如果 upload_asset 在将创始人照片、产品资源、品牌徽标、字幕条或本地备用素材转换为托管 URL 时失败,请勿继续在 reference_images 或 HTML 中使用本地文件系统路径。对于上述 5xx 或 429 类错误,仅重试一次。如果出现 auth_error、不支持的 MIME 类型、网络故障或重复上传失败,请停止操作,并请求提供托管 URL 或受支持的栅格图像导出文件。

长时间运行的 task_status 超过上限

每个异步 MCP 调用都会返回内联结果,或返回 {task_id, status} 以供轮询。在判定任务卡住之前,请使用以下上限:

  • Seedance i2v:每次调用 10 分钟
  • Kling 音频:每次调用 5 分钟
  • gpt-image-2 高质量:每次调用 3 分钟
  • 渲染 / 编辑 / 上传辅助工具:5 分钟

以较早到达的限制为准:提供商上限的 1.5 倍,或任何技能专用的硬性轮询上限(包括上文长时间运行的 task_status 轮询约定中的 15 分钟总上限)。如果 task_status 在该较早的限制之后仍返回 status: "processing" 或 status: "queued",请调用 task_cancel({task_id}) 并显示:“提供商耗时异常,正在中止。请重试。”

症状原因修复方法
generate_reference_video 返回 402“insufficient balance”,且 UUID 看起来很熟悉幂等性缓存为相同参数重放了旧的失败结果每次调用传入唯一的 seed(4 个分镜分别使用 101 / 202 / 303 / 404),使哈希值不同。
SeeDance 对创始人参考图返回 422“may contain likenesses of real people”触发了内容政策过滤器(偶尔发生——同一张照片下次尝试可能会通过)使用更强的风格化效果重新生成创始人肖像(“Pixar / Disney 3D animation aesthetic”)。不要自动重试同一张参考图——这会消耗额度。
创始人的衬衫在不同分镜中发生变化每个分镜都会重新读取 @Image1,没有锁定服装在每个分镜提示词中加入 WARDROBE LOCK: 行,且每次都使用完全相同的句子。
4 个分镜的实际背景都相同开场白写着“inside the location matching @Image2”——被按字面意思理解了开头改为“in a setting whose visual style, palette, lighting and materials match @Image2”,并为每个镜头添加 Background context: 行。
创始人看起来僵硬/没有肢体语言节拍只涉及面部表情;分镜只有单个镜头为每个分镜添加 3 个带时间码的子镜头,并明确写出镜头运动的 Transition: 行;每个节拍都需要手部/躯干/头部动作(参见 [3c.1])。
最终视频不足 55 秒某个 SeeDance 分镜超时,或最终拼接时裁掉了主体部分,导致只生成了部分内容不要将其作为最终成品交付。保留已成功生成的分镜,用新的 seed 重试缺失的分镜一次;如果仍无法完成,则停止并报告上游 SeeDance 超时。
音乐提示词因代码 1201 被拒绝kling-audio 提示词超过了提供方的 200 字符限制将提示词缩短为规范的、不超过 200 字符的风格描述。保留 soft instrumental background bed、no vocals 和 leave room for narration;不要更改提供方、时长或背景模式。
音乐时长不足 55 秒kling-audio 工作进程扩展时长未能满足 60 秒的请求确认调用使用了 provider: "kling-audio"、mode: "text_to_audio"、background: true 和 duration_seconds: 60。重试一次;如果仍然过短,则停止并报告工具结果。
音乐盖过了对白提示词要求旋律突出,而不是背景音乐用“soft instrumental background bed, no vocals, leave room for narration”重新生成一次,并在步骤 [10] 中将 audio_volume 保持在 0.16 或更低。
字幕将产品名称拼错自动转录对口语音频进行了规范化处理仅当你已有可信的带时间戳片段时,才使用手动 subtitles[];否则应说明转录的局限,不要默认运行本地 Whisper。
下三分之一叠加层的胶囊框外出现黑框webm 格式编码时未包含 alpha 通道(yuv420p)使用 format: "mov"(ProRes 4444 yuva)重新渲染。使用 ffprobe | grep pix_fmt 验证结果显示 yuva*。
最终视频的音频比视频短本地回退拼接使用了 -c copy,但音频参数不匹配优先使用 MCP edit_concat。如果必须进行本地拼接,则在拼接前将所有输入规范化为 aac/44100/stereo/192k。
片尾卡在 t=0 和 t=2s 渲染结果相同(没有入场动画)使用了 GSAP tl.from(),而不是 CSS @keyframes将入场动画改为 CSS @keyframes;仅将 GSAP shim 用于时长定位。
片尾标语渲染为衬线字体回退样式woff2 字体未能在 HyperFrames Chrome 中加载为每个字型使用唯一的 font-family 名称(不要按字重匹配);对子集化后的 woff2 进行 base64 内联;交付前先提取第 30 帧进行验证。
render_html_animation 失败,报错 window.__hf not ready after 45000ms片尾 HTML 未暴露运行时就绪钩子,或未提供有效的嵌套 class="clip" 合成结构添加/修复 window.__hf 钩子和 class="clip" 子元素,然后重新渲染 MP4。不要回退为静态 PNG;在 end_card_url 成为视频 URL 之前,不要继续拼接。

承重短语

这些字符串会原样写入 SeeDance 提示词(或 HTML 渲染内容)。每个字符串都经过实证验证——改写会悄无声息地破坏整个方案。编辑提示词时,请搜索这些锚点并保持原样。

短语用于承重原因
The character (matching @Image1) in a setting whose visual style, palette, lighting and materials match @Image2.每个场景提示词的开场句“in a setting whose style matches”让 SeeDance 能在每个镜头中变换背景;“inside the location matching”则会在全部 4 个场景中复现完全相同的背景。
WARDROBE LOCK: …(在全部 4 个提示词中,后面都接同一句服装描述)每个场景提示词中 CHARACTER VOICE: 下方的标题行锁定不同 15 秒生成片段中的服装。仅靠 @Image1,服装可能会在不同场景间发生偏移。
Background context: …(每个子镜头各一条,每个位置都不同)每个镜头块内强制 SeeDance 为每个镜头渲染不同的实际位置——不同的墙面、不同的角度、不同的背景特征。没有这条,全部 3 个子镜头最终都会出现在同一个角落。
<<<voice_1>>>…<<<voice_1>>>每个镜头的对白内容SeeDance 原生唇形同步令牌。引擎通过这些令牌识别需要同步口型的内容;没有它们,就完全不会进行唇形同步。
Transition: … / Hard cut:同一提示词中各子镜头之间Transition: 描述连续的镜头运动(滑动/推轨/弧形移动);Hard cut: 会触发真正的切镜。两者都没有时,SeeDance 默认会在同一位置重新取景,呈现出跳切缩放的效果。
Native lip-synced dialogue audio, no music overlay.每个场景提示词的结尾句防止 SeeDance 在对白下方叠加自己的环境音乐,以免与步骤 [10] 中专门制作的背景音乐相冲突。
provider: "kling-audio"、mode: "text_to_audio"、background: true、duration_seconds: 60步骤 [7] 的 generate_music 调用使用唯一支持背景音乐的音乐提供方,并触发 MCP 工作进程的单次 10s Kling 种子音频 + 本地 ffmpeg 延展流程。

不要做的事

  • 不要以 “inside the location matching @Image2” 开头编写 SeeDance 提示词——这会让所有段落都复现同一字面背景。请使用 “in a setting whose visual style ... match @Image2”。
  • 不要在提示词正文中描述角色——@Image1 已承载角色身份信息。正文描述与之冲突会产生幻影人物或错误服装。例外:WARDROBE LOCK: 这一行。
  • 不要使用电影行业的镜头术语——“Two-shot” / “Three-shot” / “Over-shoulder” / “OTS” / “Master shot” 会触发 SeeDance 的幻影主体伪影。请用通俗语言描述摄像机所拍到的内容。
  • 不要将 lower-third 渲染为 webm——alpha 通道不会保留(HyperFrames 会输出 yuv420p)。请使用 format: "mov"(ProRes 4444 yuva)。使用 ffprobe \| grep pix_fmt 验证。
  • 不要对片尾卡使用 generate_slide_animation——该工具的幻灯片卡片 LLM 会添加角落杂物,并生成无法确定性定位的动画。请直接编写 HTML,并通过 render_html_animation 渲染。
  • 不要串联调用 pika MCP 的 edit_text_overlay / overlay 来排版任意文本或字幕——这会导致画质逐步下降,还可能造成口型同步漂移。字幕请使用 add_captions;有界 lower-third 请通过一次 compose/本地处理完成。例外:步骤 [5.5] 中的确定性数字 UI overlay 会特意使用一次有界 edit_video_compose 处理,并可选择搭配精确品牌的 edit_text_overlay,随后进行 OCR QA,以避免文本由 Seedance 生成的品牌/UI 内容。
  • 除非 MCP 不可用,否则不要使用本地 ffmpeg concat -c copy 进行最终合成——旧的音频丢失问题出在本地 concat 行为上。默认使用 MCP edit_concat + edit_audio_mix。
  • 不要在各段中以相同参数调用 SeeDance——MCP 幂等缓存会计算出相同的任务 ID,并重放旧结果(有时是失败结果)。请为每段传入唯一的 seed。
  • 不要将 MiniMax 用于默认生成的铺底音乐——它不支持 background: true,可能会让旋律在旁白下方过于突出。
  • 不要在技能中手动平铺 10s Kling 片段——MCP worker 会处理 duration_seconds: 60 所需的本地 ffmpeg 延长路径。
  • 不要对所有品牌照搬示例音乐的音色——配方指的是 Kling 铺底音乐调用,而非具体的配器。请选择符合 brief.tone 的音区(见步骤 [7] 表格)。

引擎选择:仅使用 seedance(注意事项)

SeeDance(通过 generate_reference_video 的 provider: "seedance" 调用 fal-seedance-2-i2v)是唯一的视频引擎。经测试后,相较于其他方案选择了它:

  • 与 Kling v3-omni 相比:Kling 有真正的 shots[] 硬切数组(多镜头更干净),但不接受 seed 参数(更难绕过缓存);而 4 个专业级 1080p 输出总计超过 50MB,会超出 edit_concat 上传上限(迫使使用本地 concat)。Kling 对真人照片的内容政策确实更宽松——如果 SeeDance 偶发的 422 错误变成硬性阻断,可考虑将其作为备用方案。
  • 与 Happy Horse happyhorse-1.0-r2v(Alibaba DashScope)相比:它能生成干净的 1080p 视频并支持原生口型同步,但多镜头提示词的引导效果较弱,电影感也明显不如 SeeDance。
  • SeeDance 胜出的原因:支持原生 <<<voice_1>>> 口型同步、接受 seed(可绕过缓存),对真人照片的限制足够宽松,95% 以上的运行都能通过内容过滤;单条 15s 提示词搭配带时间码的子镜头,足以让对话镜头呈现足够的变化。

如果 SeeDance 故障,或其内容过滤器开始反复拒绝你的创始人参考图,文档中建议的备用方案是使用更强的风格化效果(Pixar / Disney 3D 美学)重新生成创始人肖像。在流水线中途切换引擎会改变提示词、concat 和素材大小流程中的太多假设。

运行时预期

每个步骤的墙钟时间。总运行时间约为 12–18 分钟,主要耗时在并行 SeeDance 批处理中。

步骤墙钟时间备注
[1] analyze_brief20–60 秒
[2] analyze_media × N每个素材 15–30 秒,并行
[4] 创始人/自定义地点参考每项 10–60 秒上传本地创始人照片、使用提供的 URL,或生成创始人肖像;默认地点会等待 [4.5]
[4.5] 品牌套件导入 + 默认地点10–30 秒解析品牌套件、上传 Logo 素材;如有需要,渲染与宽高比匹配的品牌点缀背景
[5] SeeDance × 4 并行墙钟时间 5–9 分钟(最慢阶段)每个阶段耗时 3–8 分钟,也可能异步完成
[5.5] 数字界面叠加层数字产品需 30–120 秒渲染真实界面/字标叠加片段,将其合成到揭晓阶段,然后在拼接前进行 OCR 质量检查
[6] edit_concat(阶段 → 60 秒正文)30–60 秒
[7] generate_music30–90 秒;若不足 55 秒则重试一次Kling 生成一段 10 秒的种子音频,然后由工作器在本地延长至约 60 秒
[8a] 将 LT 渲染为 .mov60–120 秒ProRes 4444 比 webm 慢,但这是唯一支持 Alpha 通道的路径
[8] add_captions30–90 秒仅字幕,或在 lower-third 检查点之后添加
[8b] 本地 lower-third 叠加层备用方案20–60 秒仅在启用 lower-third 时
[9] 渲染片尾卡60–120 秒
[10] edit_concat + edit_audio_mix30–90 秒服务端标准化拼接并混合音乐
总计12–18 分钟

默认设置

  • 4 段 15 秒的 SeeDance 表演,并行生成,使用不同的种子(101、202、303、404)
  • 角色身份来自 @Image1 参考图——避免在提示词文本中描述角色(不要写“创始人 Avery”或“年轻的创意街头服饰创始人”)。每条提示词都以 "The character (matching @Image1) in a setting whose visual style, palette, lighting and materials match @Image2." 开头。使用“inside the location matching @Image2”会让 SeeDance 在所有表演中复现完全相同的背景。唯一例外是每段表演提示词中的 WARDROBE LOCK: 行,用于确保 4 次独立的 15 秒生成中服装一致。
  • 避免使用 SeeDance 会按字面理解的电影行业镜头术语——绝不要写“Two-shot”“Three-shot”或“Master shot”。镜头 F 为“品牌背景镜头”。
  • 每个脚本都有 character_voice_profile(用 3-4 行描述默认表达方式——语速节奏、标志性手势、停顿习惯)。在每段表演的 SeeDance 提示词中逐字重复为 CHARACTER VOICE: …。
  • 每个镜头都有 beats[],而不是在表演层级设置 acting。每个 beat 都有 text + emotion + physical。无声的 (beat) 条目用于指示口述句子之间发生的动作(停留的目光、细微表情、手势转换)。Beats 会作为每个镜头的“表演节拍”区块写入 SeeDance 提示词。
  • 表演中除第一个镜头外的每个镜头都有 transition_from_prev——描述如何通过连续的摄影机移动,从上一镜头的取景过渡到当前取景(滑轨移动、弧线移动、向前推进经过、向后拉远、环绕)。若没有此项,多镜头表演会像是在跳切变焦,因为 SeeDance 会从同一虚拟摄影机位置重新取景,而不是在空间中移动。
  • 在拼接到 <<<voice_1>>> 负载之前,先对对话文本应用 TTS 发音改写(Ari → Airy、API → A P I、example.com → example dot com 等)。请参阅步骤 [3] 中的“TTS 发音改写”。
  • 16:9,1080p(SeeDance resolution: "1080p")
  • 按照适合产品类型的方式展示用户提供的素材:
    • digital → 在镜头 C 和 E 中使用空白手机占位画面,然后在步骤 [5.5] 中合成真实 UI / 字标
    • physical_apparel → 创始人穿着或拿着实际 T 恤;在每个出现 T 恤的镜头中都传入素材作为参考(不只是在单个展示节拍中)
    • physical_object → 创始人举起产品展示;在所有产品可见的镜头中都传入素材
    • consumable → 创始人使用 / 吃 / 喝产品;采用相同方式
    • service → 不展示素材;只呈现环境和对话
  • 音乐:目标为约 60 秒的纯音乐——调用 generate_music,参数设为 provider: "kling-audio"、mode: "text_to_audio"、background: true 和 duration_seconds: 60。prompt 不超过 200 个字符,并包含 "soft instrumental background bed"、"no vocals" 和 "leave room for narration"。如果时长不足 55 秒,则重试一次,然后停止并提示用户,不要接受过短的配乐。
  • 使用 render_html_animation 制作 5 秒片尾卡——按照步骤 [9] 编写内嵌 HTML,并将品牌套件字体以内嵌 base64 形式加入。品牌来源为 state.brand(在步骤 [4.5] 中设置)→ 使用真实徽标、真实配色和真实字体。
  • 使用 add_captions 添加字幕。 默认使用服务端逐词字幕烧录。字体仅可从工具支持的集合中选择(inter、bebas-neue、noto-cjk);使用品牌强调色作为高亮 / 描边颜色,不要使用本地自定义字体 drawtext。
  • 下三分之一画面备选方案。 默认关闭。如果 state.lower_third = true,则通过 render_html_animation(format:"mov") 在左下角渲染一个时长为 5 秒的品牌胶囊条;将其最终叠加到主体视频上时使用 edit_video_compose,仅当 MCP 合成不可用时才执行一次本地 ffmpeg 处理。
  • 通过 MCP 完成最终组装。 使用 edit_concat 拼接主体视频和片尾卡,然后使用 edit_audio_mix 混入音乐。本地拼接 / 混音仅作为备选方案,并非标准流程。
  • Provider:仅限 seedance。参考标记为 @Image1 / @Image2 / @Image3。每个子镜头通过 <<<voice_1>>>...<<<voice_1>>> 标记实现原生口型同步。真人创始人照片绝大多数情况下都能通过内容过滤器;偶尔遇到 422 错误时,可通过加强风格化后重新生成。

评论

支持 Markdown