mcpField
P
programmatic-video

programmatic-video

github.com/itallstartedwithaidea创意与媒体4477 次安装28 周前更新
代码仓库

关于 programmatic-video

面向需要以代码生成视频的开发者,使用 React 和 Remotion 构建视频场景、动画及数据驱动内容。视频可版本管理、参数化批量渲染,并由无头 Chromium 输出 MP4 或 WebM。

主要功能

  1. 01使用 React 组件构建视频场景
  2. 02编排序列、转场与动画
  3. 03按输入数据生成内容
  4. 04无头 Chromium 渲染 MP4/WebM
  5. 05参数化批量渲染

适用场景

  1. 01生成个性化视频
  2. 02制作产品演示或社交媒体短片
  3. 03自动化 CI/CD 视频制作
  4. 04为多个品牌版本复用模板

安装

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

$npx skills add https://github.com/itallstartedwithaidea/agent-skills --skill programmatic-video

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

详细介绍

程序化视频

属于 Agent Skills™,由 googleadsagent.ai™ 提供

描述

程序化视频使用 Remotion 实现基于 React 的视频渲染,每一帧都是一个 React 组件,每个动画都通过代码实现。Agent 使用序列、转场、弹簧动画和数据驱动内容构建视频合成,并在无头 Chromium 中渲染为 MP4/WebM,无需任何视频编辑软件。

传统视频编辑依赖手动操作,无法复现,也无法制作模板。程序化视频将视频视为代码:合成内容在 git 中进行版本控制,可参数化以进行批量渲染,并通过快照断言进行测试。只需更改输入数据,一个模板就能生成数千个个性化视频,例如产品演示、社交媒体短片、引导序列或营销视频,每个视频都可针对接收者进行定制。

Remotion 的架构将 React 的组件模型映射到视频:每个组件都会接收一个 frame 编号和总时长 durationInFrames,并据此计算动画、转场和时间安排。Agent 使用可复用组件组合场景,通过 <Sequence> 包装器编排场景的时间安排,并应用基于弹簧的物理动画,呈现自然的运动效果。

适用场景

  • 无需视频编辑软件,通过代码创建视频
  • 大规模生成个性化或数据驱动的视频内容
  • 制作动画解说视频、产品演示或社交媒体短片
  • 在 CI/CD 流水线中自动化视频制作
  • 用户提出“程序化视频”“Remotion”或“通过代码制作视频”需求时
  • 制作数百种变体,同时保持品牌风格一致的视频素材

工作原理

graph TD
    A[Video Specification] --> B[Define Composition: FPS + Duration]
    B --> C[Build Scene Components]
    C --> D[Arrange with Sequences]
    D --> E[Add Spring Animations]
    E --> F[Inject Dynamic Data]
    F --> G[Preview in Browser]
    G --> H{Approved?}
    H -->|No| C
    H -->|Yes| I[Render: Headless Chromium]
    I --> J[Encode: MP4 / WebM]
    J --> K[Output Video File]

每个场景都是一个 React 组件,会接收当前帧编号。合成内容定义画布尺寸、帧率和总时长。序列会将场景放置在特定的时间偏移处。渲染时会将每一帧捕获为屏幕截图,再编码为视频。

实现

import { AbsoluteFill, Composition, Sequence, useCurrentFrame, useVideoConfig,
  interpolate, spring } from "remotion";

const TextReveal: React.FC<{ text: string }> = ({ text }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: "clamp" });
  const translateY = spring({ frame, fps, config: { damping: 12, stiffness: 200 } });
  const y = interpolate(translateY, [0, 1], [40, 0]);

  return (
    <AbsoluteFill style={{ justifyContent: "center", alignItems: "center" }}>
      <h1 style={{
        fontSize: 72,
        fontWeight: "bold",
        color: "white",
        opacity,
        transform: `translateY(${y}px)`,
      }}>
        {text}
      </h1>
    </AbsoluteFill>
  );
};

const DataDrivenSlide: React.FC<{ metric: string; value: number }> = ({ metric, value }) => {
  const frame = useCurrentFrame();
  const displayValue = Math.round(interpolate(frame, [0, 45], [0, value], { extrapolateRight: "clamp" }));

  return (
    <AbsoluteFill style={{ justifyContent: "center", alignItems: "center", background: "#0a0a0a" }}>
      <div style={{ textAlign: "center" }}>
        <div style={{ fontSize: 120, fontWeight: "bold", color: "#3b82f6" }}>
          {displayValue.toLocaleString()}
        </div>
        <div style={{ fontSize: 32, color: "#a1a1aa", marginTop: 16 }}>{metric}</div>
      </div>
    </AbsoluteFill>
  );
};

export const MainComposition: React.FC<{ title: string; metrics: Array<{ name: string; value: number }> }> = ({
  title, metrics
}) => {
  return (
    <AbsoluteFill style={{ background: "#0a0a0a" }}>
      <Sequence durationInFrames={60}>
        <TextReveal text={title} />
      </Sequence>
      {metrics.map((m, i) => (
        <Sequence key={m.name} from={60 + i * 75} durationInFrames={75}>
          <DataDrivenSlide metric={m.name} value={m.value} />
        </Sequence>
      ))}
    </AbsoluteFill>
  );
};

export const RemotionRoot: React.FC = () => (
  <Composition
    id="MainVideo"
    component={MainComposition}
    durationInFrames={300}
    fps={30}
    width={1920}
    height={1080}
    defaultProps={{
      title: "Q1 Performance",
      metrics: [
        { name: "Page Views", value: 18247 },
        { name: "Conversions", value: 1432 },
        { name: "Revenue", value: 89500 },
      ],
    }}
  />
);
# Preview in browser
npx remotion studio

# Render to MP4
npx remotion render MainVideo output.mp4

# Batch render with different data
npx remotion render MainVideo --props='{"title":"Q2","metrics":[...]}'

最佳实践

  • 使用 spring() 实现自然流畅的动画,而不是线性插值
  • 对所有 interpolate() 调用进行钳制,防止数值超出范围
  • 标准内容使用 30fps,流畅动态内容使用 60fps
  • 在渲染前预加载所有素材(图片、字体),避免出现缺帧
  • 使用 <Sequence> 按明确的时间安排组织场景,而不是使用基于帧的条件判断
  • 在多种分辨率(1080p、720p、正方形)下测试视频输出,确保兼容各平台

平台兼容性

平台支持情况备注
Cursor完全支持React + Remotion 开发
VS Code完全支持可使用 Remotion 扩展
Windsurf完全支持基于 React 的开发
Claude Code完全支持组件 + 配置生成
Cline完全支持视频流水线设置
aider部分支持仅代码生成

相关技能

关键词

programmatic-video remotion react-video animation data-driven-video batch-rendering composition spring-animation


© 2026 googleadsagent.ai™ | Agent Skills™ | MIT License

评论

支持 Markdown