本文へ移動
cccskills
無料GitHub で公開

remotion-trace

参考動画からプロ品質の Remotion 動画を再現するワークフロースキル。「参考動画から再現したい」「動画トレース」「PVを作りたい」「Remotion動画を参考動画ベースで作りたい」で発動。

インストール方法を見る

含まれるファイル(4)

  • SKILL.md21.3 KB
  • agents/openai.yaml162 B
  • SKILL.en.md19.7 KB
  • SKILL.es.md11.2 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Remotion Video Trace

参考動画からプロ品質の Remotion 動画を再現するためのワークフロースキル。 企業PV制作の実プロジェクト(16イテレーション)で確立した手法を体系化。

トリガーワード

「Remotion動画を作りたい」「PVを作りたい」「参考動画から再現」「動画トレース」

前提条件

  • Node.js + Remotion (mv-composer/ プロジェクト or 新規)
  • ffmpeg (フレーム抽出・音声処理)
  • yt-dlp (参考動画ダウンロード)

Part 1: Reference Research(参考動画リサーチ)

1.1 参考動画ソース

目的に応じてソースを使い分ける:

ソースURL用途
Vimeo Staff Picksvimeo.com/channels/staffpicksトランジション・カラーグレーディング
Art of the Titleartofthetitle.comタイトルシーケンス・モーショングラフィックス
Stash Mediastashmedia.tvCM・プロモ映像のトレンド
YouTube同業種・競合検索企業PV・紹介動画の業界水準把握
ゲームトレーラーBrikk等ダイナミックなカット・エフェクト

1.2 クリップ収集

「このシーンの表現が欲しい」単位で 5-10秒のクリップ を収集する。動画全体ではなく、特定の演出・トランジションにフォーカス。

# YouTube/Vimeo からクリップ単位でダウンロード
yt-dlp --download-sections "*57-59" -o "data/video_refs/{project}/{id}_%(section_start)s-%(section_end)s.%(ext)s" "https://youtube.com/watch?v={id}"

# Vimeo の場合
yt-dlp --download-sections "*20-30" -o "data/video_refs/{project}/vimeo_{id}_0020-0030.%(ext)s" "https://vimeo.com/{id}"

1.3 ファイル管理

data/video_refs/{project_name}/
├── {videoId}_{startSec}-{endSec}.mp4   # 参考クリップ
├── frames/                              # 抽出フレーム(Part 2で生成)
└── README.md                           # 各クリップの出典・用途メモ

必ず README.md に出典を記録:

## {videoId}_{start}-{end}.mp4
- 出典: {会社名} 公式PV (YouTube)
- 用途: 人物紹介のワイプ演出(暗背景→矩形飛散→写真露出)

Part 2: Frame Analysis(フレーム分析)

2.1 フレーム抽出

# 参考動画からフレーム抽出(6-10fps推奨)
ffmpeg -i data/video_refs/{project}/clip.mp4 \
  -vf "fps=8" \
  data/video_refs/{project}/frames/clip_%04d.png

# 特定区間のみ抽出する場合
ffmpeg -i clip.mp4 -ss 2.0 -t 3.0 -vf "fps=10" frames/%04d.png

2.2 視覚分析チェックリスト

抽出フレームを Read ツールで開き、以下の観点で分析する:

  • トランジション手法: ワイプ/フェード/スケール/clipPath/スライド
  • タイミング・イージング: spring/ease-out/linear/ステップ
  • テキスト表現: パンチイン/タイプライター/カスケード/スライドイン
  • 背景処理: 暗転/ブラー/パーティクル/グラデーション/画像overlay
  • 色彩・コントラスト: ブランドカラー/色温度/明暗バランス
  • レイアウト: グリッド/フルブリード/分割/センタリング
  • BGM同期ポイント: beat落ちでカット切り替え/テキスト出現

2.3 分析結果の記録

各クリップについて以下を記述:

## clip: {videoId}_{start}-{end}.mp4
### アニメーション分解
- 0.0s: 暗背景 + 白い矩形がランダム配置で飛散
- 0.5s: clipPath inset で左→右に写真がワイプイン
- 1.5s: 写真フル表示 + 左下に名前テロップ(白文字 shadow付き)
- 3.0s: 3ストリップに分割、各ストリップが別アングル
### Remotion実装メモ
- clipPath: `inset(0 ${100 - progress}% 0 0)` で実現可能
- 矩形飛散: position:absolute + ランダム top/left/rotation

2.4 draw.io PNG → React SVGアニメーション化ガイド

draw.io等で作成した図解PNGを、Remotion上のReact SVGアニメーションに変換する手順。

なぜ変換するか

観点PNG(そのまま)React SVG
アニメーション不可(静止画)要素が spring() で順番に登場
解像度拡大でぼやけるSVGはどんなサイズでもシャープ
微調整draw.ioで再編集→再エクスポートpx値やタイミングをコードで即座に制御
2フェーズ遷移不可1シーンで前半/後半で異なる情報を表示可能

変換手順

  1. 構成要素の分解: draw.ioの図をノード(ボックス)、矢印(コネクタ)、テキストラベルに分解。各要素の座標・サイズ・色をメモ
  2. Reactコンポーネント化: 各要素をSVGプリミティブで再実装
    // ノード → rect + text
    <rect x={node.x} y={node.y} width={node.w} height={node.h}
      rx={8} fill={node.color} opacity={nodeOpacity} />
    <text x={node.x + node.w/2} y={node.y + node.h/2}
      textAnchor="middle" dominantBaseline="central"
      fill="#FFF" fontSize={16}>{node.label}</text>
    
    // 矢印 → path or line
    <line x1={arrow.x1} y1={arrow.y1} x2={arrow.x2} y2={arrow.y2}
      stroke="#666" strokeWidth={2} markerEnd="url(#arrowhead)" />
    
  3. スタッガードアニメーション付与: spring() で要素を順番に登場させる
    const nodeOpacity = spring({
      frame: frame - index * STAGGER_DELAY,
      fps, config: { damping: 14, mass: 0.6, stiffness: 160 },
    });
    const nodeScale = spring({
      frame: frame - index * STAGGER_DELAY,
      fps, config: { damping: 14, mass: 0.6, stiffness: 160 },
    });
    // style: { opacity: nodeOpacity, transform: `scale(${nodeScale})` }
    
  4. 座標管理: 矢印のSVG path座標はTypeScript定数で管理し、ノード位置変更時に連動更新
    const NODES = {
      input:   { x: 100, y: 200, w: 180, h: 60, color: '#3B82F6', label: 'Input' },
      process: { x: 400, y: 200, w: 180, h: 60, color: '#10B981', label: 'Process' },
      output:  { x: 700, y: 200, w: 180, h: 60, color: '#F59E0B', label: 'Output' },
    } as const;
    

チェック

静的PNGが <Img> で3秒以上表示されている場合 → 「アニメーション化を検討」フラグを出す。 motion-review スキルの J3 チェック項目と連動。


Part 3: BPM & Audio Analysis(音楽分析)

3.1 BPM解析

# 参考動画から音声抽出
ffmpeg -i reference.mp4 -vn -acodec pcm_s16le ref_audio.wav

# 手動カウント: 10秒間のbeat数を数えて × 6
# または ffmpeg のエネルギー検出で波形を可視化
ffmpeg -i ref_audio.wav -af "showinfo" -f null - 2>&1 | head -50

3.2 Beat-Aligned Duration 設計

BPM = 103 の場合:
1 beat = 60/103 = 0.5825s
5 beats = 2.91s
9 beats = 5.24s

sectionDurations は必ず beat の整数倍にする。これにより BGM の拍とシーン切り替えが自然に同期する。

3.3 BGM 生成(fal.ai Stable Audio)

Stable Audio 2.5(推奨): 最大190秒を一発生成可能。ジョイント問題なし。

// fal.ai Stable Audio 2.5(最大190秒)
const result = await fal.subscribe("fal-ai/stable-audio-25/text-to-audio", {
  input: { prompt: "...", seconds_total: 80 },
});
const url = result.data?.audio?.url;
# 末尾フェードアウト(4秒)を適用して mp3 に変換
ffmpeg -y -i raw.wav -af "afade=t=out:st=76:d=4" -q:a 2 bgm_final.mp3

代替モデル(fal.ai):

モデルAPI ID最大尺用途
Stable Audio 2.5fal-ai/stable-audio-25/text-to-audio190秒汎用(推奨)
Beatoven maestrobeatoven/music-generation150秒ライセンス済み商用BGM
CassetteAIcassetteai/music-generator180秒低コスト高速
Stable Audio (旧)fal-ai/stable-audio47秒非推奨(分割+crossfadeが必要)

旧方式(47秒制限の場合のみ): 複数パートを crossfade で連結

ffmpeg -i part1.mp3 -i part2.mp3 \
  -filter_complex "[0][1]acrossfade=d=2:c1=tri:c2=tri" \
  -y bgm_full.mp3

3.4 ナレーション生成(ElevenLabs TTS)

TaxAccountantDemo v34-v40 で確立したワークフロー。

3.4.1 音声生成

# ElevenLabs multilingual v2 + 日本語向け推奨設定
VOICE_ID="StTDrGrPSyfaHGmzwXbj"  # Masa(落ち着いた日本語男性)
SETTINGS='{"stability":0.70,"similarity_boost":0.80,"style":0.10,"use_speaker_boost":true}'

curl -s -X POST "https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}" \
  -H "xi-api-key: ${ELEVENLABS_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"text":"テキスト","model_id":"eleven_multilingual_v2","voice_settings":'"${SETTINGS}"'}' \
  --output "narration.mp3"

3.4.2 中国語発音混入対策(重要)

ElevenLabs multilingual v2 は日本語の漢字を中国語読みすることがある。

対策: 問題が起きやすい漢字をひらがなに置換してから生成

税理士 → ぜいりし    記帳 → きちょう      仕訳 → しわけ
取引 → とりひき      損益 → そんえき      即時 → そくじ
即座 → そくざ        監視 → かんし        瞬時 → しゅんじ
24時間365日 → にじゅうよじかん さんびゃくろくじゅうごにち
12,800円 → いちまん にせん はっぴゃく えん

stability を 0.55→0.70 に上げると中国語混入が減る。

3.4.3 Gemini 発音評価(必須QA)

import google.generativeai as genai
model = genai.GenerativeModel("gemini-2.0-flash")
audio = genai.upload_file("narration.mp3")
resp = model.generate_content([
    audio,
    "この日本語音声を正確に書き起こしてください。"
    "中国語の発音が混入していないか、読み間違いがあれば指摘。"
])

全クリップに対して実行し、問題があるクリップのみ再生成。

3.4.4 atempo 速度調整

ナレーション尺がシーン尺を超える場合、ffmpeg atempo で調整:

# 例: 5.1秒のナレーションを3.6秒に収める(atempo 1.42)
ffmpeg -y -i raw.mp3 -af "atempo=1.42" adjusted.mp3

限界: atempo 1.35倍が上限。超えると早口で聞き取りづらい → テキストを短縮するか、シーン尺を延長。

3.4.5 Remotion への組み込み

// props にナレーションプレフィックスを定義
interface Props {
  narrationPrefix?: string;  // e.g. "tax/audio/narration/v4_s"
}

// 各シーンに Audio を配置
{p.narrationPrefix && starts.map((st, i) => {
  const padNum = String(i + 1).padStart(2, "0");
  return (
    <Sequence key={`narr-${i}`} from={st} durationInFrames={frames[i]}>
      <Audio src={staticFile(`${p.narrationPrefix}${padNum}.mp3`)} volume={1.2} />
    </Sequence>
  );
})}

音量バランス: ナレーション volume={1.0-1.2}, BGM volume={0.18-0.25}

3.5 音声ルール

  • SE なし・BGM 一本で駆け抜けるのが基本スタイル
  • 転調は動画が 45秒超の場合のみ検討
  • ライブ映像等の直接挿入時は muted で BGM と干渉させない
  • ナレーション付き動画: BGM volume を 0.20-0.25 に下げてナレーションを際立たせる
  • キャプションとナレーションの整合: キャプションテキストはナレーション内容と一致させる(数値の%表記も統一)

Part 4: Storyboard(絵コンテ作成)

4.1 シーン分割表

以下のテンプレートで全シーンを定義してから実装に入る:

Scene秒数Beat数参考クリップ演出概要コンポーネント名
012.915{clip_id}ロゴ blur→focus + パーティクルLogoFocusIn
022.915{clip_id}バリュー訴求パンチインValuePunch
035.249{clip_id}メンバー紹介ワイプMemberShowcase
...

4.2 Props インターフェース設計

interface CompositionProps {
  // 全シーン共通
  bgmSrc?: string;
  sectionDurations?: number[];  // Beat-aligned

  // シーン固有 props
  logoSrc?: string;
  // ...
}

export const DEFAULT_PROPS: CompositionProps = {
  sectionDurations: [2.91, 2.91, 5.24, 5.24, 12.23, 6.99, 8.74], // BPM倍数
  bgmSrc: '{project}/audio/bgm.mp3',
  // ...
};

4.3 sectionDurations 優先

sectionDurations 配列を先に確定 → 各シーンコンポーネントはフレーム数を受け取って内部で配分。Root.tsx の durationInFrames は Math.round(sum(sectionDurations) * FPS) で自動計算。


Part 5: Implementation Patterns(Remotion テクニック集)

企業PV制作で確立した 13 のテクニック。新プロジェクトでもそのまま適用可能。

P1: Blur→Focus ロゴ

const blurPx = interpolate(frame, [0, 20], [20, 0], { extrapolateRight: 'clamp' });
// style: { filter: `blur(${blurPx}px)` }

ロゴ画像を最初ぼかして徐々にシャープに。テキストでロゴを再現しない(フォント不一致リスク)。

P2: パンチインテキスト

const scale = spring({ frame: f, fps, config: { damping: 12, mass: 0.5, stiffness: 200 } });
// style: { transform: `scale(${scale})`, opacity: Math.min(1, f / 5) }

テキストが弾むように出現。damping を低くしすぎると振動が目立つので 10-15 が適正。

P3: clipPath ワイプ

const progress = interpolate(frame, [startF, endF], [0, 100], { extrapolateRight: 'clamp' });
// style: { clipPath: `inset(0 ${100 - progress}% 0 0)` }

右→左に写真がワイプイン。方向は inset() の値を変えるだけ。

P4: 矩形飛散→写真ワイプ

暗背景にランダム配置の白/色付き矩形を散らし、clipPath で写真を露出させる二段階演出。

// Phase A: 矩形飛散(テキストは入れない)
{rects.map((r, i) => (
  <div key={i} style={{
    position: 'absolute', top: r.y, left: r.x,
    width: r.w, height: r.h, background: r.color,
    transform: `rotate(${r.rot}deg)`,
    opacity: interpolate(f, [0, phaseAEnd], [1, 0])
  }} />
))}
// Phase B: clipPath で写真ワイプ

P5: 3ストリップ分割

画面を縦3分割し、各ストリップに異なるアングルの写真を配置。ストリップごとに微妙にタイミングをずらすとリッチに見える。

P6: Apple風カードグリッド

const scrollY = interpolate(frame, [0, dur], [0, -totalHeight], { extrapolateRight: 'clamp' });
// グリッドを translateY でスクロール
// 特定カードでデセラレーション → カーソル追従 → クリック演出

カーソル位置はスクロールオフセットからカードの実画面座標を逆算して合わせる。

P7: 4パネルスタガー

const panelDelay = panelIndex * 4; // フレーム単位のずらし
const slideIn = interpolate(frame - panelDelay, [0, 15], [100, 0], { extrapolateRight: 'clamp' });
// 各パネルの baseOffset で異なる画像を表示
const imgIdx = (cycleIndex + pi * Math.ceil(images.length / 4)) % images.length;

4分割パネルの更新タイミングをずらす。全パネル同じ画像にならないよう baseOffset 必須。

P8: カウントアップ

// spring() は振動するので絶対使わない
const eased = 1 - Math.pow(1 - ratio, 3); // cubic ease-out
const displayNum = Math.round(eased * targetNumber);

spring() でカウントアップすると数値が上がって下がって戻る。cubic ease-out を使うこと。

P9: CSS パーティクル

// i2v の代替。position:absolute + CSS animation で浮遊ドット
{particles.map((p, i) => (
  <div key={i} style={{
    position: 'absolute', borderRadius: '50%',
    width: p.size, height: p.size, background: p.color,
    top: `${p.y}%`, left: `${p.x}%`, opacity: p.opacity,
    animation: `float ${p.duration}s ease-in-out infinite`,
  }} />
))}

i2v(Kling等)は品質が微妙 → CSS パーティクルやRemotionアニメーションで代替する。

P10: SceneWrap exit

const exitProgress = interpolate(frame, [dur - exitFrames, dur], [0, 1], { extrapolateLeft: 'clamp' });
// style: { transform: `scale(${1 - 0.05 * exitProgress})`, opacity: 1 - exitProgress }

シーン終了時に scale: 0.95 + opacity: 0 で自然に次シーンへ遷移。noExit prop で無効化可能。

P11: 顔保護

// objectFit: "cover" は顔が切れる → "contain" + blurred background
<div style={{ position: 'relative', overflow: 'hidden' }}>
  {/* ブラー背景 */}
  <Img src={src} style={{ position: 'absolute', width: '120%', filter: 'blur(20px)', objectFit: 'cover' }} />
  {/* メイン画像 */}
  <Img src={src} style={{ position: 'relative', objectFit: 'contain', width: '100%', height: '100%' }} />
</div>

P12: テキスト可読性

// 黒帯はダサい → text-shadow で可読性確保
style: {
  textShadow: '0 2px 8px rgba(0,0,0,0.8), 0 0 20px rgba(0,0,0,0.5), 0 0 40px rgba(0,0,0,0.3)',
  // フォントサイズは大きめに(最低 48px)
}

P13: 動画直挿入

import { OffthreadVideo } from 'remotion';
// <OffthreadVideo src={staticFile('{project}/video/live_muted.mp4')} muted />

ライブ映像等は muted で挿入し、BGM トラックと干渉させない。サムネイルは ffmpeg で事前抽出:

ffmpeg -i video.mp4 -ss 5 -frames:v 1 thumb.jpg

Part 6: Comparison Loop(比較改善ループ)

6.1 レンダリング

cd mv-composer
npx remotion render src/index.ts {CompositionId} out/{Name}_v{N}.mp4

6.2 出力動画のフレーム抽出

ffmpeg -i out/{Name}_v{N}.mp4 -vf "fps=8" data/video_refs/{project}/output_frames/v{N}_%04d.png

6.3 比較分析

参考動画フレームと出力フレームを並べて、プロの映像クリエイター視点 で以下をチェック:

  • タイミングのズレ(フレーム単位で比較)
  • イージングの質(機械的 vs 有機的)
  • 色温度・コントラストの差
  • テキストの級数・配置・可読性
  • 画像のクロップ・アスペクト比(顔切れ)
  • BGM 同期ポイントのズレ
  • 「死んでるフレーム」(動きのない静止区間 0.5秒以上)
  • シーン間の黒フレーム(意図しない暗転)
  • 重複表示(同じテキスト/画像が2回出る等)

6.4 修正→再レンダリング

指摘事項を修正 → v{N+1} としてレンダリング → 再度比較。 v1→v18 のような反復は正常。5-10回のイテレーションで収束するのが標準。


Part 7: Lessons Learned(禁止事項・推奨事項)

禁止

ルール理由
絵文字をアイコンに使わないレンダリング環境でフォント欠落 → SVG/画像を使う
i2v(Kling/fal.ai等)に頼らない品質が微妙、Remotion CSS で代替可能
spring() でカウントアップしない振動して数値が上がって下がる
objectFit "cover" で人物写真顔が切れる → "contain" + blurred bg
黒帯テロップダサい → text-shadow で可読性確保
7MB超の画像をそのまま使うデコードエラー → sips --resampleWidth 1200
テキストでロゴを再現フォント不一致 → ロゴ画像を使う

推奨

ルール理由
SE なし・BGM 一本駆け抜ける勢いが出る
sectionDurations を BPM 倍数に音ハメが自然になる
画像は 1200px 幅以下にリサイズRemotion のデコード安定性
シーン間を ±5フレーム オーバーラップ黒フレーム防止
名前テロップは1シーン1回2回出ると違和感
パネル画像は baseOffset で分散全パネル同じ画像防止
ライブ映像は muted 挿入BGM との干渉防止
ブランドカラーは OGP/公式サイトから取得目視推定は不正確

ワークフロー全体像

[1. Reference Research]
  ↓ 参考クリップ収集(5-10秒単位)
[2. Frame Analysis]
  ↓ フレーム抽出 → 演出分解
[3. BPM & Audio]
  ↓ テンポ解析 → sectionDurations 確定 → BGM 生成
[4. Storyboard]
  ↓ シーン分割表 → Props設計
[5. Implementation]
  ↓ パターン集(P1-P13)を活用して実装
[6. Comparison Loop]  ←─── 5-10回反復
  ↓ レンダリング → フレーム比較 → 修正
[7. Final Check]
  ↓ Lessons Learned チェック → 完成

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

ab-test-setup

無料日本語概要

A/Bテストや実験の設計・実装を支援するスキル。 「A/Bテストを設計して」「スプリットテストしたい」「仮説を立ててテストしたい」「バリアントを比較」等のリクエストで発動。 トラッキング実装は analytics-tracking を参照。

minicoohei/ai-agent-camp3472026年10月7日 更新

agent-designer

無料日本語概要

マルチエージェントシステムのアーキテクチャ設計ツールキット。 「エージェントを設計して」「マルチエージェント構成」「エージェントのアーキテクチャ」「オーケストレーション設計」等のリクエストで発動。

minicoohei/ai-agent-camp3472026年10月7日 更新

aiagent-check-setup

無料日本語概要

ai-agent-campのローカル環境セットアップを確認するスキル。 「セットアップ確認」「環境チェック」「初期設定できてる?」「インストール確認」「依存関係チェック」等のリクエストで発動。

minicoohei/ai-agent-camp3472026年10月7日 更新

aiagent-command-router

無料日本語概要

ai-agent-campのスラッシュコマンドをCodexでルーティングするスキル。 「/start-0-1を実行」「スラッシュコマンドを使いたい」「コマンドルーティング」「Cursorのコマンドを使いたい」等のリクエストで発動。

minicoohei/ai-agent-camp3472026年10月7日 更新

aiagent-env-manager

無料日本語概要

ai-agent-campの環境変数・認証情報を安全に管理するスキル。 「APIキーを設定」「.envを管理」「環境変数の設定」「credential managerを使いたい」「秘密情報の管理」等のリクエストで発動。

minicoohei/ai-agent-camp3472026年10月7日 更新

aiagent-guide

無料日本語概要

ai-agent-campリポジトリの案内・オリエンテーションスキル。 「リポジトリ案内」「次のレッスンは?」「どこから始める」「ツールの違い」「aiagent概要」等のリクエストで発動。

minicoohei/ai-agent-camp3472026年10月7日 更新

minicoohei のスキルをすべて見る

このスキルの問題を報告する