ReactとRemotionで動画を作ってみた!
¡Hola! こんにちは!テラーノベルのオスカルです。最近Webの開発をしてます。日本語はまだまだ勉強してますので、応援してください! 🙏
今回、Reactで動画制作ができるRemotionというライブラリを触ってみて、思ったより楽しかったので絶対紹介したいと思いました。
セットアップのインストール
Node >= 14とFFmpegは必要です。そこから、プロジェクトを作りましょう:
yarn create video
↑を実行するとテンプレートがいくつ出てきて選べます:
今回は僕はBlank
を選びます。するといろんなファイルを作ってくれます。みてみよう!
これだけ?なるほど! じゃ、簡単そうなので一つずつ確認しましょう:
Index.ts
このファイルはエントリーポイントだけです。Root
はインポートしてregisterRoot
します、ここから始めると言っているようなものです!
Root.tsx
React
コードですね!。ここはComposition
というコンポーネントがいくつ追加できます。各Composition
の定義は動画の設定です: フレーム数、FPS、サイズなど。また、component={MyComposition}
という記述がありますが、これは動画内で表示される内容がMyComposition
コンポーネントによって制御されていることを意味します。
MyComposition.tsx
ここには、アニメーションを作成するためのコンポーネントです。他のエレメントとスタイルを追加することができます。
何も入っていないので、ちょっとコードを追加しましょう!
export const MyComposition = () => {
return (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: '#f2511b',
color: '#fff',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
fontSize: '5rem',
fontFamily: 'Arial',
}}
>
<h1>Teller Novel</h1>
</div>
);
};
h1
タイトルを含むスタイル付きのdiv
レイヤーを追加しましたね。次はプレビュー機能を確認しましょう:
プレビュー
もしターミナルでエントリポイントファイルへのパスを指定してこのコマンドを実行すれば、本当に素晴らしいUIが表示されます!
npx remotion preview src/index.ts
サーバーが起動し、ブラウザで以下のような画面が表示されるはずです。
#1- Root.tsx
で設定した動画 (いくつあったらここに出てきます)
#2- MyComp
のプレビュー
#3- タイムラインです
現在、コンテンツは静的な状態ですので、アニメーションを追加しましょう!
useCurrentFrame
フック
Root.tsx
を見たら、MyComp
動画はこの設定でした:
durationInFrames={60}
この動画には60フレームがあります。useCurrentFrameというフックがあり、現在のフレーム番号を取得できます。その値は0から59まで変化します。フレーム番号を知っていれば、要素のアニメーションに使用することができます!
まず最初に、フックをインポートし、フレームを取得し、Teller Novelのタイトルのすぐ後に表示させましょう:
import { useCurrentFrame } from "remotion";
export const MyComposition = () => {
const frame = useCurrentFrame();
return (
<div
style={....}
>
<h1>Teller Novel {frame}</h1>
</div>
)
};
保存とプレビュー画面を開いて、プレイをしたら:
ちゃんと変更してますね!、じゃ、frame
を使ってh1
にCSSでアニメーションを追加していきます:
<h1 style={{
transform: `translateY(${frame * 2}px)`,
}}>
Teller Novel
</h1>
結果は:
もっとCSS
を弄ったら:
<h1
style={{
display: 'inline-block',
padding: '10px',
border: `${frame / 20}px solid white`,
borderRadius: `${frame / 5}px`,
boxShadow: `11px 10px ${frame * 2}px 0px rgba(0,0,0,0.75)`,
transform: `translateY(${frame * 5}px)
translateX(-${frame}px)
rotate(${frame / 2}deg)
scale(${frame / 30})`,
}}>
Teller Novel
</h1>
ここまでできました!
useVideoConfig
フックもありますよ、fps
とheight
とdurationInFrames
なども取れますので、細かくまでコンポーネントは調整できます!
Spring
で物理アニメーション計算
Spring は、フレームとFPSに基づいてバウンスする値を計算するためのライブラリです。
追加が非常に簡単なので、試してみましょう!
Springアニメーションに必要なFPSを取得するために、useVideoConfig
を使用していることに注意してください。
先のh1
のtransform css
部分はspring
に変更します:
import {useCurrentFrame} from 'remotion';
import {useVideoConfig} from 'remotion'; // <-- ここ!
import {spring} from 'remotion'; // <-- ここ!
export const MyComposition = () => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig(); // <-- ここ!
return (
<div style=[..]>
<h1
style={{
display: 'inline-block',
padding: '10px',
border: `${frame / 20}px solid white`,
borderRadius: `${frame / 5}px`,
boxShadow: `11px 10px ${frame * 2}px 0px rgba(0,0,0,0.75)`,
transform: `scale(${spring({fps, frame})})`, // <-- ここ!
}}
>
Teller Novel
</h1>
</div>
);
};
動画を見ると、タイトルのサイズアニメーションは素敵な加速度で行われます:
画像の使用
アセットはpublic
フォルダに配置されます。
その後、Img
とstaticFile
コンポーネントを使ってそれらをインポートすることができます。Teller Novel
のタイトルにテノちゃん入れましょう!
import {Img, staticFile, useCurrentFrame} from 'remotion'; // <-- ここ
import {useVideoConfig} from 'remotion';
import {spring} from 'remotion';
export const MyComposition = () => {
[..]
return (
<div style=[..]>
<h1 style=[..]>
Teller Novel
<Img // <-- ここから
src={staticFile('tenno-white.png')}
style={{
transform: `rotate(${frame * 15}deg)`
}}
/>
</h1>
</div>
);
};
くるくるでちょっとかわいそうだけど、プレイしよう!!
お、忘れちゃったけど、いつでもこのコマンドを実行することでMP4
ファイルも作成することができますよ!
npx remotion render MyComposition out.mp4
画像の連続で行われる伝統的なアニメーション
もし各フレームごとに異なる画像を用意し、動的に読み込むようにすれば、簡単に伝統的なアニメーションを作成することもできます!
ここから:
(cat1.png
- cat5.png
ですね)
画像は5個だけあるので、Composition
のdurationInFrames
も5
にしよう (fps=10
もいい気がします):
Root.tsx
<Composition
id="MyComposition"
component={MyComposition}
durationInFrames={5}
fps={10}
width={1280}
height={720}
/>
Composition.tsx
import {Img, staticFile, useCurrentFrame} from 'remotion';
export const MyComposition = () => {
const frame = useCurrentFrame();
return (
<div style=[..]>
<Img src={staticFile(`cat${frame + 1}.png`)} height="200" />
</div>
);
};
この簡単なコードで、美しいアニメーションを作成することができました!
他の興味深い機能
音声
mp3
ファイルなどをpublic
フォルダに入れたら<Audio>
コンポーネントで動画に入れれますよ。frame
もわかるので、アニメーションに効果音を追加することができますよね。
データの取得
React
なので、fetch
かSWR
フックを使ってAPIからデータを取れます。delayRender
あって、データあるまでレンダリングされないので、すごく便利です!
例えば:
import { continueRender, delayRender } from "remotion";
[..]
const [handle] = useState(() => delayRender());
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://catfact.ninja/fact')
.then((response) => response.json())
.then((d) => {
setData(d.fact);
continueRender(handle);
});
}, [handle]);
これにより、例えば、各ユーザーに対して動的に個別のパーソナライズされたムービーを作成することができますよ!
終わりに
Remotionは非常に柔軟で強力なツールです! もっともっとできることあるので、docsを是非読んでみてください。ショーケースもあるので、なんかなんでもできそう気がします!
もし動画作ってみたらコメントで教えてください!🙏
Discussion