从数据集中以编程方式渲染视频
您可以使用 Remotion 进行批量渲染,根据数据集创建许多视频。在以下示例中,我们将把一个 JSON 数据集转换为一系列视频。
我们将从创建一个空白的 Remotion 项目开始:
- npm
- pnpm
- bun
- yarn
bash
npm init video --blank
bash
npm init video --blank
bash
pnpm create video --blank
bash
pnpm create video --blank
bash
bun create video --blank
bash
bun create video --blank
bash
yarn create video --blank
bash
yarn create video --blank
示例数据集
JSON 是在 Remotion 中导入的最方便的格式。如果您的数据集是以不同格式存在的,您可以使用 NPM 上的许多可用库之一进行转换。
my-data.tsts
export const data = [{name: "React",repo: "facebook/react",logo: "https://upload.wikimedia.org/wikipedia/commons/a/a7/React-icon.svg",},{name: "Remotion",repo: "remotion-dev/remotion",logo: "https://github.com/remotion-dev/logo/raw/main/withouttitle/element-0.png",},];
my-data.tsts
export const data = [{name: "React",repo: "facebook/react",logo: "https://upload.wikimedia.org/wikipedia/commons/a/a7/React-icon.svg",},{name: "Remotion",repo: "remotion-dev/remotion",logo: "https://github.com/remotion-dev/logo/raw/main/withouttitle/element-0.png",},];
示例组件
此组件将使用 Remotion 动画化标题、副标题和图像。将 src/Composition.tsx
文件的内容替换为以下内容:
Composition.tsxtsx
import React from "react";import {AbsoluteFill,Img,interpolate,spring,useCurrentFrame,useVideoConfig,} from "remotion";type Props = {name: string;logo: string;repo: string;};export const MyComposition: React.FC<Props> = ({ name, repo, logo }) => {const frame = useCurrentFrame();const { fps } = useVideoConfig();const scale = spring({fps,frame: frame - 10,config: {damping: 100,},});const opacity = interpolate(frame, [30, 40], [0, 1], {extrapolateLeft: "clamp",extrapolateRight: "clamp",});const moveY = interpolate(frame, [20, 30], [10, 0], {extrapolateLeft: "clamp",extrapolateRight: "clamp",});return (<AbsoluteFillstyle={{scale: String(scale),backgroundColor: "white",fontWeight: "bold",justifyContent: "center",alignItems: "center",}}><divstyle={{display: "flex",flexDirection: "row",alignItems: "center",gap: 20,}}><Imgsrc={logo}style={{height: 80,}}/><divstyle={{display: "flex",flexDirection: "column",}}><divstyle={{fontSize: 40,transform: `translateY(${moveY}px)`,lineHeight: 1,}}>{name}</div><divstyle={{fontSize: 20,opacity,lineHeight: 1.25,}}>{repo}</div></div></div></AbsoluteFill>);};
Composition.tsxtsx
import React from "react";import {AbsoluteFill,Img,interpolate,spring,useCurrentFrame,useVideoConfig,} from "remotion";type Props = {name: string;logo: string;repo: string;};export const MyComposition: React.FC<Props> = ({ name, repo, logo }) => {const frame = useCurrentFrame();const { fps } = useVideoConfig();const scale = spring({fps,frame: frame - 10,config: {damping: 100,},});const opacity = interpolate(frame, [30, 40], [0, 1], {extrapolateLeft: "clamp",extrapolateRight: "clamp",});const moveY = interpolate(frame, [20, 30], [10, 0], {extrapolateLeft: "clamp",extrapolateRight: "clamp",});return (<AbsoluteFillstyle={{scale: String(scale),backgroundColor: "white",fontWeight: "bold",justifyContent: "center",alignItems: "center",}}><divstyle={{display: "flex",flexDirection: "row",alignItems: "center",gap: 20,}}><Imgsrc={logo}style={{height: 80,}}/><divstyle={{display: "flex",flexDirection: "column",}}><divstyle={{fontSize: 40,transform: `translateY(${moveY}px)`,lineHeight: 1,}}>{name}</div><divstyle={{fontSize: 20,opacity,lineHeight: 1.25,}}>{repo}</div></div></div></AbsoluteFill>);};
编写脚本
为了渲染我们的视频,我们首先需要使用 Webpack 打包我们的项目并准备好进行渲染。
这可以通过使用 @remotion/bundler
包中的 bundle()
函数来完成。如果有 webpack 覆盖,请确保在捆绑时包含 webpack 覆盖。
ts
import {bundle } from "@remotion/bundler";import {webpackOverride } from "./webpack-override";constbundleLocation = awaitbundle ({entryPoint : "./src/index.ts",// If you have a webpack override, don't forget to add itwebpackOverride :webpackOverride ,});
ts
import {bundle } from "@remotion/bundler";import {webpackOverride } from "./webpack-override";constbundleLocation = awaitbundle ({entryPoint : "./src/index.ts",// If you have a webpack override, don't forget to add itwebpackOverride :webpackOverride ,});
渲染视频
导入数据集并循环遍历每个条目。
使用 selectComposition()
获取每个渲染的组合元数据。您可以使用 calculateMetadata()
函数基于数据条目参数化组合的持续时间、宽度和高度。
触发使用 renderMedia()
并将数据条目作为 inputProps
传递。这将将对象作为 React props 传递给上面的组件。
ts
import {renderMedia ,selectComposition } from "@remotion/renderer";import {data } from "./dataset";for (constentry ofdata ) {constcomposition = awaitselectComposition ({serveUrl :bundleLocation ,id :compositionId ,inputProps :entry ,});awaitrenderMedia ({composition ,serveUrl :bundleLocation ,codec : "h264",outputLocation : `out/${entry .name }.mp4`,inputProps :entry ,});}
ts
import {renderMedia ,selectComposition } from "@remotion/renderer";import {data } from "./dataset";for (constentry ofdata ) {constcomposition = awaitselectComposition ({serveUrl :bundleLocation ,id :compositionId ,inputProps :entry ,});awaitrenderMedia ({composition ,serveUrl :bundleLocation ,codec : "h264",outputLocation : `out/${entry .name }.mp4`,inputProps :entry ,});}
note
不建议同时渲染多个视频。
完整脚本
render.mjsts
import {selectComposition ,renderMedia } from "@remotion/renderer";import {webpackOverride } from "./webpack-override";import {bundle } from "@remotion/bundler";import {data } from "./dataset";constcompositionId = "MyComp";constbundleLocation = awaitbundle ({entryPoint : "./src/index.ts",// If you have a webpack override in remotion.config.ts, pass it here as well.webpackOverride :webpackOverride ,});for (constentry ofdata ) {constcomposition = awaitselectComposition ({serveUrl :bundleLocation ,id :compositionId ,inputProps :entry ,});awaitrenderMedia ({composition ,serveUrl :bundleLocation ,codec : "h264",outputLocation : `out/${entry .name }.mp4`,inputProps :entry ,});}
render.mjsts
import {selectComposition ,renderMedia } from "@remotion/renderer";import {webpackOverride } from "./webpack-override";import {bundle } from "@remotion/bundler";import {data } from "./dataset";constcompositionId = "MyComp";constbundleLocation = awaitbundle ({entryPoint : "./src/index.ts",// If you have a webpack override in remotion.config.ts, pass it here as well.webpackOverride :webpackOverride ,});for (constentry ofdata ) {constcomposition = awaitselectComposition ({serveUrl :bundleLocation ,id :compositionId ,inputProps :entry ,});awaitrenderMedia ({composition ,serveUrl :bundleLocation ,codec : "h264",outputLocation : `out/${entry .name }.mp4`,inputProps :entry ,});}
运行脚本
- Node
- Bun
bash
node render.mjs
bash
node render.mjs
要使用 TypeScript,请将文件重命名为 render.ts
,从 npm 安装 ts-node
并运行 ts-node render.ts
。如果出现错误,请将异步代码包装在异步函数中并调用它。
bash
bun render.mjs
bash
bun render.mjs
如果将文件重命名为 render.ts
,TypeScript 应该可以直接使用。
从 CSV 数据集渲染视频
使用类似 csv2json
的软件包将数据集转换为 JSON。