【React】【TypeScript】Remotionでフェードインからフェードアウトする動画を作ってみた
まえがき
ライブラリRemotionを使ってフェードインから最後にフェードアウトする動画を作ります。
動画でも解説しているので、当記事と一緒にご覧ください。
Remotionとは
Remotionとはプログラミングで動画を作れるライブラリです。
基本はReactベースでTypeScriptを使います。
また、他にもたくさんのテンプレートが用意されています。
TypeScriptではなく、JavaScriptでも使えます。
Reactのフレームワークである、Next JS App Routerも使えます。
プロジェクトを新規作成
今回からVS CodeからCursorというエディタに変更します。
VS CodeベースでAI機能が付属したようなエディタです。
詳しいことは、他の動画を見ていただきたいと思います。
それではCursorを開いて、ターミナルを呼び出します。
プロジェクトを作成する任意の場所に移動します。
私はデスクトップ上のディレクトリProject
の中にディレクトリRemotionProject
を作成しています。
コマンドcd desktop/project/remotionproject/
を実行して移動します。
cd desktop/project/remotionproject/
プロジェクトを作成するディレクトリに移動したら、ターミナルでコマンドnpm init video
を実行します。
npm init video
まずはプロジェクト名を質問されます。
ここではremotion-fade-in-out-yt
とします。
ちなみにremotion-fade-in-out-yt
は自由に決めていただいて結構です。
次はテンプレートを選択するように指示されます。ここでは、上から4番目のBlank
を選択します。
ディレクトリremotion-fade-in-out-yt
が作成されて、その中にプロジェクトが作成されます。
プロジェクトが作成されたら、指示通りにディレクトリremotion-fade-in-out-yt
に移動します。
cd remotion-fade-in-out-yt
移動したら、新たにCursorを開きます。
code .
Prettierの設定
Prettierはコードを自動的に整形するツールです。
これを利用すると決めたルールに則ってコードを自動的に変更してくれます。
拡張機能「Prettier - Code formatter」をインストール
拡張機能「Prettier - Code formatter」をインストールしておきます。
Cursorの設定
Cursorの設定を変更します。
メニューからCursor - 基本設定 - 設定を選択します。
ショートカットキーでCommand
+,
で開くこともできます。
こちらの方が早いので、覚えておきましょう。
Cursorの設定にFormat On Saveという項目があります。
Format On Saveを検索します。
検索したら、テキストエディタのFormat On Saveを見ます。
もしチェックが入っていない場合はチェックを入れてください。
次に、default formatと検索します。
検索したら、テキストエディタのEditor: Default Formatterを見ます。
Prettier - Code formatterを選択します。
.prettierrc
を変更
私の好みですが、シングルクォートよりダブルクォート、波括弧の中にはスペースを入れるようにルールを変更します。
また、タブ文字を使わずにスペースが使われるようにルールを変更します。
- import {Composition} from 'remotion';
+ import { Composition } from "remotion";
.prettierrc
でルールは設定できます。
早速.prettierrc
を編集します。
singleQuote
singleQuote
はシングルクォートを使うかどうかを設定します。
ここではtrue
でシングルクォートを使うようになっているのでfalse
に変更します。
- "singleQuote": true,
+ "singleQuote": false,
bracketSpacing
bracketSpacing
はスペースを入れるかどうかを設定します。
ここではfalse
でスペースを入れないようになっているのでtrue
に変更します。
- "bracketSpacing": false,
+ "bracketSpacing": true,
useTabs
useTabs
はタブ文字を使用してインデントを行うか、スペースを使うか設定します。
ここではtrue
でタブ文字を使うようになっているのでfalse
に変更します。
- "useTabs": true,
+ "useTabs": false,
これで決めたルール通り、保存するときにコードが自動的に整形されます。
フェードイン
まずは文字列がフェードインする動画を作成します。
今回の本題であるフェードインからフェードアウトの動画を作成するにはinterpolate
関数を必要になります。
この関数は指定された入力値の範囲から出力値の範囲への線形補間を行うRemotionライブラリの関数です。
線形補間とは得られているデータを直線でつなげることです。
と、言葉で言ってもよくわからないですよね。
そこでinterpolate
関数を使ったフェードインする動画を作成してみます。
まずは実際のコードでinterpolate
関数の基本的な使い方を見ていきます。
interpolate
関数
ファイルComposition.tsx
にコードを追記します。
+ import { interpolate, useCurrentFrame } from "remotion";
export const MyComposition = () => {
+ const frame = useCurrentFrame();
+ const opacity = interpolate(frame, [0, 20], [0, 1]);
return null;
};
interpolate
関数に3つの引数を渡しています。
第1引数は入力値を指定します。
ここではframe
を渡しています。
第2引数は入力が想定する値の範囲を指定します。
ここではフレーム0
からフレーム20
を指定しています。
第3引数は入力に対応させたい出力値の範囲を指定します。
ここでは不透明度0
から不透明度1
を指定しています。
これでフレーム0
からフレーム20
の間に不透明度0
から不透明度1
になります。
これを線形補間すると、以下のようなグラフで表されます。
ここまでを踏まえてコードを完成させます。
Root.tsx
Root.tsx
はそのまま使います。
import { Composition } from "remotion";
import { MyComposition } from "./Composition";
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="MyComp"
component={MyComposition}
durationInFrames={60}
fps={30}
width={1280}
height={720}
/>
</>
);
};
動画のフレーム数はdurationInFrames={60}
で設定しています。
これを線形補間すると、以下のようなグラフで表されます。
Composition.tsx
ファイルComposition.tsx
にコードを完成させます。
return null
のnull
の部分をコンポーネントAbsoluteFill
を追加します。
interpolate
関数以外の詳しい説明は以前のRemotionの記事をご覧ください。
あとは、わかりやすいようにフレーム数も表示するように加えておきます。
import { AbsoluteFill, interpolate, useCurrentFrame } from "remotion";
export const MyComposition = () => {
const frame = useCurrentFrame();
const opacity = interpolate(frame, [0, 20], [0, 1]);
return (
<AbsoluteFill
style={{
flex: 1,
backgroundColor: "white",
justifyContent: "center",
alignItems: "center",
fontSize: "7em",
}}
>
<p>{`フレーム数:${frame}`}</p>
<div style={{ opacity }}>Hello, World</div>
</AbsoluteFill>
);
};
プレビューを確認
わかりやすいように再生速度を0.25倍にして再生しています。
できた動画を見るとフレーム0
からフレーム20
にかけてHello, Worldが徐々に現れてきます。
その後はHello, Worldが表示されつづけます。
フェードインからフェードアウト
フェードイン効果はそのままに、最後にフェードアウト効果を加えます。
interpolate
関数
以下のinterpolate
関数のコードを変更します。
またフックuseVideoConfig
を使ってdurationInFrames
を取得します。
import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";
export const MyComposition = () => {
const frame = useCurrentFrame();
+ const { durationInFrames } = useVideoConfig();
const opacity = interpolate(
frame,
- [0, 20],
+ [0, 20, durationInFrames - 20, durationInFrames],
// v--v---v----------------------v
- [0, 1]
+ [0, 1, 1, 0]
);
...
}
第2引数[0, 20, durationInFrames - 20, durationInFrames]
は4つの時点のフレーム数を指定しています。
そして第3引数[0, 1, 1, 0]
は4つの時点に対応した不透明度を指定しています。
これを見ると20
フレームから動画が終わる20
フレーム前では不透明度は1
のままです。
最後には不透明度は0
になるはずです。
一度に複数のポイントを補間しuseVideoConfig()
を使用してコンポジションの継続時間を決定できます。
Root.tsx
Root.tsx
はそのまま使います。
Root.tsx
で動画のフレーム数はdurationInFrames={60}
で設定していました。
これを線形補間すると、以下のようなグラフで表されます。
Composition.tsx
コードは以下のようになります。
interpolate
関数以外はそのままで大丈夫です。
import {
AbsoluteFill,
interpolate,
useCurrentFrame,
useVideoConfig,
} from "remotion";
export const MyComposition = () => {
const frame = useCurrentFrame();
const { durationInFrames } = useVideoConfig();
const opacity = interpolate(
frame,
[0, 20, durationInFrames - 20, durationInFrames],
[0, 1, 1, 0]
);
return (
<AbsoluteFill
style={{
flex: 1,
backgroundColor: "white",
justifyContent: "center",
alignItems: "center",
fontSize: "7em",
}}
>
<p>{`フレーム数:${frame}`}</p>
<div style={{ opacity }}>Hello, World</div>
</AbsoluteFill>
);
};
プレビューを確認
わかりやすいように再生速度を0.5倍にして再生しています。
できた動画を見るとフレーム0
からフレーム20
にかけてHello, Worldが徐々に現れてきます。
そしてフレーム21
からフレーム40
の間はHello, Worldが表示されます。
最後にフレーム41
からフレーム60
にかけてHello, Worldが徐々に消えていきます。
interpolate
関数の考え方
ここまでinterpolate
関数を線形補間してグラフで2度表示しました。
const opacity = interpolate(
frame,
[0, 20, durationInFrames - 20, durationInFrames],
// v--v---v----------------------v
[0, 1, 1, 0]
);
durationInFrames
を60
とすると以下のようにコードを書き換えられます。
const opacity = interpolate(
frame,
[0, 20, 40, 60],
// v--v---v---v
[0, 1, 1, 0]
);
そして、グラフに表すと以下のようになりました。
コードとグラフを見比べてみます。
第2引数の値はグラフの横軸の値になり、第3引数の値はグラフの縦軸の値になっています。
そこから自分が描きたい動きをグラフで想像して、引数の値を考えるといいかもしれません。
あとがき
今回はライブラリRemotionを使ってフェードインからフェードアウトする動画を作ってみました。
プロジェクトのソースコードはGitHubで公開しています。
参考にしてください。
Discussion