今回紹介しているプログラムを動かして作成した動画です
↓↓
📚 Remotion シリーズ 全8回の記事一覧
- 第1回: 全体像をまとめる
Composition / AbsoluteFill / Sequence で動画の骨組みを作る - 第2回: Hooks を理解する
useCurrentFrame / useVideoConfig でフレーム番号と設定を取得する - 第3回: アニメーションを作る
interpolate / spring でフレーム番号を CSS の値に変換する - 第4回: 素材を使う
画像・動画・音楽素材を組み込む - 第5回: テロップを入れる
テキストオーバーレイの作り方 - ▶ 第6回: シーンを構成する(この記事)
Series / TransitionSeries でシーン切り替えとトランジション - 第7回: GitHub Actions で自動レンダリング
CI/CD で動画レンダリングを自動化する - 第8回: 応用テクニック(準備中)
GIF・静止画書き出し / FFmpeg カスタマイズ / Lambda / 3D
はじめに
前回までで、Remotion の以下機能についてまとめてきました。
Composition/AbsoluteFill/Sequenceで動画の骨組みを作る(第1回)useCurrentFrame/useVideoConfigでフレーム番号と設定を取得する(第2回)interpolate/springでフレーム番号を CSS の値に変換する(第3回)- 画像・動画・音楽素材を使う方法(第4回)
- テロップ(テキストオーバーレイ)の作り方(第5回)
ここまでで、画像・動画を配置して、テロップを重ねてアニメーションをつけるという「1つのシーンを作る」技術は揃いました。
今回は 複数のシーンを1本の動画にまとめる 方法を扱います。<Series> でシーンを順番に並べ、<TransitionSeries> でトランジションを入れます。
Sequence の復習と限界
第1回の記事 で <Sequence> を使ってコンポーネントの表示タイミングをずらす方法を説明しました。
<Sequence from={0} durationInFrames={90}> <IntroScene /> </Sequence> <Sequence from={90} durationInFrames={120}> <MainScene /> </Sequence> <Sequence from={210} durationInFrames={60}> <OutroScene /> </Sequence>
これでもシーンを順番に並べられますが、問題があります。
from を全部手動で計算しないといけません。
3つのシーンなら大したことありませんが、10シーンの動画だと各シーンの from を計算するのが面倒ですし、途中のシーンの長さを変えたら後ろの from を全部ずらす必要があります。
手動でやるとミスの元ですね。
Series:シーンを順番に並べる
基本
<Series> を使うと、from を書かずにシーンを 順番に 並べるだけでOKです。
import { Series } from "remotion"; export const MyVideo: React.FC = () => { return ( <Series> <Series.Sequence durationInFrames={90}> <IntroScene /> </Series.Sequence> <Series.Sequence durationInFrames={120}> <MainScene /> </Series.Sequence> <Series.Sequence durationInFrames={60}> <OutroScene /> </Series.Sequence> </Series> ); };
再生順は Intro(90f) → Main(120f) → Outro(60f) で、合計 270f になります。
<Series> が内部で from を自動計算してくれます。例えば、MainScene の長さを 150f に変えてもOutroScene の開始位置は自動で調整されます。
offset で重ねる
<Series.Sequence> に負の offset を指定すると、前のシーンとの間に重なりを作れます。
<Series> <Series.Sequence durationInFrames={60}> <SceneA /> </Series.Sequence> <Series.Sequence offset={-15} durationInFrames={60}> {/* SceneA の終了15フレーム前から始まる */} <SceneB /> </Series.Sequence> </Series>
offset はそのシーンだけでなく、後続のシーンの開始位置にも影響します(後ろもまとめてシフトされます)。
ただし、これは単純に重なるだけでトランジション効果はありません。両方のシーンが同時に表示されるだけです。トランジション(フェードやスライド)を入れたい場合は、次の <TransitionSeries> を使います。
TransitionSeries:シーン間にトランジションを入れる
パッケージのインストール
<TransitionSeries> は @remotion/transitions パッケージに入っています。
npx remotion add @remotion/transitions
フェードトランジション
最も基本的なトランジションです。次のシーンが前のシーンの上にフェードインで重なります。
import { TransitionSeries, linearTiming } from "@remotion/transitions"; import { fade } from "@remotion/transitions/fade"; export const MyVideo: React.FC = () => { return ( <TransitionSeries> <TransitionSeries.Sequence durationInFrames={90}> <SceneA /> </TransitionSeries.Sequence> <TransitionSeries.Transition presentation={fade()} timing={linearTiming({ durationInFrames: 15 })} /> <TransitionSeries.Sequence durationInFrames={90}> <SceneB /> </TransitionSeries.Sequence> </TransitionSeries> ); };
timeline: 0 ----- 75 - 90 ----- 165
[ SceneA ]
[ SceneB ]
<TransitionSeries.Transition> を2つの Sequence の 間に挟む だけです。
注意点として、fade() は 次のシーンをフェードインで上に重ねる トランジションで、前のシーンの opacity は変化しません。いわゆるクロスフェード(両方が同時にフェードイン/アウトする)ではないので、incoming のシーンは不透明な背景を持つ必要があります(透明だと前のシーンが透けて見えてしまいます)。
スライドトランジション
次のシーンが横からスライドしてきます。
import { slide } from "@remotion/transitions/slide"; <TransitionSeries.Transition presentation={slide({ direction: "from-left" })} timing={linearTiming({ durationInFrames: 20 })} />
方向は4種類です。
| direction | 動き |
|---|---|
"from-left" |
左から右へスライド |
"from-right" |
右から左へスライド |
"from-top" |
上から下へスライド |
"from-bottom" |
下から上へスライド |
from-left: SceneA が右へスライドアウト ←→ SceneB が左からスライドイン from-bottom: SceneA が上へスライドアウト ←→ SceneB が下からスライドイン
ワイプトランジション
一方のシーンが「拭き取る」ように消えて次のシーンが現れます。テレビ番組でよく見る効果ですね。
import { wipe } from "@remotion/transitions/wipe"; <TransitionSeries.Transition presentation={wipe({ direction: "from-left" })} timing={linearTiming({ durationInFrames: 20 })} />
slide と同じ4方向に加えて、"from-top-left" などの斜め4方向もあり、計8方向から選べます。
その他のトランジション
import { fade } from "@remotion/transitions/fade"; // フェード(incoming を上から重ねる) import { slide } from "@remotion/transitions/slide"; // スライド import { wipe } from "@remotion/transitions/wipe"; // ワイプ import { flip } from "@remotion/transitions/flip"; // フリップ(カードを裏返すように) import { clockWipe } from "@remotion/transitions/clock-wipe"; // 時計回りワイプ
どれも使い方は同じで、presentation={xxx()} に渡す関数を変えるだけです。
タイミングの制御:linearTiming と springTiming
トランジションの 速度の変化 を timing で制御します。
linearTiming:一定速度
import { linearTiming } from "@remotion/transitions"; linearTiming({ durationInFrames: 20 })
20フレームかけて、一定速度でトランジションが進みます。最も基本的で予測しやすいです。
springTiming:バネ的な動き
import { springTiming } from "@remotion/transitions"; springTiming({ config: { damping: 200 } })
アニメーションの記事 で解説した spring と同じ物理モデルです。linearTiming と違い、トランジションの長さはバネの物理パラメータから自動で決まります。スライドトランジションに springTiming を使うと、ページが勢いよくスライドしてきて、最後にスッと減速して止まるような自然な動きになります。
まとめ
今回は新しい API がいくつか出てきましたが、考え方はシンプルです。
| テクニック | 使うもの | ポイント |
|---|---|---|
| シーンを順番に並べる | <Series> |
from の手動計算が不要 |
| トランジション | <TransitionSeries> + presentation + timing |
fade / slide / wipe / flip / clockWipe |
| タイミング制御 | linearTiming / springTiming |
一定速度 or バネ的な動き |
サンプルアニメーションとソースコード
これを組み合わせると、以下みたいな動画は簡単に作ることができます。
コンポーネント部分だけですが、ソースコードも Gist で一応置いておきます
https://gist.github.com/chan-ume/2bd57a79fe1aec803d3d6a0079e34eb3
次は、レンダリングや書き出しなどの便利機能を見ていきます。