Communitygithub.com

erencalik/motion-graphics-video-generator-claude

1回のリクエストから、アニメーション付きMP4モーショングラフィックス動画を生成します。HTML/CSS/JSアニメーションをフレームごとにレンダリングし、ffmpegで結合することで、9:16のリールや16:9の動画を音楽付きで作成できます。

motion-graphics-video-generator-claude とは?

Motion Graphics Video スキルは、Claudeのコード実行環境内で、編集ソフトやストック動画を一切使わずに、エンドツーエンドでMP4動画を生成するツールです。主な用途は、モーショングラフィックス、キネティックタイポグラフィ、アニメーション統計、リール動画です。仕組みとしては、まずアニメーションを1つのHTMLページとして記述し、すべての要素の位置や色、不透明度をフレーム番号から計算します。次に、Headless Chrome(Playwright)を使って全フレームをキャプチャし、ffmpegでMP4に変換。さらに、コードで音楽を合成し、動画に追加します。対応プラットフォームは、Claude.ai(コード実行とファイル作成を有効にする必要があります)と Claude Code で、ユーザーがアップロードしたロゴや画像、フォントなども利用できます。スキルは、シーンプランの作成、HTMLテンプレートの生成、フレームキャプチャ、音楽合成、最終的な動画結合という一連の手順を自動化し、高速なプロトタイピングを可能にします。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/erencalik/motion-graphics-video-generator-claude/tree/HEAD

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

モーショングラフィックス動画

編集ソフトやストック動画を一切使わずに、Claudeのコード環境内でエンドツーエンドにMP4を生成します。コード実行とファイル作成が必要です(claude.aiの場合:設定 > 機能)。ブランド動画の場合は、ロゴ、写真、色、フォントをアップロードするか、ブランドスタイルファイルを指定してください。ユーザーの言語で応答します。

仕組み

  1. アニメーションは1つのHTMLページとして記述されます。すべての要素の位置、サイズ、色、不透明度はフレーム番号から計算されます(window.renderFrame(f))。CSSトランジション、setTimeout、requestAnimationFrameは使用しません。これにより、レンダリングが決定論的になります。
  2. Headless Chrome(Playwright)がすべてのフレームをキャプチャします。20秒×60fps = 1,200フレーム。
  3. ffmpegがフレームをMP4(H.264、yuv420p)に変換します。
  4. 音楽はコード内で合成され、トランジションに合わせてタイミングが調整され、動画に追加されます。

リクエストチェックリスト(不足しているものがあれば1回尋ねます)

  1. 長さ: 15〜20秒が理想的です。
  2. フォーマット: Reel/TikTok/Shortsには9:16(1080x1920)、YouTube/ポートフォリオには16:9(1920x1080)。
  3. 素材: Webサイト、アップロードした写真、ロゴ、または何もなし。
  4. スタイル: 技法を指定してください。キネティックタイポグラフィ、アニメーションインフォグラフィック/統計、パーティクル、ハーフトーン、マップ/地形図、カウンター、タイムラインなど。技法を指定すると、より確実な結果が得られます。
  5. ルールと除外事項: 合わせる色、除外するもの(例:価格、余分なテキスト)。
  6. 野心度: ユーザーが「最善を尽くして」と言った場合、Claudeがコンセプト、パレット、音楽を自ら選択し、大胆に進めます。

ストーリーリール用の既製構造:ロゴ/フックのイントロ(0〜2秒)→ キネティックタイプのストーリー文 → カウンターで増加する数字 → タイムラインまたはマップ → クロージングカード(アカウントハンドル)。画面上のテキストはリールのセーフエリア内(上部210px、下部310px、右側84pxはクリア)に配置してください。数字と日付は情報源を明示する必要があります。架空の数字をアニメーション化しないでください。

制作手順

  1. 秒単位のシーンプランを書き、表示します(表:時間 | 画面の内容 | トランジション | オーディオヒット)。
  2. scene.htmlを記述します。ルール:固定ピクセルサイズ、window.TOTAL(総フレーム数)とwindow.renderFrame(f)を定義。イージング関数で補間。フォントはbase64のwoff2として埋め込み(環境がGoogle Fontsにアクセスできない可能性があります)、画像もbase64として埋め込みます。
  3. 最初に3〜4フレームのPNGをキャプチャし、自分で検査します(テキストのはみ出し、誤ったフォント、空フレームなど)。その後、フルレンダリングを実行します。
  4. audio.pyで音楽を合成。シーントランジションにヒットを配置します。ユーザーが自分の音楽をアップロードした場合は、それを使用します。
  5. 結合し、ffprobeで長さ/解像度を確認し、中間フレームを視覚的にチェックして、MP4を納品します。

レンダリング時間:20秒、60fpsの場合、約8〜10分かかります。クイックドラフトには30fps、最終版には60fpsを使用してください。修正リクエストはタイムコードで受け付けます(「0:07のカウンターを遅くして」など)。

テンプレート(テスト済み、このSKILL.mdと一緒にファイルとしても提供されます)

scene.html(スケルトン)

<!doctype html><html><head><meta charset="utf-8"><style>
html,body{margin:0;width:1080px;height:1920px;overflow:hidden;background:#0E0E10;font-family:'Montserrat',Arial,sans-serif}
#s{position:relative;width:1080px;height:1920px}
.t{position:absolute;left:90px;right:90px;color:#F5F1E8;font-weight:800;line-height:1.05}
</style></head><body><div id="s">
<div class="t" id="a" style="top:520px;font-size:120px">5,126</div>
<div class="t" id="b" style="top:680px;font-size:64px;color:#FF5A1F">FAILED PROTOTYPES</div>
</div><script>
const FPS=30,DUR=3;window.TOTAL=FPS*DUR;
const clamp=(x,a=0,b=1)=>Math.min(b,Math.max(a,x));
const easeOut=t=>1-Math.pow(1-t,3);
window.renderFrame=f=>{const t=f/FPS;
 const p=easeOut(clamp(t/0.6));a.style.opacity=p;a.style.transform=`translateY(${(1-p)*80}px)`;
 a.textContent=Math.round(5126*easeOut(clamp(t/1.5))).toLocaleString('en-US');
 const q=easeOut(clamp((t-0.8)/0.5));b.style.opacity=q;b.style.transform=`scale(${0.8+0.2*q})`;};
</script></body></html>

render.js: node render.js scene.html video.mp4 30(Playwrightがない場合:npm i playwright && npx playwright install chromium。それができない場合は、Python Playwrightで同じループを構築してください)

// node render.js scene.html out.mp4 [fps]
const {chromium}=require('playwright');const {spawn}=require('child_process');const path=require('path');
(async()=>{const [,,html,out,fpsArg]=process.argv;const fps=+(fpsArg||30);
const b=await chromium.launch();const p=await b.newPage({viewport:{width:1080,height:1920}});
await p.goto('file://'+path.resolve(html));await p.evaluate(()=>document.fonts.ready);
const total=await p.evaluate(()=>window.TOTAL);
const ff=spawn('ffmpeg',['-y','-f','image2pipe','-framerate',String(fps),'-i','-','-c:v','libx264','-pix_fmt','yuv420p','-crf','18','-preset','medium',out],{stdio:['pipe','inherit','inherit']});
for(let f=0;f<total;f++){await p.evaluate(f=>window.renderFrame(f),f);ff.stdin.write(await p.screenshot({type:'jpeg',quality:92}));}
ff.stdin.end();await new Promise(r=>ff.on('close',r));await b.close();console.log('frames',total);})();

16:9の場合は、ビューポートとページサイズを1920x1080に変更してください。

audio.py: python3 audio.py music.wav <秒数>(numpy合成:パッド+ヒット)

# python3 audio.py music.wav 3   -> 合成されたパッド+ヒット
import sys,wave,numpy as np
out,dur=sys.argv[1],float(sys.argv[2]);sr=44100;t=np.arange(int(sr*dur))/sr
pad=sum(np.sin(2*np.pi*f*t) for f in (110,164.8,220))*0.08*np.minimum(1,t/0.5)
def hit(at,f0=60):
    x=np.zeros_like(t);m=t>=at;tt=t[m]-at;x[m]=np.sin(2*np.pi*f0*tt*(1+3*np.exp(-tt*30)))*np.exp(-tt*8)*0.6;return x
y=pad+hit(0.0)+hit(0.8,90)
y=y/np.max(np.abs(y))*0.8;fade=np.minimum(1,(dur-t)/0.4);y*=fade
w=wave.open(out,'wb');w.setnchannels(1);w.setsampwidth(2);w.setframerate(sr);w.writeframes((y*32767).astype(np.int16).tobytes());w.close()

結合

ffmpeg -y -i video.mp4 -i music.wav -c:v copy -c:a aac -b:a 192k -shortest final.mp4

制限事項

  • 写真にエフェクトを適用できます(パーティクル、ハーフトーン、切り抜き)。人物をアニメーション化したり、リップシンクを行うことはできません(その場合は専用のアバター/動画モデルを使用してください)。
  • 合成音楽は電子音楽です。本物の楽器やボーカルが必要な場合は、オーディオファイルをアップロードしてください。
  • ユーザーが所有していない著作権で保護されたキャラクターやロゴは使用できません。実際の企業ロゴは、ニュースや解説の文脈でのみ、出典を明示した場合に限り使用可能です。

クレジット:Michael Ly氏のガイド「How to Generate Motion Graphics Videos with Claude」(milleemd.com/guides/motion-graphics-videos)の手法に基づいています。コードテンプレートはこのスキル用に作成されました。

関連スキル