【React】【TypeScript】Remotionで「Hello, World」が飛び出す動画を作ってみた
まえがき
ライブラリRemotionを使って「Hello, World」が徐々に表示される動画と飛び出す動画を作ります。
動画でも解説しているので、当記事と一緒にご覧ください。
Remotionとは
Remotionとはプログラミングで動画を作れるライブラリです。
基本はReactベースでTypeScriptを使います。
また、他にもたくさんのテンプレートが用意されています。
TypeScriptではなく、JavaScriptでも使えます。
Reactのフレームワークである、Next JS App Routerも使えます。
プロジェクトを新規作成
まずはVS Codeを開いて、ターミナルを呼び出します。
プロジェクトを作成する任意の場所に移動します。
私はデスクトップ上のディレクトリProject
の中にディレクトリRemotionProject
を作成しています。
コマンドcd desktop/project/remotionproject/
を実行して移動します。
cd desktop/project/remotionproject/
プロジェクトを作成するディレクトリに移動したら、ターミナルでコマンドnpm init video
を実行します。
npm init video
まずはプロジェクト名を質問されます。
ここではremotion-str-anima-yt
とします。
ちなみにremotion-str-anima-yt
は自由に決めていただいて結構です。
次はテンプレートを選択するように指示されます。ここでは、上から4番目のBlank
を選択します。
ディレクトリremotion-str-anima-yt
が作成されて、その中にプロジェクトが作成されます。
最後にVS Codeでプロジェクトを開くかどうか質問されるので、y
を入力します。
新たにVS Codeが立ち上がるので、元のウィンドウは消します。
新たにが立ち上がったVS Codeでターミナルを開きます。
README.md
が開いているので閉じておきます。
文字列が徐々に現れるアニメーションを作成
最初は文字列が徐々に現れるアニメーションを作成します。
FadeIn.tsx
src
ディレクトリにファイルFadeIn.tsx
を作成します。
ファイルFadeIn.tsx
を開いてrafc
と入力すると候補が出てくるのでrafc
を選択します。
すると、コードが自動補完されます。
これは、拡張機能、ES7+ React/Redux/React-Native snippetsを導入すると使えるようになります。
ぜひ、オススメします。
import React from 'react'
export const FadeIn = () => {
return (
<div>FadeIn</div>
)
}
コードを以下のように編集します。
import { AbsoluteFill, useCurrentFrame } from "remotion";
export const FadeIn = () => {
const frame = useCurrentFrame();
const opacity = Math.min(1, frame / 60);
return (
<AbsoluteFill
style={{
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
fontSize: 80,
}}
>
<div style={{ opacity }}>Hello, World</div>
</AbsoluteFill>
);
};
return
の前にconst frame = useCurrentFrame();
を追記します。
前回も説明しましたが、useCurrentFrame()
はRemotionのフックで動画のフレーム数を取得します。
そして、変数frame
に代入しています。
次はconst opacity = Math.min(1, frame / 60);
を追記します。
これはopacity
という変数に文字列の透明度の値を取得しています。
JavaScriptのMath.min
関数は与えられた数値の中でもっとも小さい値を返します。
具体的にはframe / 60
と1
の間で小さい方の値をopacity
として選択します。
frame / 60
が1
より大きくなるときは1
を使用します。
それ以外の場合はframe / 60
の値をopacity
として使用します。
return
の中のdiv
タグをAbsoluteFill
に変更します。
コンポーネントAbsoluteFill
の解説は前回の動画ライブラリRemotionで動画を作成(PART1)をご覧ください。
次にAbsoluteFill
内にdiv
タグを追記します。
div
タグにstyle
を当てていきます。
要素はopacity
だけです。
最後にdiv
タグ内にHello, World
を入力します。
Root.tsx
import { Composition } from "remotion";
import { FadeIn } from "./FadeIn";
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="FadeIn"
component={FadeIn}
durationInFrames={60}
fps={30}
width={1280}
height={720}
/>
</>
);
};
ファイルComposition.tsx
は不要なので削除しておきます。
ファイルRoot.tsx
を開いて、Composition
の引数をMyComposition
からFadeIn
に変更します。
id
の引数もMyComp
からFadeIn
に変更します。
残りの値をそのままでいいです。
コンポーネントComposition
の解説はライブラリRemotionで動画を作成(PART1)で詳しく解説しています。
プレビューを確認
コマンドnpm start
を実行してプレビューを確認します。
文字列が飛び出すアニメーションを作成
次に文字列が飛び出すアニメーションを作成します。
ScaleText.tsx
src
ディレクトリにファイルScaleText.tsx
を作成します。
ファイルScaleText.tsx
を開いてrafc
と入力すると候補が出てくるのでrafc
を選択します。
すると、コードが自動補完されます。
import React from 'react'
export const ScaleText = () => {
return (
<div>ScaleText</div>
)
}
コードを以下のように編集します。
import {
AbsoluteFill,
spring,
useCurrentFrame,
useVideoConfig,
} from "remotion";
export const ScaleText = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scale = spring({ fps, frame });
return (
<AbsoluteFill
style={{
flex: 1,
backgroundColor: "white",
justifyContent: "center",
alignItems: "center",
fontSize: "7rem",
}}
>
<div style={{ transform: `scale(${scale})` }}>Hello, World</div>
</AbsoluteFill>
);
};
まずはreturn
の前にconst frame = useCurrentFrame();
を追記します。
するとuseCurrentFill
が自動でインポートされます。
次にconst { fps } = useVideoConfig();
を追記します。
useVideoConfig
が自動でインポートされます。
useVideoConfig
はRemotionライブラリのフックで、動画の設定情報を取得するために使用されます。
このフックを使用することで動画のフレームレート(fps)などの設定を取得できます。
上記のコードではuseVideoConfig
から取得した動画のフレームレートを変数fps
に代入しています。
これにより、動画のフレームレートを使用してアニメーションを制御できます。
最後にconst scale = spring({ fps, frame });
を追記します。
spring
が自動でインポートされます。
spring
関数は指定されたフレームレートとフレーム数に基づいてスケール値を計算します。
Reactのインポートは不要なので削除します。
return
の中のdiv
タグの開始タグと終了タグをAbsoluteFill
に変更します。
AbsoluteFill
タグにstyle
を当てていきます。
style
内の説明は割愛します。
AbsoluteFill
タグ内のScaleText
を消してdiv
タグを追加します。
div
タグにstyle
を当てていきます。
要素はtransform: `${scale(${scale})}`
です。
transform
プロパティにscale()
関数を適用して文字列を拡大縮小しています。
最後にdiv
タグ内にHello, World
を入力します。
Root.tsx
import { Composition } from "remotion";
import { FadeIn } from "./FadeIn";
+ import { ScaleText } from "./ScaleText";
export const RemotionRoot: React.FC = () => {
return (
<>
+ <Composition
+ id="ScaleText"
+ component={ScaleText}
+ durationInFrames={60}
+ fps={30}
+ width={1280}
+ height={720}
+ />
<Composition
id="FadeIn"
component={FadeIn}
durationInFrames={60}
fps={30}
width={1280}
height={720}
/>
</>
);
};
ファイルRoot.tsx
を開きます。
元々あるComposition
をコピペして新たにComposition
を追加します。
引数id
と引数component
の値をScaleText
に変更します。
名前 'ScaleText' が見つかりません。とエラーが表示されます。
カーソルを合わせるとダイアログが表示されます。
Command + . でクイックフィックスを使います。
選択肢の2番目にインポートの追加が表示されるので選択して追加します。
残りの値をそのままでいいです。
プレビューを確認
コマンドnpm start
を実行してプレビューを確認します。
あとがき
今回は徐々にHello, Worldが表示される動画とHello, Worldが飛び出すような動画を作成しました。
プロジェクトのソースコードをGitHubで公開しています。
参考にしてください。
Discussion