div アニメーションで作るコールアウトはシンプルで再現性が高い一方、「矢印にループアニメーションを付けたい」「既製のアイコンアニメーションをそのまま使いたい」という場面もあります。

そういったときに役立つのが LottieFiles との連携です。LottieFiles には無料・有料問わず大量のアニメーション素材が公開されており、Remotion の @remotion/lottie パッケージで簡単に組み込めます。

この記事では、LottieFiles から矢印アニメーションを取得して Remotion のオーバーレイ動画に組み込む方法を、実装上のポイントも含めて解説します。

環境構築・プロジェクト作成・基本的な書き出し手順は「Claude Code × Remotion で動画字幕を自動化する」で解説しています。この記事では LottieFiles の組み込みに絞って解説します。

Claude Code × Remotion で動画字幕を自動化する【環境構築から書き出しまで】 Claude CodeとRemotionを組み合わせて、動画の字幕(キャプション)をProRes 4444透過動画として生成するワークフローを解説。content.tsでタイムスタンプを一元管理し、マニュアル動画・PV動画・YouTube動画など幅広い動画制作...  続きを読む

    LottieFiles とは

    LottieFiles は、After Effects で作成したアニメーションを JSON 形式(.json)で書き出した素材を配布するプラットフォームです。

    Lottie の JSON ファイルは軽量で、Web・モバイル・動画制作など幅広い用途で使われています。Remotion には公式の @remotion/lottie パッケージが用意されており、JSON を読み込むだけでアニメーションを再生できます。


    パッケージのインストール

    npm install @remotion/lottie
    

    Step 1: LottieFiles から JSON を取得する

    1. LottieFiles にアクセスし、使いたいアニメーションを検索
    2. アニメーションの詳細ページで 「Download」→「Lottie JSON」 を選択してダウンロード
    3. ダウンロードした JSON を src/lottie/ フォルダに配置
    src/
    └─ lottie/
         └─ arrow-right.json   # ← ここに配置
    

    矢印アニメーションの探し方

    検索ワードの例です。

    用途 検索ワード
    右向き矢印 arrow rightarrow animation
    クリック誘導 click heretap
    チェックマーク checkmarksuccess
    ローディング loadingspinner

    無料素材でも品質の高いものが多数あります。ライセンスは素材ごとに異なるため、商用利用する場合は必ず確認してください。


    Step 2: JSON のカラーを変更する

    LottieFiles からダウンロードした JSON は、素材のデフォルトカラーになっています。ブランドカラーに変更したい場合は JSON を直接編集します。

    カラー情報は JSON 内の "k" フィールドに [R, G, B, A] の形式(0〜1 の範囲)で格納されています。

    // 変更前(デフォルトカラー)
    "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }
    
    // 変更後(#0EA5E9 の場合)
    "c": { "a": 0, "k": [0.055, 0.647, 0.914, 1], "ix": 4 }
    

    HEX → 0〜1 変換は R/255, G/255, B/255 で計算できます。#0EA5E9 なら 14/255 ≈ 0.055, 165/255 ≈ 0.647, 233/255 ≈ 0.914 です。

    カラー箇所が複数ある場合は、エディタの「全置換」で一括変更するのが早いです。Claude Code に「この JSON の白([1,1,1,1])をブランドカラー #0EA5E9 に変更して」と指示する方法でも対応できます。


    Step 3: LottieArrow コンポーネントの実装

    @remotion/lottie の <Lottie> コンポーネントに JSON を渡すだけで再生されます。フェード・スライドなどのアニメーションは Remotion 側で interpolate を使って追加します。

    // src/components/LottieArrow.tsx
    
    import React from "react";
    import { useCurrentFrame, interpolate, Easing } from "remotion";
    import { Lottie } from "@remotion/lottie";
    import arrowAnimation from "../lottie/arrow-right.json";
    
    interface LottieArrowProps {
      x: number;          // 表示位置(左端からの px)
      y: number;          // 表示位置(上端からの px)
      label?: string;     // ラベルテキスト(任意)
      startFrame: number;
      endFrame: number;
      size?: number;      // アニメーションの幅(px)。デフォルト 200
    }
    
    export const LottieArrow: React.FC<LottieArrowProps> = ({
      x,
      y,
      label,
      startFrame,
      endFrame,
      size = 200,
    }) => {
      const frame = useCurrentFrame();
      const fadeInDuration = 10;
      const fadeOutDuration = 10;
    
      // フェードイン/アウト
      const opacity = interpolate(
        frame,
        [startFrame, startFrame + fadeInDuration, endFrame - fadeOutDuration, endFrame],
        [0, 1, 1, 0],
        { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
      );
    
      // 左からスライドイン
      const slideX = interpolate(
        frame,
        [startFrame, startFrame + fadeInDuration],
        [-20, 0],
        {
          extrapolateLeft: "clamp",
          extrapolateRight: "clamp",
          easing: Easing.out(Easing.cubic),
        }
      );
    
      if (frame < startFrame || frame > endFrame) return null;
    
      return (
        <div
          style={{
            position: "absolute",
            left: x,
            top: y,
            opacity,
            transform: `translateX(${slideX}px)`,
            display: "flex",
            alignItems: "center",
            gap: 8,
          }}
        >
          {label && (
            <div
              style={{
                backgroundColor: "#0EA5E9",
                color: "white",
                padding: "8px 16px",
                borderRadius: 6,
                fontSize: 18,
                fontWeight: "bold",
                whiteSpace: "nowrap",
              }}
            >
              {label}
            </div>
          )}
          <Lottie
            animationData={arrowAnimation}
            style={{ width: size, height: size / 2 }}
          />
        </div>
      );
    };
    

    実装のポイント

    animationData に JSON を直接インポートする

    @remotion/lottie の <Lottie> は src ではなく animationData prop に JSON オブジェクトを渡します。import で読み込んでそのまま渡すのが最もシンプルです。

    import arrowAnimation from "../lottie/arrow-right.json";
    
    <Lottie animationData={arrowAnimation} style={{ width: 200, height: 100 }} />
    

    高さは幅の半分を基準に

    多くの矢印アニメーションはアスペクト比 2:1 前後です。height: size / 2 を起点にして、見た目を確認しながら調整してください。

    Lottie アニメーション自体のループ・速度は JSON 側で制御される

    Lottie の再生速度やループ回数は元の JSON データに依存します。Remotion 側で playbackRate や loop を変更したい場合は <Lottie> の props で指定できます。

    <Lottie
      animationData={arrowAnimation}
      playbackRate={1.5}   // 1.5倍速
      loop={true}          // ループ再生
      style={{ width: size, height: size / 2 }}
    />
    

    Step 4: オーバーレイコンポジションへの組み込み

    content.ts に座標情報を持たせ、コンポジション側で展開します。

    content.ts に座標フィールドを追加

    // src/content.ts
    
    export interface Step {
      id: number;
      start: string;
      end: string;
      description: string;
      attention?: {
        x: number;       // 矢印の X 座標
        y: number;       // 矢印の Y 座標
        label?: string;  // ラベル(任意)
      };
    }
    
    export const STEPS: Step[] = [
      {
        id: 1,
        start: "00:05",
        end: "00:15",
        description: "管理画面から「設定」を開きます",
        attention: { x: 150, y: 400, label: "ここをクリック" },
      },
      {
        id: 2,
        start: "00:15",
        end: "00:28",
        description: "「保存」ボタンをクリックします",
        attention: { x: 800, y: 300 },
      },
    ];
    

    CalloutOverlay コンポジション

    // src/compositions/CalloutOverlay.tsx
    
    import { AbsoluteFill, Sequence } from "remotion";
    import { LottieArrow } from "../components/LottieArrow";
    import { STEPS, toFrame, VIDEO_CONFIG } from "../content";
    
    export const CalloutOverlay: React.FC = () => {
      const { fps } = VIDEO_CONFIG;
    
      return (
        <AbsoluteFill style={{ backgroundColor: "transparent" }}>
          {STEPS.filter((step) => step.attention).map((step) => {
            const startFrame = toFrame(step.start, fps);
            const endFrame = toFrame(step.end, fps);
    
            return (
              <Sequence
                key={step.id}
                from={startFrame}
                durationInFrames={endFrame - startFrame}
              >
                <LottieArrow
                  x={step.attention!.x}
                  y={step.attention!.y}
                  label={step.attention!.label}
                  startFrame={0}
                  endFrame={endFrame - startFrame}
                />
              </Sequence>
            );
          })}
        </AbsoluteFill>
      );
    };
    

    attention フィールドがある Step だけフィルターするため、矢印が不要なシーンは attention を省略するだけで自動的にスキップされます。


    Step 5: Root.tsx への登録と書き出し

    // src/Root.tsx
    
    import { Composition } from "remotion";
    import { CalloutOverlay } from "./compositions/CalloutOverlay";
    import { VIDEO_CONFIG } from "./content";
    
    const { fps, width, height, durationInFrames } = VIDEO_CONFIG;
    
    export const RemotionRoot: React.FC = () => (
      <>
        <Composition
          id="CalloutOverlay"
          component={CalloutOverlay}
          durationInFrames={durationInFrames}
          fps={fps}
          width={width}
          height={height}
        />
      </>
    );
    

    書き出しコマンドは他の記事と同じ形式です。

    npx remotion render CalloutOverlay output/callout.mov 
      --image-format=png 
      --pixel-format=yuva444p10le 
      --codec=prores 
      --prores-profile=4444 
      --muted
    

    package.json に登録しておくと便利です。

    {
      "scripts": {
        "render:callout": "remotion render CalloutOverlay output/callout.mov --image-format=png --pixel-format=yuva444p10le --codec=prores --prores-profile=4444 --muted"
      }
    }
    

    div アニメーションと Lottie の使い分け

    この記事で扱った LottieArrow と、Callout 記事で解説した div ベースの Callout は用途で使い分けるのがおすすめです。

    div アニメーション Lottie
    向いている用途 地図ピン・波紋・矩形ボーダーなど独自デザイン 矢印・アイコンなど既製素材をそのまま使いたい場合
    カスタマイズ コードで多くのコントロールできる JSON 編集でカラー変更は可能。形状変更は難しい
    工数 実装に時間がかかる JSON を置くだけで動く
    ループ・速度 Remotion 側で自由に制御 元の JSON データに依存(playbackRate で調整可)

    シンプルな矢印や汎用アイコンは Lottie、ブランドの独自デザインが必要な場合は div、という切り分けが実用的です。


    まとめ・関連記事

    この記事では、LottieFiles の JSON を Remotion に組み込み、フェード・スライドアニメーションを付けてオーバーレイ動画として書き出す方法を解説しました。

    @remotion/lottie を使えば既製のアニメーション素材をそのまま活用できるため、矢印・アイコン類の実装コストを大幅に削減できます。

    Claude Code × Remotion で動画字幕を自動化する【環境構築から書き出しまで】 Claude CodeとRemotionを組み合わせて、動画の字幕(キャプション)をProRes 4444透過動画として生成するワークフローを解説。content.tsでタイムスタンプを一元管理し、マニュアル動画・PV動画・YouTube動画など幅広い動画制作...  続きを読む Gemini×Remotion でテロップを作る【Telop.tsx の実装とフォント設定】 Remotionでテロップコンポーネント(Telop.tsx)を実装する方法を解説。日本語フォント・約物カーニング・フェードアニメーション・縦位置の切り替えなど、品質にこだわった実装を紹介。Geminiとのcontent.ts連携でタイムスタンプ生成も自動化で...  続きを読む Remotion で Callout アニメーションを作る【Studio × Zod でリアルタイム座標調整】 Remotionでコールアウト(地図ピン・波紋・コネクター線・ラベル)をdivアニメーションで実装する方法を解説。SVGが使えない問題の解決策、段階的アニメーションのチェイン、Remotion Studio+Zodスキーマによるリアルタイム座標調整まで踏み込ん...  続きを読む

    参考リンク