Skip to main content

从数据集以编程方式渲染视频

你可以使用 Remotion 批量渲染来根据数据集创建许多视频。在下面的示例中,我们将把一个 JSON 数据集转换成一系列视频。

🌐 You can use Remotion to do a batch render to create many videos based on a dataset. In the following example, we are going to turn a JSON dataset into a series of videos.

我们将从创建一个空的 Remotion 项目开始:

🌐 We'll start by creating a blank Remotion project:

npm init video --blank

示例数据集

🌐 Sample dataset

JSON 是在 Remotion 中导入最方便的格式。如果你的数据集是其他格式,你可以使用 NPM 上的众多可用库之一进行转换。

🌐 JSON is the most convenient format to import in Remotion. If your dataset is in a different format, you can convert it using one of many available libraries on NPM.

my-data.ts
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', }, ];

示例组件

🌐 Sample component

这个组件将使用 Remotion 对标题、副标题和图片进行动画处理。将 src/Composition.tsx 文件的内容替换为以下内容:

🌐 This component will animate a title, subtitle and image using Remotion. Replace the contents of the src/Composition.tsx file with the following:

Composition.tsx
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 ( <AbsoluteFill style={{ scale: String(scale), backgroundColor: 'white', fontWeight: 'bold', justifyContent: 'center', alignItems: 'center', }} > <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 20, }} > <Img src={logo} style={{ height: 80, }} /> <div style={{ display: 'flex', flexDirection: 'column', }} > <div style={{ fontSize: 40, transform: `translateY(${moveY}px)`, lineHeight: 1, }} > {name} </div> <div style={{ fontSize: 20, opacity, lineHeight: 1.25, }} > {repo} </div> </div> </div> </AbsoluteFill> ); };

写脚本

🌐 Writing the script

为了渲染我们的视频,我们首先需要使用 Webpack 打包我们的项目并为渲染做好准备。可以使用 @remotion/bundler 包中的 bundle() 函数来完成此操作。如果你有 webpack 覆盖配置,请确保在打包中包含它。

🌐 In order to render our videos, we'll first need to bundle our project using Webpack and prepare it for rendering. This can be done by using the bundle() function from the @remotion/bundler package. Make sure to include the webpack override in the bundle if you have one.

import {bundle} from '@remotion/bundler';
import {webpackOverride} from './webpack-override';

const bundleLocation = await bundle({
  entryPoint: './src/index.ts',
  // If you have a webpack override, don't forget to add it
  webpackOverride: webpackOverride,
});

渲染视频

🌐 Rendering videos

导入数据集并遍历每个条目。

🌐 Import the dataset and loop over each entry.

使用 selectComposition() 获取每个渲染的合成元数据。你可以基于数据条目使用 calculateMetadata() 函数来参数化合成的持续时间、宽度和高度。

🌐 Fetch the composition metadata for each render using selectComposition(). You have the opportunity to parametrize the duration, width and height of the composition based on the data entry with the calculateMetadata() function.

使用renderMedia()触发渲染,并将数据条目作为inputProps传递。这将把对象作为React props传递给上面的组件。

🌐 Trigger a render using renderMedia() and pass the data entry as inputProps. This will pass the object as React props to the component above.

import {renderMedia, selectComposition} from '@remotion/renderer';
import {data} from './dataset';

for (const entry of data) {
  const composition = await selectComposition({
    serveUrl: bundleLocation,
    id: compositionId,
    inputProps: entry,
  });

  await renderMedia({
    composition,
    serveUrl: bundleLocation,
    codec: 'h264',
    outputLocation: `out/${entry.name}.mp4`,
    inputProps: entry,
  });
}
note

不建议同时渲染多个视频,因为每次渲染都已经尽量使用你的电脑所能提供的资源。

完整脚本

🌐 Full script

render.mjs
import {selectComposition, renderMedia} from '@remotion/renderer'; import {webpackOverride} from './webpack-override'; import {bundle} from '@remotion/bundler'; import {data} from './dataset'; const compositionId = 'MyComp'; const bundleLocation = await bundle({ entryPoint: './src/index.ts', // If you have a webpack override in remotion.config.ts, pass it here as well. webpackOverride: webpackOverride, }); for (const entry of data) { const composition = await selectComposition({ serveUrl: bundleLocation, id: compositionId, inputProps: entry, }); await renderMedia({ composition, serveUrl: bundleLocation, codec: 'h264', outputLocation: `out/${entry.name}.mp4`, inputProps: entry, }); }

运行脚本

🌐 Running the script

node render.mjs

要使用 TypeScript,请将文件重命名为 render.ts,从 npm 安装 ts-node 并运行 ts-node render.ts。如果出现错误,请将异步代码封装在一个异步函数中并调用它。

🌐 To use TypeScript, rename the file to render.ts, install ts-node from npm and run ts-node render.ts. If you get errors, wrap the asynchronous code in an async function and call it.

从 CSV 数据集渲染视频

🌐 Rendering videos from a CSV dataset

使用像 csv2json 这样的包将你的数据集转换为 JSON。

🌐 Use a package like csv2json to convert your dataset into a JSON.

另请参阅

🌐 See also