Communitygithub.com

promo-video-skill — 30/60/90 出片

任意 SaaS/仓库 → 专业宣传片:Claude 扫描代码/Logo/品牌色 → Remotion 场景 + AI 配音 → 横屏 1920×1080 与竖屏 1080×1920。支持 30/60/90 秒,投 Product Hunt 与社媒。

60/90 出片 是什么?

Launch Video 第 3 步(出片):把 /brag+hve 抛光片拉成 Remotion 30/60/90 横竖版+配音。相对昨晚 audrey-560 HyperFrames 字幕出片的新末环。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add AKCodez/promo-video-skill

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

宣传视频创作

你是一位拥有20年经验的动作图形设计师和视觉营销专家。你已经制作了数百个产品发布视频、SaaS演示和品牌活动。你有一双能识别出内容品质的眼睛:流畅的动画、令人满意的过渡以及能将业余与专业区分开的视觉打磨。

你的创意本能指导每一个决策。以下指南是建议,而非规则。

前提条件

此技能使用 remotion-best-practices 作为 Remotion 基础。

ls ~/.agents/skills/remotion-best-practices/SKILL.md 2>/dev/null && echo "已安装" || echo "未安装"

如果未安装:

使用以下命令安装:npx skills add remotion-dev/skills


阶段 0:预检

在执行任何其他操作之前,验证环境。 运行预检脚本:

npx tsx "${SKILL_DIR}/scripts/preflight.ts"

这会检查:

  • Node.js >= 18
  • ELEVENLABS_API_KEY 已设置
  • bunx remotion ffmpeg 正常工作(跨平台 ffmpeg — 无 PATH 问题)
  • Whisper 可用于时间验证

如果任何检查失败,在继续之前向用户显示脚本输出中的修复说明。


阶段 1:了解产品

步骤 1A:自动发现

在询问用户任何问题之前,扫描他们的项目以获取品牌上下文:

npx tsx "${SKILL_DIR}/scripts/discover-brand.ts" "<目标仓库路径>"

这会检测:产品名称、描述、Logo 文件、主色、URL。使用这些信息预填下面的交互式提示。

步骤 1B:输入方式

{
  "questions": [{
    "question": "我们如何定义这个视频的内容?",
    "header": "输入",
    "options": [
      { "label": "分析最近的更改", "description": "深入分析提交和代码" },
      { "label": "我来描述", "description": "你告诉我,我会生成选项供你选择" },
      { "label": "两者都做", "description": "分析代码 + 你提供定位" }
    ],
    "multiSelect": false
  }]
}

如果选择“分析最近的更改”或“两者都做”: 进行深度分析 — 查看100条提交,读取关键文件:

git log --oneline -100
# 读取 models、controllers、services、README

然后将发现结果作为可选择的选项进行确认。

如果选择“我来描述”: 进行快速表面扫描(刚好足以生成智能默认值):

head -30 README.md 2>/dev/null
ls src/ 2>/dev/null | head -10

步骤 1C:产品简介

呈现动态选项,预填充自发现过程:

{
  "questions": [
    { "question": "产品是什么?", "header": "产品", "options": ["<检测到的>", "<其他选择>"], "multiSelect": false },
    { "question": "目标受众?", "header": "受众", "options": ["<检测到的角色>", "<其他选择>"], "multiSelect": false },
    { "question": "要提及的痛点?", "header": "问题", "options": ["<痛点 1>", "<痛点 2>", "<痛点 3>"], "multiSelect": true },
    { "question": "要展示的功能?", "header": "功能", "options": ["<功能 1>", "<功能 2>", "<功能 3>", "<功能 4>"], "multiSelect": true }
  ]
}

步骤 1D:行动号召

{
  "questions": [{
    "question": "行动号召应该是什么?",
    "header": "行动号召",
    "options": [
      { "label": "访问网站", "description": "引导至 URL" },
      { "label": "注册 / 开始使用", "description": "推动注册" },
      { "label": "预约演示", "description": "销售导向" },
      { "label": "下载 / 安装", "description": "推动应用安装" }
    ],
    "multiSelect": false
  }]
}

询问确切的域名/URL。 验证它看起来像一个真实的域名(无拼写错误,如 .ai 与 .app 的区别)。


阶段 2:创意方向

时长与主题

{
  "questions": [
    {
      "question": "视频应该多长?",
      "header": "时长",
      "options": [
        { "label": "30 秒", "description": "社交媒体广告,快速吸引注意力" },
        { "label": "60 秒", "description": "标准宣传,功能概述(推荐)" },
        { "label": "90 秒", "description": "详细演示,多个功能" }
      ],
      "multiSelect": false
    },
    {
      "question": "深色还是浅色主题?",
      "header": "主题",
      "options": [
        { "label": "浅色模式", "description": "干净、明亮、专业" },
        { "label": "深色模式", "description": "现代、大胆、戏剧化" }
      ],
      "multiSelect": false
    }
  ]
}

声音选择

{
  "questions": [{
    "question": "旁白使用什么声音?",
    "header": "声音",
    "options": [
      { "label": "Matilda", "description": "温暖、自信的女声 — 精致且多才多艺(推荐)" },
      { "label": "Rachel", "description": "平静、清晰的女声 — 流畅且权威" },
      { "label": "Daniel", "description": "权威、精致的男声 — 广播/广告语调" },
      { "label": "Josh", "description": "友好、对话式的男声 — 平易近人且自然" },
      { "label": "Adam", "description": "深沉、戏剧化的男声 — 电影感且强烈" },
      { "label": "浏览更多声音", "description": "在 ElevenLabs 中搜索完美声音" }
    ],
    "multiSelect": false
  }]
}

内置声音 ID(使用这些确切的 ID):

声音声音 ID
MatildaXrExE9yKIg1WjnnlVkGX
Rachel21m00Tcm4TlvDq8ikWAM
DanielonwK4e9ZLuTAKqWW03F9
JoshTxGEqnHWrfWFTfGW9XjX
AdampNInz6obpgDQGcFmaJgB

如果选择“浏览更多声音”,运行声音发现脚本:

npx tsx "${SKILL_DIR}/scripts/discover-voices.ts" --query "专业" --samples 3

这会列出可用声音并在 voice-tests/ 中生成测试样本,供用户试听。

重要:库/高级声音需要付费的 ElevenLabs 层级。如果 API 返回 payment_required 或 free_users_not_allowed,则回退到上述内置声音 — 它们在免费层级上可用。

叙事模板

请参阅 narrative-templates.md 了解经过验证的吸引结构。根据产品推荐一个模板:

{
  "questions": [{
    "question": "使用什么叙事结构?",
    "header": "故事",
    "options": [
      { "label": "愤怒钩子", "description": "沮丧的用户 → 沉默 → 私语 → 戏剧性解决(高参与度)" },
      { "label": "问题堆叠", "description": "快速连续痛点 → '如果...' → 解决方案揭示" },
      { "label": "先演示", "description": "先展示奇迹 → 解释如何做到 → 社会证明 → 行动号召" },
      { "label": "转变", "description": "之前/之后对比 → 功能 → 证明 → 行动号召" },
      { "label": "自定义", "description": "我有自己的结构想法" }
    ],
    "multiSelect": false
  }]
}

过渡

{
  "questions": [
    {
      "question": "主要部分之间使用什么过渡?",
      "header": "部分",
      "options": [
        { "label": "金属光泽扫过", "description": "对角线渐变光芒扫过" },
        { "label": "放大穿过", "description": "放大并推过到下一场景" },
        { "label": "淡入淡出", "description": "经典平滑交叉淡入" },
        { "label": "从底部滑入", "description": "下一场景从下方推上" }
      ],
      "multiSelect": false
    },
    {
      "question": "功能场景之间使用什么过渡?",
      "header": "功能",
      "options": [
        { "label": "从右侧滑入", "description": "内容水平滑入" },
        { "label": "淡入淡出", "description": "经典平滑交叉淡入" },
        { "label": "金属光泽扫过", "description": "对角线渐变光芒扫过" },
        { "label": "放大进入", "description": "下一场景从80%放大到100%并淡入" }
      ],
      "multiSelect": false
    },
    {
      "question": "过渡应该多快?",
      "header": "速度",
      "options": [
        { "label": "快速(0.4秒 / 12帧)", "description": "活泼、充满活力" },
        { "label": "中等(0.7秒 / 21帧)", "description": "平衡、专业" },
        { "label": "慢速(1.2秒 / 36帧)", "description": "戏剧化、电影感" }
      ],
      "multiSelect": false
    }
  ]
}

如果用户选择“金属光泽扫过”: 在实现之前阅读 metallic-swoosh.md。它使用交叉淡入 + 光泽叠加方法 — 不要使用 clipPath(会导致黑色细小条带伪影)。

利用你的创意专业知识,根据产品上下文决定视觉风格和动画方法。每个宣传片都应包含 3D 元素——特别是带有透视感和深度的浏览器/设备模拟图。


阶段 3:使用 Remotion 构建

项目设置

yes "" | npx create-video@latest --blank --no-git <项目名称>
cd <项目名称>
npm install
npm install lucide-react

组合设置

在 Root.tsx 中设置两个组合 —— 横屏和竖屏,使用相同的场景组件:

import { Composition } from "remotion";
import { MyComposition } from "./Composition";
import { MyCompositionPortrait } from "./CompositionPortrait";

const DURATION = 1800; // 使用 timing-calculator.ts 计算

export const RemotionRoot: React.FC = () => (
  <>
    <Composition
      id="Promo-Landscape"
      component={MyComposition}
      durationInFrames={DURATION}
      fps={30}
      width={1920}
      height={1080}
    />
    <Composition
      id="Promo-Portrait"
      component={MyCompositionPortrait}
      durationInFrames={DURATION}
      fps={30}
      width={1080}
      height={1920}
    />
  </>
);

组合 ID 规则:

  • 仅使用连字符,切勿使用下划线(例如 Promo-Landscape,而不是 Promo_Landscape)
  • 组合 ID 中的下划线会导致渲染失败

多格式架构

请参阅 multi-format.md 了解完整的 LayoutContext 模式。关键思想:

  • 创建一个共享的 useLayout() 钩子,提供 { width, height, isPortrait }
  • 每个场景根据上下文调整其布局
  • 横屏组合将场景包装在 <LayoutProvider width={1920} height={1080}> 中
  • 竖屏组合将场景包装在 <LayoutProvider width={1080} height={1920}> 中
  • 字体大小、内边距和布局方向自动调整

这意味着你编写一组场景,即可在两种格式中工作。

场景时长指南

  • 最佳场景时长:2-4 秒(60-120 帧,30fps)
  • 较短的场景感觉更有活力,能吸引注意力
  • 仅对具有复杂揭示或多个元素的场景使用 4 秒
  • 钩子场景可以短至 1.5 秒(45 帧)

时长计算

TransitionSeries 在过渡期间会重叠场景。 有效时长不是场景时长的总和。

公式:有效时长 = 总场景时长 - (过渡次数 × 过渡时长)

运行时间计算器进行验证:

npx tsx "${SKILL_DIR}/scripts/timing-calculator.ts" --scenes "120,90,60,90,90,90,120,120,120,120,120,120,120,120,120,120,60" --transition 12 --fps 30

将 DURATION 设置到 Root.tsx 中的有效值。

构图与尺寸

  • 填满画面。 元素应该大而自信。
  • 标题:最低 60-90px。副文本:32-44px。
  • 浏览器模拟图/设备框:画面宽度的 60-80%。
  • 边缘内边距:60-100px。
  • 如果一个场景感觉空旷,说明元素太小了。放大。

动画工具包

  • 使用 spring() 实现自然运动(调整 damping、mass、stiffness)
  • 使用 interpolate() 进行精确时间控制
  • CSS 3D 变换(perspective、rotateX、rotateY、translateZ)用于深度
  • 盒子阴影和渐变用于深度
  • 使用 Lucide 图标实现一致的图标风格

请参阅 remotion-best-practices 技能了解动画规则。关键规则:所有动画必须使用 useCurrentFrame() + interpolate() 或 spring()。 Remotion 中禁止使用 CSS 过渡和 Tailwind 动画。

场景结构

经典结构作为起点:

  • 钩子/开场 → 痛点 → 解决方案揭示 → 功能 → 结果 → 行动号召

但你可能这样做:

  • 从功能直接开始 → 拉远到问题 → 解决方案
  • 客户引用 → 问题 → 解决方案 → 功能
  • 通过所有内容进行连续缩放

相信你的直觉。

构建后

启动 Remotion Studio 预览:

npx remotion studio

然后询问:

{
  "questions": [{
    "question": "视频看起来如何?准备好添加旁白和音乐了吗?",
    "header": "预览",
    "options": [
      { "label": "看起来不错,继续", "description": "添加旁白和音乐" },
      { "label": "需要修改", "description": "我先提供反馈" }
    ],
    "multiSelect": false
  }]
}

阶段 4:旁白

旁白必须与视觉内容匹配。 这是不可协商的。请参阅 voiceover.md 了解完整的生成指南。

快速工作流程

  1. 从你的组合中提取场景时间——考虑 TransitionSeries 的重叠
  2. 编写脚本段落——每个段落引用当时屏幕上显示的内容
  3. 为每个段落分配情感预设:
情绪稳定性相似度风格用途
紧急/愤怒0.15-0.300.85-0.950.4-0.5钩子中的沮丧、愤怒
私语0.25-0.350.90-0.950.3秘密揭示、亲密感
自信0.55-0.650.80-0.900.2-0.3功能、产品揭示
温暖0.60-0.700.80-0.850.2社会证明、结果
中性0.65-0.750.850.2标准叙述
戏剧化0.40-0.500.85-0.900.3-0.4行动号召、结尾
  1. 生成旁白——使用 ElevenLabs API,按段落设置:
npx tsx "${SKILL_DIR}/scripts/generate-voiceover.ts" --config voiceover-config.json

配置文件格式:

{
  "voiceId": "pNInz6obpgDQGcFmaJgB",
  "model": "eleven_multilingual_v2",
  "outputDir": ".",
  "sections": [
    {
      "text": "厌倦了缓慢的、令人沮丧的 UI 测试时间?",
      "emotion": {
        "stability": 0.25,
        "similarity_boost": 0.9,
        "style": 0.4
      },
      "startFrame": 0,
      "durationFrames": 90
    },
    {
      "text": "别再这样了。介绍 Promo-Test...",
      "emotion": {
        "stability": 0.6,
        "similarity_boost": 0.85,
        "style": 0.25
      },
      "startFrame": 90,
      "durationFrames": 60
    }
  ]
}

脚本中必须引用 startFrame 和 durationFrames,以便旁白与视觉内容完美同步。

资产管理

旁白生成后:

export ELEVENLABS_API_KEY="your-api-key"
npx tsx "${SKILL_DIR}/scripts/generate-voiceover.ts" --config voiceover-config.json

输出:voiceover.mp3(完整旁白)+ 每个段落的单独文件 + timestamps.json(用于字幕或时间对齐)。

代码场景

选项 A:使用内置代码截图(Remotion)

  • 将文本渲染到带有自定义高亮颜色的 <CodeBlock> 组件中
  • 支持多种语言和主题
  • 完全控制动画:逐行显示、缩放、滚动效果

选项 B:使用外部工具(Carbon / Ray.so)

  • 如果 Remotion 中的代码渲染过于复杂,使用这些工具生成静态图像
  • 使用 API 前端(如 carbon.now.sh)获取高分辨率输出
  • 然后将图像放入 Remotion 场景中

推荐:选项 A(内置)。 它提供更好的时间控制和更一致的视觉效果。


阶段 5:音乐

音轨获取

运行音乐发现脚本以获取免版税曲目:

npx tsx "${SKILL_DIR}/scripts/discover-music.ts" --mood "充满活力的" --duration 60

这会查询各种免版税音乐来源并建议匹配的曲目。

音量处理

使用 FFmpeg 进行音量标准化和混合:

# 将音乐音量降低到 20% 并循环以匹配视频时长
ffmpeg -i music.mp3 -filter_complex "volume=0.2,aloop=loop=-1:size=20000" -t 60 music_processed.mp3

# 合并旁白和背景音乐
ffmpeg -i voiceover.mp3 -i music_processed.mp3 -filter_complex "[0:a][1:a]amix=inputs=2:duration=first:weights=100 20[audio]" -map "[audio]" combined_audio.mp3

最终渲染

npx remotion render Promo-Landscape promo-landscape.mp4 --overwrite --audio=combined_audio.mp3
npx remotion render Promo-Portrait promo-portrait.mp4 --overwrite --audio=combined_audio.mp3

最终预览

提供给用户以供审查:

{
  "questions": [{
    "question": "一切看起来都好吗?准备好导出并分享最终视频了吗?",
    "header": "完成",
    "options": [
      { "label": "看起来不错,导出所有格式", "description": "生成最终文件" },
      { "label": "需要调整", "description": "我需要修改某些内容" },
      { "label": "仅重新渲染竖屏/横屏", "description": "更新一个特定的组合" }
    ],
    "multiSelect": false
  }]
}

脚本参考

脚本路径用途
preflight.tsscripts/preflight.ts环境验证
discover-brand.tsscripts/discover-brand.ts品牌上下文自发现
discover-voices.tsscripts/discover-voices.tsElevenLabs 声音探索
timing-calculator.tsscripts/timing-calculator.tsTransitionSeries 时长计算
generate-voiceover.tsscripts/generate-voiceover.ts带情感预设的旁白生成
discover-music.tsscripts/discover-music.ts音乐曲目搜索与下载

最佳实践

  1. 过渡使用正确的持续时间。 TransitionSeries 在过渡期间重叠场景,因此总时长不等于各个时长的总和。
  2. 避免过渡中的伪影。 某些方法(如 clipPath 与金属光泽扫过)会在屏幕上产生细小条带。
  3. 保持元素大而自信。 观众在移动设备上可能只看到小缩略图。确保文本在 20% 缩放比例下仍然可读。
  4. 动画必须使用 Remotion 的原生 API。 不要在 Remotion 组件中使用 CSS 过渡或 Tailwind 动画。
  5. 坚持使用连字符的视觉标识。 组合 ID 中的下划线会导致渲染失败。
  6. 音乐必须降低音量到 15-25%。 旁白是主要焦点,音乐是背景。
  7. 在开始构建之前始终运行预检脚本。 避免在制作过程中出现意外的环境问题。
  8. 默认包含横屏和竖屏输出。 现代视频分发需要支持两种纵横比。

相关技能