with one click
oss-video
为开源官网制作宣传视频,传入 {owner}/{repo} 参数
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
为开源官网制作宣传视频,传入 {owner}/{repo} 参数
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
| name | oss-video |
| description | 为开源官网制作宣传视频,传入 {owner}/{repo} 参数 |
制作宣传视频前,需要通过以下方式收集项目信息:
启动 Chrome Debug Protocol (CDP),用于后续浏览器自动化操作:
.agent/skills/oss-video/scripts/check-cdp.sh
使用统一脚本获取所有 GitHub 相关数据:
# 从项目根目录执行
.agent/skills/oss-video/scripts/fetch-github-stats.sh {owner}/{repo}
# 示例:获取 alibaba/higress 的信息
.agent/skills/oss-video/scripts/fetch-github-stats.sh alibaba/higress
脚本将数据保存至 src/data/github-stats.json,包含以下字段:
repoInfo)| 字段 | 用途 | 对应场景 |
|---|---|---|
name | 项目名称 | Scene1 标题 |
description | 项目描述/Slogan | Scene1 Slogan、Scene3 定位 |
htmlUrl | GitHub 仓库链接 | Scene5 CTA 按钮跳转 |
language | 主要编程语言 | Scene3 技术栈 |
topics | 项目标签/领域 | Scene3 定位描述 |
createdAt | 创建时间 | Scene1 "EST. 20XX" |
licenseName | 开源许可证 | 可选展示 |
ownerLogin | 组织/作者名 | Scene1 "Powered by XXX" |
ownerAvatarUrl | 组织头像 | 可选 Logo 素材 |
homepage | 项目官网 | 需进一步访问收集信息 |
defaultBranch | 默认分支 | 获取贡献者时需要 |
stats)| 字段 | 用途 | 对应场景 |
|---|---|---|
starsCount | Stars 数量 | Scene2 数据展示 |
forksCount | Forks 数量 | Scene2 数据展示 |
contributorsCount | 贡献者总数 | Scene4 统计 |
pullRequestsCount | PR 总数 | Scene4 统计 |
countriesCount | 贡献者国家数(估算) | Scene4 统计 |
contributors)返回前 24 个贡献者的详细信息:
login: 用户名id: 用户 IDavatar_url: 头像 URL(用于 Scene4 头像墙)contributions: 贡献次数注意:GitHub API 有速率限制(未认证 60次/小时,认证后 5000次/小时)。如遇限流,可设置 GITHUB_TOKEN 环境变量后重试。
如果 GitHub API 返回了 homepage 字段(项目官网 URL),需要进一步访问官网收集补充信息。
确保 CDP 已启动(步骤 1),然后使用 Browser Agent 访问官网。
使用脚本自动获取 Logo URL:
# 从项目根目录执行
.agent/skills/oss-video/scripts/logo-url.sh <homepage_url>
# 示例
.agent/skills/oss-video/scripts/logo-url.sh https://higress.ai
脚本查找优先级:
<link rel="apple-touch-icon"> - 高清图标(180x180+)<link rel="icon"> - favicon/logo.svg, /favicon.ico 等失败时的备选方案:
owner.avatar_url(GitHub 组织头像)使用 Browser Agent 访问官网后,通过以下方式提取品牌色:
输出格式:
主色调: #3B82F6 (blue-500)
辅助色: #8B5CF6 (purple-500)
使用 Browser Agent 浏览官网,收集以下信息:
| 信息类型 | 查找位置 | 用途 |
|---|---|---|
| 产品定位 | 首页 Hero 区域 | Scene3 理念描述 |
| 用户数据 | 首页/关于页 | Scene2 第三指标(企业用户/下载量) |
| 竞品对比 | 文档/对比页 | Scene3 差异化描述 |
| 社区数据 | 社区/贡献者页 | Scene4 国家数等 |
| 未来愿景 | Roadmap/博客 | Scene5 愿景文案 |
第三指标备选项(按优先级):
https://api.npmjs.org/downloads/point/last-week/{package} 获取在收集完数据后,需进行格式化和验证处理:
| 原始数据 | 转换规则 | 输出示例 |
|---|---|---|
createdAt: "2019-03-15T..." | 提取年份 | "EST. 2019" |
starsCount: 12345 | 千位分隔或简写 | "12,345" 或 "12K+" |
forksCount: 1234 | 千位分隔或简写 | "1,234" 或 "1.2K+" |
| 贡献者数量 > 100 | 显示为区间 | "500+" |
数字格式化规则:
< 1,000: 显示原数字1,000 - 9,999: 显示千位分隔(如 1,234)或 X.XK+10,000 - 999,999: 显示为 XXK+(如 12K+)>= 1,000,000: 显示为 X.XM+(如 1.2M+)| 情况 | 处理方式 |
|---|---|
repoInfo.homepage 为空 | 跳过官网信息采集,使用 GitHub 数据 |
| Logo URL 获取失败 | 使用 repoInfo.ownerAvatarUrl 或文字 Logo |
| 官网无法访问 | 记录错误,仅使用 GitHub 数据 |
| 第三指标无法获取 | 使用 stats.contributorsCount 作为替代 |
| 脚本执行失败 | 检查网络连接或设置 GITHUB_TOKEN 后重试 |
执行信息收集后,确保以下必需字段已获取:
Scene1 必需: repoInfo.name, repoInfo.description, repoInfo.createdAt, repoInfo.ownerLogin, logo_url
Scene2 必需: stats.starsCount, stats.forksCount, 第三指标
Scene3 必需: repoInfo.language, repoInfo.topics, 竞品对比描述
Scene4 必需: contributors (头像列表), stats.pullRequestsCount
Scene5 必需: repoInfo.htmlUrl, CTA 文案
□ 基础信息(Scene1)- 来自 github-stats.json
- [ ] 项目名称 (repoInfo.name)
- [ ] 项目描述/Slogan (repoInfo.description)
- [ ] 创建年份 (repoInfo.createdAt → "EST. 20XX")
- [ ] 所属组织 (repoInfo.ownerLogin)
- [ ] GitHub 仓库链接 (repoInfo.htmlUrl)
□ 数据指标(Scene2)- 来自 github-stats.json
- [ ] GitHub Stars (stats.starsCount)
- [ ] GitHub Forks (stats.forksCount)
- [ ] 第三指标(企业用户/下载量/安装量)
- [ ] 第三指标来源说明
□ 技术定位(Scene3)- 来自 github-stats.json + 官网
- [ ] 主要语言 (repoInfo.language)
- [ ] 技术标签 (repoInfo.topics)
- [ ] 与竞品的差异化描述
- [ ] 核心价值主张
□ 品牌素材 - 需从官网获取
- [ ] Logo URL(或备选方案:repoInfo.ownerAvatarUrl)
- [ ] 品牌主色调 HEX 值
- [ ] 辅助色调 HEX 值
- [ ] 官方 Slogan
□ 社区数据(Scene4)- 来自 github-stats.json
- [ ] 贡献者头像列表 (contributors,至少 20 个)
- [ ] 贡献者总数 (stats.contributorsCount)
- [ ] PR 数量 (stats.pullRequestsCount)
- [ ] 贡献者国家数 (stats.countriesCount)
□ 愿景内容(Scene5)- 需从官网获取
- [ ] CTA 主文案
- [ ] CTA 副文案
- [ ] 未来发展方向/Roadmap 摘要
注意:完成信息收集后,整体输出 Report 报告文档,确保所有数据完整后再进行下一步场景定制。
当前项目包含 5 个场景,构成一个完整的开源项目介绍视频叙事:
| 场景 | 文件 | 用途 | 核心要素 |
|---|---|---|---|
| Scene1 | Scene1Origin.tsx | 起源/品牌展示 | Logo、项目名称、Slogan、成立时间 |
| Scene2 | Scene2Growth.tsx | 数据增长展示 | Stars、Forks、全球安装量等统计 |
| Scene3 | Scene3Philosophy.tsx | 理念/定位阐述 | 与竞品对比、技术栈展示、核心价值 |
| Scene4 | Scene4Community.tsx | 社区展示 | 贡献者头像、国家数、PR 数量 |
| Scene5 | Scene5Future.tsx | 愿景/行动号召 | 未来方向、CTA 按钮 |
在定制场景之前,需要先修改入口文件:
// 修改 GitHub 仓库地址,用于获取 Stars、Forks、贡献者等数据
repo = "owner/repo" // 替换为目标项目的 GitHub 仓库
Composition 使用 Zod schema 定义参数,支持 Remotion Studio 可视化编辑:
export const CompositionSchema = z.object({
fontFamily: z.string().describe("Main font family"),
monoFontFamily: z.string().describe("Monospace font family"),
repo: z.string().optional().describe("GitHub repository"),
});
// 修改 Composition ID(用于渲染命令)
id="ProjectNamePromo" // 替换为项目名称
// 确保 schema 正确引用
schema={CompositionSchema}
需要修改的内容:
// 1. Logo 设计 - 根据项目品牌选择合适的方案
// 方案 A:远程 Logo URL(推荐,从官网获取 apple-touch-icon 或 logo)
<Img src="https://example.com/logo.png" alt="{repo} Logo" className="h-12 w-auto" />
// 方案 B:文字 Logo(双色,无法获取远程 Logo 时的备选)
<div className="... bg-white">
<span className="text-blue-600">Hi</span>
<span className="text-slate-900">gress</span>
</div>
// 方案 C:渐变背景 Logo(无法获取远程 Logo 时的备选)
<div className="... bg-gradient-to-br from-orange-500 to-amber-400 text-white">
<span>Hi</span>
</div>
// 方案 D:本地图片/SVG Logo(需要 import { staticFile } from "remotion")
<img src={staticFile("logo.svg")} className="w-16 h-16" />
// 方案 E:图标 + 文字组合
<div className="flex items-center gap-2">
<IconComponent className="w-8 h-8" />
<span>Name</span>
</div>
// 2. 标题文字
const titleText = "ProjectName"; // 改为你的项目名称
// 3. Slogan
<p>Your Project Slogan</p> // 改为你的项目 Slogan
// 4. 元信息
<span>EST. 2023</span> // 成立年份
<span>Powered by XXX</span> // 技术栈或版本历程
需要修改的内容:
// 1. 默认统计数据(当 API 获取失败时使用)
const starsCount = stats?.starsCount ?? 10000; // 默认 Stars
const forksCount = stats?.forksCount ?? 1000; // 默认 Forks
// 2. 第三个指标 - 可自定义为任意指标
globalInstalls = 100, // 默认值,传入 props
// 在 AnimatedCounter 中修改:
<AnimatedCounter
targetValue={globalInstalls}
label="Global Installs" // 改为: "企业用户"、"Downloads"、"Active Users" 等
suffix="万+" // 改为: "+"、"K"、"M" 等
/>
// 3. 描述文案
<p>从第一个 commit 到全球开发者信赖的基础设施</p>
// 4. 结语引言
<p>"从 <span>实验性工具</span> 到 <span>企业级平台</span>"</p>
需要修改的内容:
// 1. 左侧标题(渐变色)
<span className="bg-gradient-to-r from-blue-400 to-purple-400">不只是</span>
<span>工具箱</span> // 改为你的项目定位
// 2. 与竞品对比的文案
<p>LangChain 是锤子与钉子,</p>
<p>而 ProjectName 是<span>脚手架</span>。</p>
// 3. 技术定位(左侧边框装饰)
<p className="border-l-2 border-blue-500"> // 边框颜色需与品牌色一致
Backend as a Service + LLMOps
<br />
让 AI 应用开发从第一天就具备生产级能力
</p>
// 4. 工作流节点(右侧)- 每个节点需修改颜色、标签和描述
// Node 1
<div className="w-2 h-2 rounded-full bg-blue-500" /> // 节点颜色
<span className="text-blue-400">MODEL</span> // 标签颜色和文字
<p>GPT-4 / Claude / Llama</p> // 描述
// Node 2
<div className="w-2 h-2 rounded-full bg-purple-500" />
<span className="text-purple-400">ORCHESTRATION</span>
<p>Workflow & Agent</p>
// Node 3
<div className="w-2 h-2 rounded-full bg-emerald-500" />
<span className="text-emerald-400">DEPLOYMENT</span>
<p>API + WebApp</p>
// 5. 连接线颜色(需与对应节点颜色一致)
<path stroke="rgba(59,130,246,0.3)" /> // Node1→Node2 连线,蓝色
<path stroke="rgba(139,92,246,0.3)" /> // Node2→Node3 连线,紫色
// 6. 底部格言
<p>简单 · 克制 · 迭代迅速</p>
需要修改的内容:
// 1. 默认显示值(当 API 获取失败时使用,根据项目规模调整)
const contributorsDisplay = stats ? formatCountWithPlus(stats.contributorsCount) : "100+";
const countriesDisplay = stats ? `${stats.countriesCount}+` : "20+";
const pullRequestsDisplay = stats ? formatCountWithPlus(stats.pullRequestsCount) : "1,000+";
// 2. 描述文案
<p>来自全球的开发者共同书写开源的未来</p>
需要修改的内容:
// 1. 主标题
<span>Define your AI.</span> // 动作召唤语
<span className="bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400">
Modify the Future. // 愿景声明(渐变色需与品牌色一致)
</span>
// 2. 描述
<p>从 RAG 到 Agent,从 Workflow 到 Autonomous AI。</p>
<p>ProjectName 正在从工具进化为 <span>更大的愿景</span>。</p>
// 3. CTA 按钮
<div>Star on GitHub</div> // 主按钮(保持不变)
<div>Explore ProjectName</div> // 次按钮(改为项目名称)
当需要根据项目品牌色调整配色时,以下是所有需要修改的位置:
| 场景 | 位置 | 默认颜色 | 修改示例 |
|---|---|---|---|
| Scene1 | Logo 背景/文字 | text-blue-600 | text-orange-500 或 bg-gradient-to-br from-X to-Y |
| Scene3 | 标题渐变 | from-blue-400 to-purple-400 | from-orange-400 to-amber-400 |
| Scene3 | 边框装饰 | border-blue-500 | border-orange-500 |
| Scene3 | Node1 颜色 | bg-blue-500, text-blue-400 | bg-orange-500, text-orange-400 |
| Scene3 | 连接线颜色 | rgba(59,130,246,0.3) | rgba(249,115,22,0.3) |
| Scene5 | 标题渐变 | from-blue-400 via-purple-400 to-pink-400 | from-orange-400 via-amber-400 to-yellow-400 |
| 全局 | BackgroundOrbs | 蓝+紫预设 | 自定义 OrbConfig[] |
蓝色系: blue-400/500/600 rgba(59,130,246,X)
紫色系: purple-400/500 rgba(139,92,246,X)
橙色系: orange-400/500 rgba(249,115,22,X)
琥珀色: amber-400/500 rgba(245,158,11,X)
绿色系: emerald-400/500 rgba(16,185,129,X)
红色系: red-400/500 rgba(239,68,68,X)
| 组件 | 用途 | 关键 Props |
|---|---|---|
BackgroundOrbs | 背景模糊光球效果 | orbs: OrbConfig[] |
AnimatedCounter | 数字递增动画 | targetValue, startFrame, endFrame, suffix |
AvatarItem | 贡献者头像展示 | contributor, index, frame |
StatItem | 静态统计项 | value, label |
StatusWrapper | 加载/错误状态包装 | loading, error, loadingMessage |
orbPresetsimport { BackgroundOrbs, orbPresets } from "../components";
// 使用预设
<BackgroundOrbs orbs={orbPresets.default} /> // 双色(蓝+紫)
<BackgroundOrbs orbs={orbPresets.triColor} /> // 三色(蓝+紫+粉)- 用于开场和结尾
<BackgroundOrbs orbs={orbPresets.minimal} /> // 单色简约
位于 src/utils/animations.ts:
| 函数 | 作用 | 参数 |
|---|---|---|
fadeIn | 淡入 (0→1) | frame, startFrame, endFrame |
fadeOut | 淡出 (1→0) | frame, startFrame, endFrame |
slideIn | 滑入位移 | frame, startFrame, endFrame, distance |
scaleIn | 缩放进入 | frame, startFrame, endFrame, overshoot |
countUp | 数字递增 | frame, startFrame, endFrame, targetValue |
springIn | Spring 弹性动画 | frame, fps, options? |
createStaggerAnimation | 批量交错动画 | frame, count, options |
springPresetsimport { springPresets } from "../utils/animations";
springPresets.smooth // { damping: 200 } - 平滑无弹跳,适合细腻入场
springPresets.snappy // { damping: 20, stiffness: 200 } - 快速响应
springPresets.bouncy // { damping: 8 } - 活泼弹跳效果
springPresets.heavy // { damping: 15, stiffness: 80, mass: 2 } - 厚重感
import { fadeIn, slideIn, springIn, springPresets } from "../utils/animations";
import { useCurrentFrame, useVideoConfig, spring, interpolate } from "remotion";
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// 淡入动画:从 0 秒到 0.8 秒完成(使用 fps 计算帧数)
const opacity = fadeIn(frame, 0, 0.8 * fps);
// 滑入动画:从 20px 偏移滑入到原位
const translateY = slideIn(frame, 0, 0.8 * fps, 20);
// Spring 动画:自然弹性效果
const logoScale = spring({
frame,
fps,
config: springPresets.bouncy, // 活泼弹跳
});
// Spring + interpolate 组合:映射到位移
const titleSpring = spring({ frame, fps, delay: 10, config: springPresets.smooth });
const titleY = interpolate(titleSpring, [0, 1], [32, 0]);
// 应用到元素
<div style={{ opacity, transform: `translateY(${translateY}px)` }}>
Content
</div>
配色方案: 根据项目品牌色修改 Tailwind 类名(如 text-blue-500 → text-green-500)
数据源: 修改 useGitHubStats hook 中的 repo 参数以获取正确的 GitHub 数据
const { stats, contributors, loading, error } = useGitHubStats("owner/repo");
内容本地化: 根据目标受众调整中英文文案
时长调整: 使用 useVideoConfig() 获取 fps,以秒数乘以 fps 来控制动画时长
const { fps } = useVideoConfig();
// 0.8 秒淡入动画
const opacity = fadeIn(frame, 0, 0.8 * fps);
// 0.5 秒后开始,持续 1 秒的动画
const slide = slideIn(frame, 0.5 * fps, 1.5 * fps, 20);
自定义背景: 通过 orbPresets 或自定义 OrbConfig[] 调整背景效果
const customOrbs: OrbConfig[] = [
{
widthClass: "w-96",
heightClass: "h-96",
colorClass: "bg-green-600", // 自定义颜色
position: { top: "-10%", left: "-10%" },
blur: 100,
opacity: 0.4,
},
];
本项目遵循 Remotion 官方最佳实践,以下是关键要点:
动画时长应使用秒数乘以 fps,而非硬编码帧数:
// ✅ 推荐:使用 fps 计算
const { fps } = useVideoConfig();
const opacity = fadeIn(frame, 0, 0.8 * fps);
// ❌ 避免:硬编码帧数
const opacity = fadeIn(frame, 0, 24);
使用 @remotion/transitions 的 TransitionSeries 组件实现场景间的专业过渡效果:
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={90}>
<Scene1 />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
presentation={fade()}
timing={linearTiming({ durationInFrames: 15 })}
/>
<TransitionSeries.Sequence durationInFrames={120}>
<Scene2 />
</TransitionSeries.Sequence>
</TransitionSeries>
注意:TransitionSeries 会自动计算总时长(减去过渡重叠时间)。
对于 UI 入场动画,推荐使用 spring() 替代线性 interpolate:
import { spring } from "remotion";
// ✅ 推荐:使用 spring 获得自然动效
const logoScale = spring({
frame,
fps,
config: { damping: 15, stiffness: 100 }, // 轻微弹跳
});
// 或使用预设
import { springPresets } from "../utils/animations";
const scale = spring({
frame,
fps,
config: springPresets.smooth, // 平滑无弹跳
});
使用 Zod schema 让 Composition 支持 Remotion Studio 的可视化 props 编辑:
import { z } from "zod";
export const CompositionSchema = z.object({
fontFamily: z.string().describe("Main font family"),
repo: z.string().optional().describe("GitHub repository"),
});
export type CompositionProps = z.infer<typeof CompositionSchema>;
// 在 Root.tsx 中使用
<Composition
schema={CompositionSchema}
defaultProps={{ fontFamily: "...", repo: "owner/repo" }}
// ...
/>
Remotion 对 type 的类型推断更友好:
// ✅ 推荐
export type CompositionProps = z.infer<typeof CompositionSchema>;
// ❌ 避免
export interface CompositionProps { ... }
所有动画必须通过 useCurrentFrame() 驱动,不要使用:
transition-* 属性animation-* 属性animate-* 类名src/
├── scenes/
│ ├── Scene1Origin.tsx # 起源场景
│ ├── Scene2Growth.tsx # 增长场景
│ ├── Scene3Philosophy.tsx # 理念场景
│ ├── Scene4Community.tsx # 社区场景
│ └── Scene5Future.tsx # 未来场景
├── components/
│ ├── BackgroundOrbs.tsx # 背景光球
│ ├── AnimatedCounter.tsx # 动画计数器
│ ├── AvatarItem.tsx # 头像项
│ ├── StatItem.tsx # 统计项
│ ├── StatusOverlay.tsx # 状态覆盖层
│ └── index.ts # 组件导出
├── utils/
│ └── animations.ts # 动画工具函数
├── types/
│ └── scene.ts # 场景类型定义
└── hooks/
└── useGitHubStats.ts # GitHub 数据获取