rebelle について
rebelle は、Rebelle の描画を自動化するエージェント向けスキルです。WebSocket によるライブ操作と Motion IO のバッチレンダリングに対応し、出力確認や運用上の注意も扱います。
主な機能
- 01WebSocketで描画イベントを送信
- 02Motion IOによるバッチレンダリング
- 03ストロークとアニメーションフレームの構築
- 04キャンバスを出力してPNGを確認
活用シーン
- 01開いているRebelleのキャンバスで描画を自動化
- 02再現可能な作品を一括生成
- 03フレーム単位のアニメーションを作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jablonkai/ skills --skill rebelleインストール後、Claude Code で/rebelleを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/assets.mdbatch.mdjson-events.mdwebsocket.mdscripts/rebelle_events.pyrebelle_ws.pyrebelle-batch.sh詳細
Rebelle Control
Rebelle は実際の絵の具をシミュレートします。水が流れ、顔料が粒状化し、厚塗りが光を受け止めます。 そして、スクリプトから操作できる両方のビルドで、同じ JSON イベント語彙が使われます。
| ビルド | 操作方法 | 最適な用途 |
|---|---|---|
/Applications/Rebelle 8.app (Pro) | WebSocket サーバーでリアルタイムに操作 | ユーザーが見ているアプリ上での描画、試行、単発の作品制作。Motion IO が使えない場合のアニメーションにも適しています |
/Applications/Rebelle 8 Motion IO.app | -batch-json ファイルで、ほぼヘッドレスに実行 | 再現可能なレンダリング、アニメーションのフレームシーケンス、データレイヤーの入出力 |
まずインストールされているものを確認してください(ls -d /Applications/Rebelle*)。多くの場合、インストールされているのは Pro だけです。
Pro のバイナリは -batch-json を受け付けますが、その後は何も通知せずに無視します(空白の作品、フレームなし。8.3.4 で確認済み)。そのため、Path B では Motion IO のみを使用します。
データレイヤー、16 ビット出力、またはヘッドレスレンダリングが必要な場合を除き、ライブ操作を開始してください。往復処理は 1 分ではなく数秒で済み、いつでもキャンバスを確認でき、アニメーションもライブで動作します(Path B の最後の段落を参照)。
- references/json-events.md — 両方の方法で使うイベント語彙の全容です。単純なストローク以外を書く前に読んでください。
- references/websocket.md — ライブプロトコル、ドキュメント化されていない
cmdAPI、ライブ操作でサポートされていない機能について説明します。 - references/batch.md — Motion IO CLI、データレイヤー、フレームから動画への変換、ライセンスについて説明します。
- references/assets.md — ブラシプリセット名と用紙名の解決方法について説明します(間違っていてもエラーは通知されません)。
- scripts/rebelle_ws.py — 依存関係のない WebSocket クライアント(ライブラリおよび CLI)です。
- scripts/rebelle_events.py — イベントファイルを作成します。バッチフレームのルールとストロークジオメトリのヘルパーが実装されています。
- scripts/rebelle-batch.sh — バッチを実行し、実際に完了してから戻ります。
Path A — WebSocket 経由のライブ操作
Rebelle が接続を受け付けるのは、フラグを付けて起動した場合のみです。また、タスクごとに再起動する必要はありません。まず確認し、その後に尋ねてください。
python3 scripts/rebelle_ws.py --ping # prints e.g. "Rebelle 8 Pro here"
何も応答しない場合は、起動する前にユーザーに確認してください。新しいインスタンスは新しい空白のドキュメントであり、描画は開いている作品に追加され、取り消しグループも作成されません。
"/Applications/Rebelle 8.app/Contents/MacOS/Rebelle 8" \
-websocket-server-enable \
-websocket-allowed-ip-addresses "::ffff:127.0.0.1,127.0.0.1" &
許可リストはソケットのピアアドレスの文字列と照合されます。ローカルクライアントは IPv6 マップ形式の ::ffff:127.0.0.1 として接続するため、127.0.0.1 だけを登録すると、自分自身の接続が拒否されます(Rebelle の出力に ... refused と表示されます)。
その後、Python から操作します。ヘルパーはこのスキルの scripts/ にある通常のモジュールなので、そのディレクトリをパスに追加するか、そこから実行してください。
import sys; sys.path.insert(0, "<this skill>/scripts")
from rebelle_ws import Rebelle
from rebelle_events import catmull_rom, taper
with Rebelle() as r:
r.event({"event_type": "NEW_ARTWORK", "width": 1200, "height": 800, "units": "px"})
r.event({"event_type": "SET_BRUSH", "tool": "WATERCOLOR", "preset": "Watercolor/Round",
"size": 55, "water": 70, "opacity": 90, "paint_type": "PAINT",
"color": {"r": 30, "g": 90, "b": 200}})
r.stroke(catmull_rom([(150, 450), (400, 250), (800, 600), (1050, 320)]),
pressure=taper(0.95))
r.event({"event_type": "SIMULATION", "repeats": 20}) # let the water spread
r.sync() # wait until Rebelle is really finished
r.export("/tmp/check.png") # then Read the PNG
sync() は BOOKMARK を送信し、そのエコーを待ちます。ほかの操作では完了を確認できないため、これを行わないと、まだストロークの途中であるキャンバスをエクスポートすることになります。
NEW_ARTWORK は競合させてはいけない唯一のイベントです。キャンバスの再初期化中に、Rebelle は次のメッセージを破棄します。通常は SET_BRUSH が破棄され、ブラシなしでストロークすると、起動直後のアプリがクラッシュします(bad_optional_access、8.3.4)。Rebelle.event() は、ブックマークが返るまで(ready())NEW_ARTWORK の後で待機するため、生の send_text() ではなくこちらを使ってください。独自にクライアントを作る場合も、同じようにポーリングする必要があります。
SAVE/LOAD イベントはライブ操作では拒否されます。作品を書き出す唯一の方法は export()(cmd: export_canvas)で、ユーザーに見えている合成済みキャンバスがそのまま書き出されます。
Path B — Motion IO によるバッチレンダリング
python3 build_painting.py # writes events.json via rebelle_events.Doc
bash scripts/rebelle-batch.sh events.json out/
Motion IO は macOS では自動終了せず、進行状況も標準出力の batch frame end: i/n でしか報告しません。そのため、必ず rebelle-batch.sh を使用してください。これは i == n になるまで待機し、ERROR: 行を表示してからアプリを停止します。
1 フレームにつき、出力画像が 1 枚生成され、暗黙の流体シミュレーションステップが 1 回実行されます。そのため、アニメーションを自然に作成できます。少し描画してフレームを閉じ、これを繰り返します。
from rebelle_events import Doc, catmull_rom, taper
d = Doc(1200, 800, paper={"preset": "Handmade/HM01 Handmade", "deckled_edges": True})
d.set_brush("WATERCOLOR", "Watercolor/Round", size=55, water=70, opacity=90,
paint_type="PAINT", color=(30, 90, 200))
d.stroke(catmull_rom([(150, 450), (400, 250), (800, 600), (1050, 320)]), pressure=taper())
d.frame() # one animation frame ends here
d.simulation(15, frames=20) # 20 frames of the paint spreading and drying
d.write("events.json")
バッチ処理を機能させるフレームのルール
Doc はこれらのルールをすでに適用しています。手書きの JSON でも同様に守らないと、処理が永遠に停止したり、作業内容が気づかないうちに失われたりします。最初のフレームを読み込んでいる間、Motion IO はまだ起動処理中です。起動中も問題なく処理されるフレームは次のとおりです。
- フレーム 0 は、ブラシを読み込むためのウォームアップです。 ここに
SET_BRUSHを置けば、起動完了に必要な実作業として十分です。BOOKMARKだけのフレーム、または空のフレームでは、最初のフレームが処理される前にデッドロックします。 NEW_ARTWORKはフレーム 1 に置き、フレーム 0 には置かないでください。 フレーム 0 に置くと何も通知されずに破棄され、Rebelle のデフォルトの A4 キャンバス(200 dpi、2339×1654)がそのまま使われます。NEW_ARTWORKと同じフレームには、その後に別のイベントが必要です(SET_BRUSHをもう一度設定すれば問題ありません)。NEW_ARTWORKの直後に終わるフレームはデッドロックします。NEW_ARTWORKのフレームでは描画しないでください。キャンバスの再初期化時に描画が消去されます。次のフレームから描画を始めてください(実際のコンテンツが始まるのはDoc.first_content_frameです。これをffmpeg -start_numberに渡してください)。
NEW_ARTWORK を完全に省略する必要がある場合は、-input artwork.reb で既存の作品を開くのがキャンバスサイズを設定する最も確実な方法です。ただし、ユーザーがあらかじめ作品を保存しておく必要があります。
Motion IO を使わない場合は、同じ Doc をライブでレンダリングできます。 rebelle_ws.py --send events.json --frames-out out/ は WebSocket 経由でフレームごとに再生し、バッチと同じ番号で frame_0000.png… を書き出すため、first_content_frame と batch.md の ffmpeg レシピをそのまま適用できます。ライブでは、流体シミュレーションはフレームごとに 1 ステップではなくリアルタイムで実行されます。そのため、フレーム数に頼らず、濡れた部分には SIMULATION の繰り返しを明示的に指定してください。
絵の具で描いたような仕上がりにする
- 座標はキャンバスのピクセル単位で、左上を原点として y 軸は下向きです。キャンバスの外側も指定できます。端から端まで塗るには、ストロークをキャンバスの外から始めて、外で終わらせてください。
POINTER_MOVEは前の区間を描画するため、ストロークは最後の移動位置でリリースして終える必要があります。stroke()/stroke_events()はこの処理を行いますが、イベントを手書きすると最後の区間が失われることがよくあります。- ブラシの幅はプリセットごとに調整してください。
size(UI のスライダー値)もsize_pxも、実際の描画幅の目安にはなりません。8.3.4 では、size_pxを 200 にすると、Round では約 150 px、Mop では約 50 px、Flat では約 200 px になり、Round でsize_pxを 50 にすると、わずか約 6 px でした。構図を決める前に、プリセットごとにテストストロークを描いて書き出し、幅を測ってから調整してください。 - パスは高密度でサンプリングしてください。 Rebelle は点と点の間を補間するため、4 点では滑らかでもありきたりな曲線になります。
catmull_rom()を使い、セグメントごとに約 16 点を指定すると、ブラシのテクスチャや間隔、筆圧が実際に表現されます。 - 筆圧を変化させてください。 0.9 で一定にすると機械的な線に見えます。
taper()は両端を細くし、ramp()は徐々に強くします。それだけでも、プロッターで描いた線とストロークの違いの大部分を表現できます。 - 湿った画材にはシミュレーション時間が必要です。 水が広がるのはシミュレーションのステップ中だけです。描画したら、フレーム数を重ねるか
{"event_type":"SIMULATION","repeats":N}を指定して、にじみが広がる時間を与えます。その下のレイヤーににじませたくないレイヤーを描く前に、DRY/FAST_DRYを実行してください。 - 実際の絵画と同様に、色をレイヤー状に重ねてください。 まず淡いウォッシュを置き、
DRYを実行してから、その上に濃いグレーズを重ねます。SET_ENGINE_PARAMSでは、吸収性、垂れ、粒状感を制御できます。 - ブラシは名前ではなくシミュレーション特性で選んでください。ウォッシュやにじみには
WATERCOLOR、再び濡らせる線画にはINK_PEN、厚塗りやキャンバス上での色混ぜにはOIL_AND_ACRYLIC、乾いた質感にはPENCIL/PASTEL、柔らかなグラデーションにはAIRBRUSHが適しています。
常に結果を確認してください
Rebelle はほとんど何も返さず、用紙やプリセットを間違えると、もっともらしく見えるものの完全に間違った画像ができあがります。キャンバスをちらっと確認するのと同じように、意味のあるステップごとに書き出して PNG を読み込んでください。ライブ操作では r.export(path)、バッチ処理では最後にレンダリングされたフレームを読み込みます。絵として、描画範囲、色、水彩の効果が出ているかを判断し、反復してください。その後、ユーザーが完成した作品を求めたら、フルサイズで書き出します(rgba_canvas、または NanoPixel スケールで書き出す場合は scaling を指定した SAVE)。
事前に知っておきたい落とし穴
- プリセット名が間違っていると明確なエラーが出ますが、用紙名が間違っていても何も起きません。 まずファイルシステム上で両方を確認してください(assets.md)。公式クイックスタートの
"Default/HM01 Handmade"も、Rebelle 8 では間違った名前です。 presetを指定せずにSET_BRUSHを実行すると何も描画されず、Preset for brush was not setとログに記録されます。- Rebelle を同時に起動できるのは 1 つだけです。 GUI ビルドと Motion IO を同時に実行するのは問題のもとになります。もう一方を起動する前に、片方を終了してください。
- アプリを強制終了すると、
~/Library/Application Support/Escape Motions/Rebelle 8/にData/Sessions/<pid>/フォルダーが残ります。実害はありませんが、1 つにつき数十 MB ずつたまっていきます。ユーザーに知らせず削除するのではなく、その旨を伝えるとよいでしょう。 - 色は 8 ビット RGB オブジェクト(
{"r":…,"g":…,"b":…})ですが、エンジン内では 16 ビットで混色されます。16 ビットで出力できるのは Motion IO の.exr書き出しだけです。 - ドキュメントの記述がビルドより先行しています。 8.3 のドキュメントでは WebSocket 経由の
SAVE/LOADが可能とされていますが、リリース済みの 8.3.x ビルド(8.3.0 と 8.3.4 で確認)では拒否されます。ドキュメントに記載された動作より、実際に確認した書き出しを信頼してください。 - アニメーションのライセンスには条件があります。 商用制作を支援する前に、batch.md の末尾にある注意事項を確認してください。
セキュリティ
Path B は何も開きません。Motion IO はファイルを読み込んでレンダリングするだけです。Path A は異なります。Rebelle を -websocket-server-enable 付きで起動すると、イベント語彙を受け取ってコードを実行できる コード実行サーバー になります。ユーザーに再起動を依頼する前に、そのことを伝えてください。
- サーバーは
127.0.0.1:8265(REBELLE_WS_PORT)で待ち受けます。受信したイベント JSON を、ユーザーが開いている作品に適用し、export()は現在の権限でファイルを書き込みます。認証はありません。ローカルのすべてのプロセスと、共有マシン上の他のユーザー全員がキャンバスに描画できます。 -websocket-allowed-ip-addressesは唯一のアクセス制御であり、ソケットのピアアドレスと照合されます。ループバック(::ffff:127.0.0.1,127.0.0.1)のみにしてください。LAN アドレスは決して追加しないでください。 キャンバスがネットワークに公開されます。また、ユーザー自身のブラウザー内の Web ページもループバックのピアであり、WebSocket 接続には CORS が適用されないため、許可リストで除外できるとは考えないでください。- 停止するには、Rebelle を終了し、フラグを付けずに再起動してください。 このフラグは起動ごとに指定するもので、通常どおり起動した Rebelle は何も待ち受けません。