p5-paint-animation について
p5-paint-animationは、p5で文字、写真、短い動画を手描き風のアニメーションにするスキルです。文字の描画、写真の絵画化、動画の動く絵画化という3つの手順があり、PNGまたはMP4をオフラインで出力します。
主な機能
- 01罫線上に文字を描くアニメーション
- 02写真の静止画・動画化
- 03動画を動く絵画としてレンダー
- 04スタイル・細部・シードの調整
- 05オフラインでPNG・MP4出力
活用シーン
- 01文字が書かれていく映像の制作
- 02ポートレートを描画アニメーションにする
- 03短い動画を筆致のある絵画風にする
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ heygen-com/ hyperframes-community-skills --skill p5-paint-animationインストール後、Claude Code で/p5-paint-animationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/flows.mdgotchas.mdscripts/package-lock.jsonpackage.jsonrender-anim.mjsrender-video.mjsrender.mjssetup.shscripts/lib/inject.mjspage-safety.mjsscripts/sketches/handwriting.anim.jsrepaint-video.jsrepaint.anim.js詳細
p5 Paint Animation
3つのフロー、1つのエンジン。入力に応じて選択します。
| 入力 | フロー | 出力 |
|---|---|---|
| テキストプロンプト/フレーズ | A:書き込みアニメーション | 罫線入りの紙に手書き文字が現れ、ペンの動きを追跡してカメラに反映します |
| 写真 | B:描き直し+描画アニメーション | 筆致のある絵画。静止画、または絵そのものが描かれていく動画。カメラが引きます |
| 動画/Live Photo | C:動く絵画 | 固定された筆致の格子に沿って、各フレームを描き直します |
使用する場合/しない場合
次の用途に使用します:手作りのような動き。文字が自動で書かれるアニメーション、筆致のある絵画にした写真(静止画またはアニメーション)、動く絵画のような短いクリップ。 次の用途には使用しないでください:鮮明なタイポグラフィやブランドに忠実なテキスト(実際のフォントを使用してください)、フォトリアルな出力、約10秒を超える映像(レンダリングコストはフレームごとに約5~20秒かかり、長さに比例します)、ライブ/インタラクティブなページ(オフラインでMP4/PNGをレンダリングします)。
要件と副作用
- 必要なもの:Node 22.12以降、PATH上のffmpeg、約500MBのディスク容量(Chromium用)。
sh scripts/setup.sh(手動で一度実行)は、コミット済みのロックファイルを使ってnpmレジストリから固定バージョンの依存関係をダウンロードします:puppeteer 25.9.0、p5 2.3.2(LGPL-2.1)、p5.brush 2.2.1(MIT)。Puppeteerは固定バージョンのChrome for TestingビルドをGoogleのダウンロードサービスからダウンロードします。ダウンロードは読み取り専用です。認証情報は不要で、費用はかからず、何もアップロードされません。- レンダリングでは、空白のページ上でサンドボックス化されたヘッドレスChromiumを起動します。スケッチからのネットワークアクセスとローカルファイルへのリクエストはブロックされます。スケッチには入力がデータURLとして渡されます。
- 書き込み先は指定したパスのみです(
out.png/out.mp4に加えて、同じ場所に.track.json、さらに--keep-frames 1を指定した場合は_frames_*ディレクトリ)。 - オプション。フローCの被写体のマッティングにのみ使用します:
npx hyperframes remove-background(HyperFrames CLIをnpmからダウンロードします。ローカルでCoreML推論を行い、データがマシンの外に出ることはありません)。
成功の確認
以下のいずれかのコマンドでレンダリングし、出力を開いて確認します。最後のフレームに作品全体が表示されている必要があります(テキストがすべて書き終わっている/絵が全体に描かれている)。また、同じ--seedで再実行すると、キャンバス上のバイト列が同一になる必要があります。レビューで使用したスモークテスト:node render-anim.mjs sketches/handwriting.anim.js /tmp/t.mp4 --size 1600x900 --seed 7 --inject 'PHRASE="go make something"'。
セットアップ(一度だけ)
sh scripts/setup.sh
scripts/package-lock.jsonに記録された正確な依存関係ツリーをインストールします。
以下のコマンドはすべてscripts/から実行します。
フローA — プロンプト → 書き込みアニメーション
node render-anim.mjs sketches/handwriting.anim.js out.mp4 \
--size 1600x900 --fps 24 --seed 7 --hold 12 \
--inject 'PHRASE="your text here";SIZE=170'
- アルファベット全体に対応します:小文字、大文字、数字、
? . , - / @。自動で折り返します。 --injectで調整できます:SIZE、INK(16進数)、BRUSH("2B"は鉛筆、"crayon"、"charcoal")、白紙の場合はPAPER=1。- 実行すると、フレームごとのペンの位置を記録した
out.track.jsonが書き出されます。カメラをペンに追従させるには、平滑化したトラックに沿って各フレームをクロップします(指数追従、ゲイン約0.14。カメラのy座標はベースラインに固定します。ペン先のy座標を追わせると、文字の上部に合わせてカメラが毎回跳ねてしまいます)。 - 文字をかすれさせたり乱雑にしたりするには、スケッチで文字ごとのジッターを大きくします。ナレーションの音声に単語を同期させるには、まず文字起こしを行い、各単語の筆跡をその単語が発話される時刻に合わせて開始します。
フロー B — 写真 → 絵画(+描画フィルム+カメラ)
静止画:
node render.mjs sketches/repaint.anim.js out.png \
--size 720x900 --seed 3 --image photo.jpg --inject "STYLE=0;DETAIL=3"
描画フィルム(絵画が自ら描き上がる仕組みです。粗い描写から細かい描写へ、落ち着いた領域から先に描き、最後に顔を描きます):
node render-anim.mjs sketches/repaint.anim.js out.mp4 \
--size 720x900 --seed 3 --image photo.jpg --fps 14 --hold 40 \
--inject 'STYLE=0;DETAIL=3;SUBJECT="0.5,0.5,0.44,0.55"'
- まず被写体に合わせてトリミングします。 フレーム内の顔の大きさが仕上がりを左右します。自撮り距離の顔は美しく描写され、小さな顔は人物として描かれます。ポートレートは 4:5 または 9:16 にします。
- ダイヤル:
STYLEは 0 がパステル、1 がガッシュ、2 が木炭スケッチです。DETAILは 1 が絵画的、2 が顔を描写、3 が柔らかな顔立ち(鼻など)、5 がポートレート品質(細かい描画パスをもう 1 回追加)です。LOOSEは 0.7~1.5 でストロークの奔放さを調整します。SATは色補正(約 1.1)です。 SUBJECT="cx,cy,rx,ry"(画像に対する割合)を指定すると、すべてのパスで最初にその楕円内をすべて描画し、subject-doneのフレームマーカーを出力します。カメラを引くレシピ:被写体をタイトに映し、マーカーフレームで ffmpeg zoompan を使って滑らかに引きます(コサインイージング、約 2 秒)。zoompan=z='if(lte(in,M),1.9,1.85-0.85*(0.5-0.5*cos(PI*min((in-M)/28,1))))'(タイトな状態でもシャープさを保つため、最初に lanczos で 2 倍にアップスケールします)。
フロー C — 動画/Live Photo → 生きた絵画
node render-video.mjs clip.mov out.mp4 \
--size 720x900 --fps 12 --seed 7 --inject "STYLE=0;DETAIL=2"
- ストロークの格子はフレーム 1 から一度だけ生成して固定します。フレームごとに再サンプリングされるのは色と向きだけです。被写体が動いてもストロークは静止し、絵画が「沸き立つ」ことはありません。
- Live Photos: ペアになった
.movを取得します(共有シートの「オプション」→「Live Photo」をオンにするか、Photos.app →「未変更のオリジナルを書き出す」を選びます)。JPEG のみで届いた場合、転送中にモーションが削除されています。代わりに 2~3 秒の通常の動画を依頼してください。こちらのほうが入力としても適しています。 - まずモーションをトリアージします。 Live Photos にはスマートフォンを振る動きが含まれています。フレームごとのモーションを測定し(
ffprobe -f lavfi "movie=in.mov,signalstats"→ YDIF)、落ち着いた区間だけを--start/--durで描画し、結果をピンポン再生(順方向+逆方向を連結)して、シームレスに息づくループにします。 - カメラの動きが大きい場合:
WORLD=1は画像相関でカメラを追跡し、ストロークをワールド座標上に配置します。カメラが 1 枚の成長していく絵画の上をパンするようになります。対応するのは平行移動のみです。高速ズームではずれが生じます。 - 被写体だけを描画する場合:まずマットフレームを作成し(
npx hyperframes remove-background)、マット処理済み PNG を--frames DIRとMASKED=1で渡し、BGに紙の色を設定します。 - 暗い映像:ガンマのみでグレーディングします(
eq=gamma=1.2)。描画前に彩度を上げないでください。シャドウのクロマノイズが、そのままティール色の絵の具になります。
QC ゲート(すべてのフロー)
- 実際の出力フレームを確認し、意図だけで納品しないでください。確認項目:顔が描写されていること、キャンバスのむき出し部分がないこと、最初・中間・最後のフレームに一貫性があること。
- 同じシードならレンダリング結果も同一になります。固定シードで、一度に 1 つのダイヤルだけを変更して反復します。
- 大きな映像に組み込む場合は、モーションドクトリンに従って継ぎ目を数値で検証してください。このスキルが生成するのは素材であり、最終的な文法ではありません。
references/flows.md には完全な手順例があり、references/gotchas.md には既知の失敗パターンがまとめられています。同じ失敗を繰り返さないために参照してください。