mcpField
C
cavalry

cavalry

github.com/jablonkaiクリエイティブ・メディア447 回インストール今日更新
リポジトリ

cavalry について

JavaScript スクリプトと Cavalry Bridge を使って、アニメーションソフトウェア Cavalry を操作するスキルです。API のパターンとヘルパースクリプトでシーンを作成・確認・レンダリングし、プレビューを反復できます。

主な機能

  1. 01JavaScript による Cavalry 操作
  2. 02API ヘルパーでのシーン作成
  3. 03キーフレームとイージングの設定
  4. 04レンダーとシーンデータの確認
  5. 05PNG フレーム列のレンダリング

活用シーン

  1. 01アニメーションシーンの作成
  2. 02テキストや図形のアニメーション
  3. 03コンポジションのプレビューと修正
  4. 04フレーム列のレンダリング

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jablonkai/skills --skill cavalry

インストール後、Claude Code で/cavalryを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api-reference.md
references/cavalry-types/
deformer.d.ts
emitter.d.ts
LICENSE
modifier.d.ts
plugin.d.ts
README.md
render.d.ts
script.d.ts
shape.d.ts
utility.d.ts
references/cavalry-types/namespaces/
api.d.ts
cavalry.d.ts
console.d.ts
ctx.d.ts
def.d.ts
install.d.ts
plugin.d.ts
render.d.ts
ui.d.ts
scripts/
cavalry-bridge.js
cavalry-helpers.js
cavalry-send.sh

詳細

Cavalry Control

Cavalry(/Applications/Cavalry.app)は JavaScript でスクリプトを記述できます(2.6 以降は V8 12.4 なので ES2024 に対応しており、let/const、アロー関数、Set メソッドがすべて動作します。api.*/ui.*/cavalry.* モジュールを使用します)。Cavalry Bridge を介して操作します。これは Cavalry 内で動作する小さなスクリプト UI で、127.0.0.1:8731 に POST された内容を実行します。以下の内容はすべて、実際のプロジェクトで Cavalry 2.7.2(2026 年 5 月時点の最新リリース)を使って検証済みです。その他の API の詳細についてはリファレンスファイルを参照してください。

2.7 以降、Cavalry は Canva の傘下にあります。サインインには Canva アカウントを使用し、以前は Professional 向けだった機能はすべてのユーザーに無料で提供されます。そのため、ライセンスの区分を前提に計画しないでください。唯一の注意点は、CLI が 2.7.x に同梱されていないことです(「レンダリング」を参照)。

  • references/api-reference.md — モジュール(api、cavalry、ui、WebClient/WebServer、レンダースクリプト、CLI)の要約リファレンスです。以下のチートシートにない機能が必要な場合に参照してください。
  • references/cavalry-types/ — JSDoc の例を含む TypeScript 定義として収録された完全な API です。リファレンスに記載のない関数は、こちらを grep してください。
  • scripts/cavalry-bridge.js — Cavalry にインストールするブリッジです。
  • scripts/cavalry-helpers.js — setAttrs/keyAttrs(エラーを黙って無視せず、明確に通知しながら設定やキーフレーム化を行います)、newComp/useComp/findComp、splitLetters(文字単位のテキスト)、renderFrames、writeJSON を提供します。各ビルドスクリプトの先頭で api.load("<abs path>/scripts/cavalry-helpers.js") を実行して読み込んでください。
  • scripts/cavalry-send.sh — JS ファイル(または -c 'inline code')をブリッジに送信し、完了まで待機します。失敗時はゼロ以外の終了コードを返し、JS エラーを表示します。--ping を指定するとブリッジへの接続を確認し、ブリッジと Cavalry のバージョンを報告します。

制御ループ

  1. ユーザーがブリッジを起動します(セッションごとに一度):Cavalry を起動し、Scripts メニューから Cavalry Bridge.js を起動しておく必要があります。これはリモートでは実行できません。bash scripts/cavalry-send.sh --ping に応答がない場合は、ユーザーに Cavalry を開き、Scripts ▸ Cavalry Bridge を実行するよう依頼してください。ブリッジを初めてインストールするには、scripts/cavalry-bridge.js を Cavalry の Scripts フォルダーに Cavalry Bridge.js としてコピーします(~/Library/Application Support/Cavalry/Scripts/ — 存在しない場合は作成してください。Help ▸ Show Scripts Folder でパスを確認できます)。--ping の応答に "version" フィールドがない場合は、古いブリッジが実行されています。現在のブリッジで上書きして、再起動してください。
  2. ビルドスクリプトをスクラッチパッドに書き、送信します:bash scripts/cavalry-send.sh /path/to/build.js。各送信にはリクエスト ID が割り当てられ、ユーザーの Cavalry 環境設定フォルダー(ブリッジの GET /get 応答から特定)にある専用の結果ファイルを待ち受けます。そのため、複数の呼び出し元が一つのブリッジを安全に共有できます。長時間のレンダリングには CAVALRY_SEND_TIMEOUT=600(秒)を設定します。
  3. フィードバックは HTTP ではなくファイル経由で返されます。 ブリッジは、成功/失敗に加えて、スローされたエラーの例外メッセージとスタックを報告します。console.log の出力は Cavalry の Log ウィンドウに表示されます。そのため、スクリプトの結果を読み取れるよう、すべてのスクリプトで結果をディスクに書き込む必要があります。
    • 視覚的な状態 → 重要なフレームで api.setFrame(f); api.renderPNGFrame(dir + "/check_" + f, 50) を実行します(50 = 50% スケールのプレビュー)。その後 PNG を読み込みます。レンダリングはビルド後の別の送信で行ってください。スクリプト内で作成した接続(デフォーマーやスタッガーなど)はスクリプトが返るまで評価されないため、同じ送信内のプレビューは正しくないことがあります。
    • データ(ID、バウンディングボックス、属性値)→ api.writeToFile(path, JSON.stringify(x), true)。
  4. 反復します:プレビューを確認し、スクリプトを修正して再送信します。ビルドスクリプトは再実行できるようにしてください。バージョンごとに新しいコンプ(api.createComp("Thing v2"))を作成し、再実行時に古いコンプへレイヤーが積み重ならないようにします。アクティブなコンプは UI で共有される状態であり、ユーザーや別の呼び出し元が送信の合間に変更する可能性があります。そのため、後続の送信でレンダリングまたは編集を行うスクリプトでは、まずコンプ名で検索してください。ヘルパーの useComp("Thing v2") を使います。
  5. 最終レンダリング:PNG フレームのループ + ffmpeg(下記の「レンダリング」を参照)。

送信に失敗すると、標準エラー出力に Cavalry error: <message + stack> が表示されます。行番号は送信したスクリプトと一致します。メッセージなしで失敗した場合は、構文エラー(スクリプトが開始されなかった)か、権限確認ダイアログで拒否された可能性があります。node --check build.js で確認し、Cavalry に開いたダイアログがないかユーザーに確認してもらってください。レンダリング中にタイムアウトした場合、通常は単にレンダリングに時間がかかっています。再送信するとレンダリングが二重に実行されるため、再送信せずにタイムアウトを延長してください。

シーン構築のチートシート(実証済みのパターン)

api.set はエラーを出しません — 名前を確認し、推測しないでください

api.set は、レイヤーに存在しない属性を黙って無視します。名前の誤記や古い Cavalry の属性名でも、何もせず送信は成功と報告されます。そのため、try/catch によるフォールバックの連鎖(「frameRate を試し、だめなら fps」)は役に立たないどころか逆効果です。最初の候補は常に「成功」してしまいます。ヘルパーの setAttrs(id, {...}) を使ってください(api.hasAttribute を確認し、属性名とレイヤーの種類を示してエラーをスローします)。確信が持てない場合は、api.getAttributes(id) で実際の名前を一覧表示してください。

コンプの設定
api.load("/abs/path/to/skills/cavalry/scripts/cavalry-helpers.js");
var comp = newComp("My animation v1", {width: 1920, height: 1080, fps: 30, frames: 240,
                                       background: "#121212"});   // or "transparent"

これは api.createComp + api.setActiveComp + resolution、fps、startFrame/endFrame(両端を含む — 240 フレームの場合は 0~239)、および backgroundColor を設定するものです。新しいコンプの背景はデフォルトで不透明です(ユーザーの環境設定が異なる場合を除き、白)。単色にするには backgroundColor を設定します。大きな BG 矩形は不要です。透明な出力にするには "#00000000"(アルファ 0)を設定します。

シェイプと属性
var rect = api.primitive("rectangle", "Bar");        // also: "ellipse", "polygon", "star"...
setAttrs(rect, {"generator.dimensions": [400, 60],   // rectangle: [w, h]
                "position": [0, 0],                  // origin = comp centre, +y = UP
                "material.materialColor": "#00ADEF"});
var dot = api.primitive("ellipse", "Dot");
setAttrs(dot, {"generator.radius": [20, 20]});        // ellipse: radius [rx, ry], not dimensions

よく使う属性パス:position [x,y]、position.x、scale.x/scale.y、rotation.z、 opacity、material.materialColor(16 進数文字列)、material.alpha(0~100 のスケール。値が ≤ 1 の場合、ほぼ見えません)、generator.dimensions(長方形)、generator.radius(楕円)。 名前を確認するには、api.getAttributes(id)、api.getAttributeDefinition(id, attr)(型、 デフォルト値、列挙値)を使うか、UI で属性を右クリックして Copy Scripting Path を選択します。

信頼できるサイズ設定:推測せずに測定する

テキストや読み込んだ画像には設定可能なサイズ属性がないため、実際のサイズを測定し、 scale で正規化します:

var bb = api.getBoundingBox(layer, true);          // world space: {x,y,width,height,left,right,top,bottom,centre}
var s = 470 / bb.height;                           // e.g. scale an image or title to 470 px tall
setAttrs(layer, {"scale.x": s, "scale.y": s});

ワールド空間では top > bottom です(+y は上方向)。scale のキーフレームを設定する前に測定してください。

キーフレームとイージング
api.keyframe(layer, 22, {"position.y": 940});
api.keyframe(layer, 50, {"position.y": 150});
api.magicEasing(layer, "position.y", 22, "BounceOut");   // easing is applied per-attr AT a keyframe

api.keyframe が受け取るのはスカラーのリーフ属性のみです。 配列 — {"position": [x, y]}、 {"generator.dimensions": [w, h]} — や、ベクトル属性に対する単独の数値 — {"rotation": 45}(rotation は 2.x 以降 x/y/z で、2D の回転は rotation.z)— を指定しても、 キーフレームは作成されず、エラーも発生しません。position.x/position.y、scale.x、rotation.z などを 直接キーにするか、ヘルパーの keyAttrs(id, frame, {...}) を使います。これは配列を分割し、単独の rotation を rotation.z に割り当て、未知の名前を拒否します。同様に、magicEasing にはリーフ属性名を指定します ("rotation" ではなく "rotation.z")。api.getKeyframeTimes(id, "position.x") でキーを確認してください。 (api.set はより柔軟で、配列と単独の rotation の数値をどちらも使えます。)

Magic easing のプリセット:SlowIn/SlowOut/SlowInSlowOut、VerySlowIn/VerySlowOut/VerySlowInVerySlowOut、 SpringIn/SpringOut/SpringInSpringOut、SmallSpring… の各バリアント、AnticipateIn、OvershootOut、 AnticipateInOvershootOut、BounceIn/BounceOut/BounceInBounceOut、None。 制作での使用例:ポップインするテキストには OvershootOut、落下や着地には BounceOut、 バースト(パーティクル、ほこり)には SlowOut、漂いやパルスには SlowInSlowOut を使います。

手軽なパーティクルバースト(パーティクルシステムは不要):小さな楕円を N 個作り、ひとつの原点から Math.cos/sin(angle) * dist で外側へキーフレーム移動させながら、scale を 0 にし、SlowOut を設定します。 完全な紙吹雪/火花のスニペットはリファレンスを参照してください。

テキスト — 1 文字ずつのアニメーションレシピ
var t = api.create("textShape", "Title");
setAttrs(t, {"text": "EMU 6-DAY RACE",
             "horizontalAlignment": 1, "verticalAlignment": 1,   // 1 = centre
             "fontSize": 150, "font.font": "Nebula Sans", "font.style": "Black",
             "material.materialColor": "#FFFFFF", "autoWidth": true, "autoHeight": true,
             "position": [0, -190]});

autoWidth を指定しないと、テキストボックス内で長い行が折り返されます。Unicode(アクセント記号、ő/ű)は そのまま使えます。フォントを使う前に確認してください:cavalry.fontExists(family, style)(両方の引数が必須) と cavalry.getFontStyles(family) を使い、Cavalry に黙って代替させず、存在するフォントに切り替えてください。

1 文字ずつのアニメーション(各字形を時間差で落下させる)では、テキストレイヤーを 1 つだけ使い、 Sub-Mesh デフォーマーと、その時間オフセットを制御する Stagger を接続します。Sub-Mesh のデフォルトは Level Mode が Text (Characters)(levelMode 3)なので、各字形には、stagger によってずらされた Sub-Mesh キーフレームのコピーが個別に適用されます:

var subMesh = api.create("subMesh", "Title bounce");
api.keyframe(subMesh, 34, {"shapePosition.y": 990});   // start above frame (+y = up)
api.keyframe(subMesh, 64, {"shapePosition.y": 0});
api.magicEasing(subMesh, "shapePosition.y", 34, "BounceOut");
api.connect(subMesh, "id", t, "deformers");
api.parent(subMesh, t);

var stagger = api.create("stagger", "Title stagger");
setAttrs(stagger, {"minimum": -12, "maximum": 0});     // frames of per-letter offset
api.flipGraph(stagger, "graph", "vertical");           // so the FIRST letter lands first
api.connect(stagger, "id", subMesh, "shapeTimeOffset");
api.parent(stagger, t);

別の送信でプレビューしてください。 Cavalry が新しい接続(デフォーマー、stagger、ビヘイビア)を評価するのは、 それらを作成したスクリプトが戻った後です。同じ送信内でレンダリングしたフレームではすべての文字が一緒に動き、 stagger が壊れているように見えます。1 回目の送信で作成し、次の送信で useComp(...) とレンダリングを実行してください。 同様に、api.get で取得した Sub-Mesh の値は stagger が適用されていません。1 文字ずつの動きは、レンダリングしたフレームでのみ確認できます。

各字形に個別のイージング、色、パスが必要な場合(またはスクリプトで行を再レイアウトする必要がある場合)は、 ヘルパーの splitLetters(str, style, cx, cy) を使うと、各字形のテキストレイヤーが 1 つずつ作成され、 文字列全体での正確な位置(カーニングを含む)に配置されます。それぞれ開始フレームを設定してキーフレームを作成します:

var letters = splitLetters("NIGHT RUN 2026",
    {"fontSize": 150, "font.font": "Helvetica", "font.style": "Bold",
     "material.materialColor": "#FFFFFF"}, 0, 40);          // line centred on [0, 40]
letters.forEach(function (id, i) {
    var y = api.get(id, "position.y"), f0 = 10 + i * 3;     // 3-frame stagger
    api.keyframe(id, f0, {"position.y": y + 700});
    api.keyframe(id, f0 + 20, {"position.y": y});
    api.magicEasing(id, "position.y", f0, "BounceOut");
});
画像とその他のアセット
var asset = api.loadAsset("/abs/path/logo.png", false);   // false = not an image sequence
var layer = api.addAssetToComp(asset);
var bb = api.getBoundingBox(layer, true);
var s = 470 / bb.height;                                  // scale to ~470px tall
setAttrs(layer, {"scale.x": s, "scale.y": s});

データ駆動型のシーンでは、api.jsonFromAsset(assetId) で JSON/CSV アセットを解析し、 api.loadGoogleSheet(spreadsheetId, sheetId) でライブのシートを取得し、 api.WebClient で任意の HTTP API からデータを取得できます。リファレンスを参照してください。

レンダリング

デフォルト:PNG フレームループ+ffmpeg。 ブリッジ以外に必要なものはなく、確認用のフレームを取得できます。ffmpeg はその後、自分のシェルから実行します。

api.load("/abs/path/to/skills/cavalry/scripts/cavalry-helpers.js");
useComp("My animation v1");
renderFrames(OUT, "name", 0, 239, 100);   // OUT/name_0000.png … name_0239.png

renderPNGFrame(pathWithoutExtension, scalePercent) は、アクティブなコンポの現在のフレームをレンダリングします。.png が追加され、表示されているレイヤーのみがレンダリングされます(ソロ状態も反映されます。api.soloLayers([]) で解除してください)。1080p で 240 フレームをレンダリングするには時間がかかるため、CAVALRY_SEND_TIMEOUT を大きくしてください。その後、次のように組み立てます。

ffmpeg -framerate 30 -i name_%04d.png -c:v libx264 -pix_fmt yuv420p out.mp4       # opaque
ffmpeg -framerate 30 -i name_%04d.png -c:v qtrle out.mov                          # alpha overlay

アルファ付きで出力するには、コンポの背景を透明にします(newComp(..., {background: "transparent"})、つまり backgroundColor を "#00000000" に設定)。デフォルトのままのコンポは、BG レイヤーがなくても不透明な白背景でレンダリングされます。すると PNG にアルファが含まれ、qtrle .mov はオーバーレイとして DaVinci Resolve にそのまま読み込めます(ProRes 4444 の -c:v prores_ks -profile:v 4 -pix_fmt yuva444p10le は、よりファイルサイズの小さい代替形式です)。次のコマンドで確認してください。 ffprobe -v error -show_entries stream=pix_fmt out.mov の結果は rgb24 ではなく、argb/rgba になるはずです。ffmpeg は api.runProcess 経由ではなく、シェルから実行してください。ブリッジなどのスクリプト UI から呼び出すと、「このスクリプトを信頼しますか」というダイアログが表示され、ユーザーが回答するまで処理が停止します。ベクタースナップショットには api.renderSVGFrame(path, scale, skipComps) を使用できます。

レンダーキュー(アプリ内):api.addRenderQueueItem(compId) → 設定 → api.render(itemId) または api.renderAll()。ネイティブの mp4/ProRes/GIF 出力や、複数のコンポまたはシーンの一括処理(ファイルごとに api.openScene(path, true))に便利です。レンダーキューアイテムには Setup/Pre/Post のレンダースクリプトを設定できます(レンダーごとにアセットやテキストを切り替えるなど)。リファレンスを参照してください。

Cavalry CLI — 2.7.x では利用できません。 Scene Group の 2.7.0~2.7.2 のリリースノートには、CLI が欠落している(「現在のバージョンを引き続きご利用ください……再導入に向けて作業中です」)と記載されています。また、2.7 より前のバージョンでは、render/list コマンドに Enterprise ライセンスが必要でした。2.7.2 バンドル内には今も CavalryCLI.app がありますが、その Contents/MacOS/ は空で、実行できるバイナリはありません。ヘッドレス形式で一括レンダリングする場合は、代わりにブリッジ経由で実行中のアプリを操作してください(各シーンを開き、レンダリングして、ffmpeg を実行します)。古いバージョンを使い続ける場合の 2.7 より前の CLI フラグについては、リファレンスを参照してください。

苦労して学んだ注意点

  • ブリッジは実行結果を返しません — すべてのスクリプトは、ファイルベースのフィードバック(ステータス JSON、プレビュー PNG、エラー記録ファイル)を前提に設計してください。console.log が見られるとは想定しないでください。
  • ブリッジは api.exec のコードを IIFE でラップします。そのため、トップレベルの var はそのまま使えますが、送信の間で値は保持されません。状態はシーンまたはディスクに保存してください。
  • api.set/api.keyframe はエラーを出さずに失敗します。認識されない名前はエラーなしで無視され、keyframe はベクトルに対する配列や単独の数値も無視します。setAttrs/keyAttrs を使用してください。このファイルにある名前は 2.7.2 で使用されているものです(fps、endFrame、text、backgroundColor)。frameRate/string/frameRangeEnd に関する以前の記述は、2.7 では誤りです。古いリリースでも動作するスクリプトが必要な場合は、api.getCavalryVersion() で分岐してください。
  • カラー:2.6 で Linear Gamma(コンポジション設定)と Color Filter シェーダーが削除されました。代わりに、Working Color Space を Linear sRGB に設定した Color Management を使用してください。
  • material.alpha は 0~100 であり、0~1 ではありません。
  • 新しいレイヤーはアクティブなコンポジションに追加されます。 api.create/api.primitive/addAssetToComp は、その時点でアクティブなコンポジションに追加します。何かを作成する前に、使い捨ての確認用スクリプトであっても、newComp/useComp を呼び出してください。
  • 重なり順とグループ化:後から作成したレイヤーは手前に描画されるため、背景やプレートはその上のテキストより先に作成してください。複数のレイヤー(ローワーサードのプレート、バー、テキストなど)をまとめて移動するには、api.create("null", "Group") の下に api.parent で親子関係を設定し、ヌルをアニメーションさせてください。
  • ベクトル属性はオブジェクトとして読み取られます:api.get(id, "position") の値は {x, y} です(resolution、generator.radius も同様です。backgroundColor は {r,g,b,a} です)。一方、api.set には [x, y] を渡します。数値が必要な場合は position.x/position.y を読み取ってください。
  • プレビューは効率よく行ってください:すべてのフレームではなく、物語の要所となる数フレームを 50%のスケールでチェックレンダリングしてください。フル解像度・全範囲のレンダリングは、プレビューに問題がないことを確認してから一度だけ行ってください。
  • 再実行:試行ごとに api.createComp で新しいバージョンのコンポジションを作成してください。同じコンポジションで再実行すると、すべてのレイヤーが重複します。
  • スクリプトからシーンを保存してください — api.saveSceneAs("/path/scene.cv") — こうすればクラッシュしても作業が失われません。モーダルダイアログが開いていると false が返る(または例外が発生する)ため、結果を確認してください。ユーザーに確認せず api.newScene()/api.openScene() を呼び出さないでください。開いているユーザーのシーンが破棄されます。
  • 同梱の型定義はオフラインドキュメントとしても利用できます。ほぼすべての関数に JSDoc の例があるため、シグネチャを推測する前に grep で検索してください。

セキュリティ

ブリッジを実行することは、ユーザーのマシン上でコード実行サーバーを実行することを意味します。ブリッジの起動を依頼する前に、そのことを伝えてください。

  • ブリッジは 127.0.0.1:8731 にバインドし、ライブセッション内でそこに POST された JavaScript を、ユーザーの権限とユーザーが開いているシーンを使って実行します。JSON 以外の本文は JavaScript として直接実行されます。リクエストには認証がありません。ローカルプロセスはすべて、また共有マシン上の他のユーザーも、ブリッジ経由で Cavalry を操作できます。
  • Web ページからは操作できません。Origin ヘッダーを含むリクエスト、またはクロスサイトの Sec-Fetch-Site を含むリクエストは 403 で拒否されるため、ユーザーのブラウザーで開いたページからブリッジにアクセスすることはできません。このチェックが唯一の防御策であり、トークンはありません。
  • ユーザーが実行するまで、待ち受けは始まりません。 cavalry-bridge.js を Scripts フォルダーにコピーしただけでは、メニューに追加されるだけです。ユーザーが Scripts ▸ Cavalry Bridge を選ぶとポートが開き、そのセッション中は開いたままになります。
  • ブリッジを停止するには、Cavalry を終了してください。 リモートからのシャットダウン機能はなく、プロセスの終了とともにポートが解放されます。

コメント