以下の内容はhttps://www.randpy.tokyo/entry/remotion-6-transitionより取得しました。


Remotion でシーン同士を繋げるトランジションを作る【Remotion 第6回】

 Remotion でシーンを構成する:Series とトランジション 今回紹介しているプログラムを動かして作成した動画です
↓↓

youtu.be

📚 Remotion シリーズ 全8回の記事一覧

  1. 第1回: 全体像をまとめる
    Composition / AbsoluteFill / Sequence で動画の骨組みを作る
  2. 第2回: Hooks を理解する
    useCurrentFrame / useVideoConfig でフレーム番号と設定を取得する
  3. 第3回: アニメーションを作る
    interpolate / spring でフレーム番号を CSS の値に変換する
  4. 第4回: 素材を使う
    画像・動画・音楽素材を組み込む
  5. 第5回: テロップを入れる
    テキストオーバーレイの作り方
  6. ▶ 第6回: シーンを構成する(この記事)
    Series / TransitionSeries でシーン切り替えとトランジション
  7. 第7回: GitHub Actions で自動レンダリング
    CI/CD で動画レンダリングを自動化する
  8. 第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 バネ的な動き

サンプルアニメーションとソースコード

これを組み合わせると、以下みたいな動画は簡単に作ることができます。

youtu.be

コンポーネント部分だけですが、ソースコードも Gist で一応置いておきます

https://gist.github.com/chan-ume/2bd57a79fe1aec803d3d6a0079e34eb3


次は、レンダリングや書き出しなどの便利機能を見ていきます。

www.randpy.tokyo




以上の内容はhttps://www.randpy.tokyo/entry/remotion-6-transitionより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14