framefields-effects について
framefields-effects は、framefields でレイヤー、コンポジション、メディアに GPU エフェクトを適用するためのクリエイターや開発者向けスキルガイドです。オンデバイスのビジョンモデルと、その結果を利用するリアクティブシグナルも扱います。
主な機能
- 01レイヤー、コンポジション、メディアへのエフェクト適用
- 02カラーグレーディング、レンズ、テクスチャエフェクト
- 03アニメーションやリアクティブシグナルによるパラメーター制御
- 04空間ライティングとマテリアルエフェクト
- 05検出、セグメンテーション、姿勢推定モデルの実行
活用シーン
- 01映像のカラーグレーディングとシネマティックなレンズ効果
- 02コンポジションへの局所的なぼかしや空間ライティングの追加
- 03ビジョンモデルによるオブジェクト追跡やマスク生成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gatewai-dev/ framefields --skill framefields-effectsインストール後、Claude Code で/framefields-effectsを入力して読み込まれたか確認します。
同梱ファイルreferences/effects-catalog.mdreferences/style-guide.md
詳細
framefields-effects
セットアップ
framefields npm パッケージからすべてをインポートしてください。プロジェクトでまだ framefields をセットアップしていない場合は、まず framefields スキル(インストール、プロジェクトの雛形作成、最初のレンダリング)に従ってください。
概要
framefields は、2D VFX、トーン調整、映画的なレンズシミュレーション、空間リライティング、リアルタイムのニューラルビジョンコンディショニングに対応する、ネイティブの WebGPU シェーダー実行パイプラインを備えています。
framefields のエフェクトは、強い型付けがされた Effect サブクラスです。uniform プロパティには、静的な値、時間変化するキーフレーム、リアクティブな Signal インスタンス、またはオーディオ抽出パイプラインを指定できます。
プロパティ単位のカタログ、デフォルト値、型の範囲については、references/effects-catalog.md を参照してください。
エフェクトの適用
エンジンには、主に4つの適用方法があります。
1. レイヤーレベルのエフェクトパイプライン
.withEffect(effect) または .withEffects([...]) を使って、任意のレイヤー(box、flex、shape、text、media)に1つ以上のエフェクトを直接適用します。
import { Layer, Curves, Vignette, Blur, Pixelate } from "framefields";
// Media layer with color grade and lens effects
const videoLayer = Layer.video("assets/footage.mp4", { fit: "cover" })
.withEffect(new Curves({
master: [{ x: 0, y: 0.05 }, { x: 0.5, y: 0.52 }, { x: 1, y: 0.95 }]
}))
.withEffect(new Vignette({ strength: 0.4, radius: 0.85, softness: 0.6 }))
.withEffect(new Blur({ strength: 8, blurType: "Gaussian" }));
// Styled container box with blur
const cardLayer = Layer.box({ width: 400, height: 300, background: "#1e1e24" })
.withEffect(new Blur({ radius: 12 }));
// Kinetic text with pixelation
const titleLayer = Layer.text("CYBERPUNK", { fontSize: 72 })
.withEffect(new Pixelate({ size: 8 }));
2. コンポジション全体へのマスターエマルジョン
レンダリングされたすべてのレイヤーに、全体的なポストプロセスのグレードまたはフィルムエマルジョンを適用します。
import { Composition, FilmGrain, ColorBalance } from "framefields";
const comp = new Composition({ width: 1920, height: 1080, fps: 30 });
// Shared organic 35mm grain applied across titles, background video, and vector graphics
comp.apply(new FilmGrain({
strength: 0.06,
size: 1.5,
monochrome: true,
animated: true,
speed: 1.0,
}));
comp.apply(new ColorBalance({
shadows: { cyanRed: 4, yellowBlue: -6 },
highlights: { cyanRed: 2, yellowBlue: -4 },
preserveLuminosity: true,
}));
3. 空間セクションとトラッキングセクション(comp.section / Layer.section)
プレートまたはキャンバスのサブ領域を分離して、局所的なエフェクトを適用します。
// Box blur on a tracked object or explicit bounding rectangle
const blurredPlate = comp.section({
source: "assets/interview.mp4",
x: 400,
y: 200,
width: 300,
height: 300,
borderRadius: 150,
effects: [new Blur({ strength: 25, blurType: "Gaussian" })],
});
4. 流れるように記述できるメディアチェーン(Media)
レイアウトツリーにマウントする前、またはエクスポートする前に、クリップを処理します。
import { Media, ApplyLUT, Crop } from "framefields";
const clip = Media.video("assets/raw_log.mp4")
.apply(new ApplyLUT({ lutUrl: "assets/luts/cinematic.cube", intensity: 1.0 }))
.apply(new Crop({ cropType: "rectangle", topPercentage: 10, heightPercentage: 80 }));
const pngBuffer = await clip.renderFrame({ atMs: 1500 });
エフェクトのカテゴリ
1. カラーグレーディングとトーンダイナミクス
Curves:マスター、赤、緑、青に加え、色相/彩度カーブ(hueVsHue、hueVsSat、lumVsSat、satVsSat)をスプライン補間するトーンカーブです。ColorBalance:preserveLuminosityに対応した、シャドウ、中間調、ハイライトの色調整です。Levels:マスターおよびチャンネルごとの入力/出力の黒点/白点とガンマを設定します。SelectiveColor:赤、黄、緑、シアン、青、マゼンタ、白、ニュートラル、黒を対象とした、CMYK 方式の写真向け選択的調整です。GradientMap:複数の停止点を持つグラデーションマッピングです(stops: [{ position: 0, color: "#000" }, { position: 1, color: "#FFF" }])。ShadowsHighlights:半径とトーン幅を調整して、シャドウの持ち上げとハイライトの復元を個別に行います。ApplyLUT:1D および 3D の.cubeカラールックアップテーブルを適用します。Modulate:リアルタイムの HSL/コントラスト調整です。hue、brightness、contrast、exposure、saturation、sepiaに対応します。
2. 光学、テクスチャ、映画的なエマルジョン
FilmGrain:粒子のサイズ、シャドウ/ハイライトのマスキング、時間方向のアニメーション速度を調整できる、GPU で生成されるフィルムグレインです。Vignette:中心、丸み、柔らかさをカスタマイズできる、楕円形または円形のレンズ減光です。Blur:高性能なマルチモードブラーです。"Gaussian"、"Box"、"Median"、"Motion"、"Bilateral"、"Edge-preserving"、"Radial"、"Zoom"に対応します。部分的なブラー領域や、トラッキングされたオブジェクトのバウンディングボックスもサポートします。UnsharpMask:しきい値による抑制機能を備えた、高周波エッジのシャープ化です。HighPass:コントラストを強調しながら、エッジと周波数成分を分離します。HalftoneScreen:"Monochrome"または"CMYK"の角度で、"Circle"、"Diamond"、"Line"、"Square"のドットを使う、プロシージャルな印刷スクリーン処理です。TileOffset:"wrap"、"clamp"、"mirror"、"transparent"の境界モードに対応する、シームレスな UV ラッピングです。MotionBlur:カスタムシャッター角度と速度制限を使った、方向性のあるシャッターシミュレーションです。TemporalDeflicker:マルチフレームのオプティカルフロー合成により、生成 AI クリップや高速撮影映像のちらつきを除去します。
時間軸(記憶を持つエフェクト)
Trails:自身の過去の残像を減衰させながら重ねるレイヤーです。mode: "blend"(デフォルト。全画面映像に残像を付けます)、"over"(切り抜きやテキスト向け)、"add"(暗いシーンでのライトペインティング向け)、"max"(光跡向け)を指定できます。decayは 0.8 で短い残像、0.97 で長い光跡になります。フレームごとにzoom(1.02 = トンネル効果)、rotation、offsetX/Y、hueShift(サイケデリックな色の変化)を指定できます。Datamosh:前の画像を新しいフレームのオプティカルフローに沿って引きずり、更新せずに表示します。keyframesフレーム(I フレーム)に達すると、きれいな画像が表示されます。きれいな画像にしたい位置にキーフレームを配置してください。カットを入れずに次のショットの動きを重ねると、前のショットがにじみます。strength、bleed(フレームごとにきれいな画像を混ぜ戻す量)を指定できます。- どちらもフレームのレンダリングに合わせて処理されます。スクラブや単一の
renderFrameなどでジャンプした後は、履歴を再構築するため、直近のフレームをwarmup回分再生します。
3. 3D 空間ライティングとマテリアル
Relight3D:スクリーンスペースの法線マップを使った再ライティングです。ポイントライト、スポットライト、ディレクショナルライト、スペキュラハイライト、ラフネス、メタリックの各ユニフォームに対応します。SSAO:深度バッファーから接触影を生成するスクリーンスペースアンビエントオクルージョンです。PBRGlass:物理ベースの透過、屈折率(IOR)、光学的分散、フレネル反射を適用します。DepthOfField:絞り値、焦点距離、フォーカス面までの距離、錯乱円(CoC)ぼかしを使ってカメラレンズをシミュレートします。
4. マット、キーイング、エッジ操作
ColorKey:スピル抑制と滑らかさの調整に対応した、スタジオ向けグリーンスクリーン/ブルースクリーンのキーイングです。Crop:矩形、円形、または任意のポリゴンパスで切り抜きます。角を丸めることもできます。
5. スタイライズ表現(Styles.*)
リクエストに合わせたルックの選び方: references/style-guide.md を参照してください。「VHS」、「8-bit」、「comic」、「liquid logo」などの表現をプリセット、エフェクト、テクニックに対応付けています。スタイル名が指定された場合は、必ずこちらを読んでください。
Styles.<name>(options?) はエフェクトスタックを返します:layer.withEffects(Styles.vhs())。プリセット:pixelArt、gameBoy、teletext、ledWall、ascii、oneBit、risograph、comic、cartoon、thermal、vhs、crt、glitch、oilPainting、watercolor、topographic、kaleidoscope、opArt、holographic、noir、film。
細かく制御する場合は、以下のエフェクトを使います。
Pixelate:大きなピクセルを適用します。shape: "square" | "circle" | "diamond"(LED ウォール向け)、gapを指定できます。Posterize:色数を減らすか、palette(gameboy、teletext、cga、pico8、c64、grayscale、sepia、custom+colors)に色を合わせます。BayerditherとpixelSizeも指定できます。Dither:bayer/noise/halftoneに対応します。1-bit のデュオトーン(dark/light)またはチャンネルごとのlevelsを指定できます。Ascii:明るさに応じてグリフを割り当てます。colorMode: "mono" | "source" | "green"、cellSize、fg/bg、invertを指定できます。Toon:明るさの階調に加え、Sobel のインク線を適用します(edgeColor、edgeWidth、edgeThreshold)。RGBSplit:angleまたはradialに沿って色収差を適用します。CRT:湾曲、走査線、アパーチャーマスク、ノイズ、ちらつき、ビネットを適用します。trackingとchromaを使うと、VHS の揺れや色にじみを再現できます。Painterly:Kuwahara のoil/watercolorを使います(顔料のエッジ、紙の粒状感)。Contour:sourceの上に地形図の等高線を重ねます。単色の紙色にすることも、何も表示しないこともできます。Kaleidoscope:中心の周りにsegmentsを鏡像として配置します。rotation/zoomをアニメーション化できます。OpArt:縞模様/リング/チェッカー/波を、画像に応じて曲げたり太くしたりします。Iridescence:明るさまたはレリーフから、薄膜の虹色効果を作ります。shiftをアニメーション化できます。Gooey:ぼかし + アルファしきい値で、メタボールを表現します。不透明な映像ではなく、透明度のあるレイヤー(SVG、パーティクル)に使ってください。
デバイス上でのビジョン処理
framefields はレンダリングされたフレーム上でビジョンモデルを実行し、結果をリアクティブなシグナルとして公開します。モデルは初回使用時に遅延ダウンロードされ、$FRAMEFIELDS_MODELS_DIR(デフォルトは ~/.cache/framefields/models)にキャッシュされます。
| オプション | モデル | 得られるもの |
|---|---|---|
enableDetection(デフォルト) | RTMDet-Ins | 時系列で追跡された COCO-80 のバウンディングボックス → vision.objects |
enableSegmentation | RTMDet-Ins(同じパス) | インスタンスごとのソフトマスク → vision.masks、vision.segmentation |
enablePose | RTMO | 人物ごとの 17 個の COCO キーポイント → vision.poseLandmarks、track.pose |
enableMatte | Selfie Segmenter | 高速な人物アルファ → vision.segmentation.matte |
variant: "t" | "s" | "m" は速度と精度のトレードオフです(デフォルトは "s")。confidence(デフォルトは 0.3)と classes: ["person", ...] で検出対象を絞り込めます。
// Whole composition: returns the reactive bundle
const vision = comp.withVision({ enableSegmentation: true, enablePose: true });
// One layer: renders through a node mode
Layer.video("assets/dancer.mp4").withVision({ mode: "matte", enableSegmentation: true });
ノードモード:passthrough、mask、matte、crop、skeleton、boxes、tracking。mask/matte/crop では、matteSource: "instance"(デフォルト。任意の COCO クラスに対応し、ドレスなど重なり合う部分を被写体に統合します)または "selfie"(人物のみ。最速)を指定します。
設定の選び方
CPU で 1280~2048 px のフレームごとに測定(onnxruntime-node):
| タスク | t | s(デフォルト) | m |
|---|---|---|---|
| 検出/セグメンテーション(共有の 1 パス) | 150~300 ms | 200~340 ms | 420~700 ms |
| 姿勢推定 | 約 50 ms | 約 120 ms | 約 280 ms |
| マット(Selfie Segmenter) | 約 20 ms | 約 20 ms | 約 20 ms |
- まずは
"s"から始めてください。動きの速いブラーや複雑な背景を含むヒーローショットには"m"を使い、"t"は主に姿勢推定の時間を短縮する場合に使います。 enableDetectionとenableSegmentationの両方を有効にしても、推論コストは 2 回分ではなく 1 回分です。- Selfie のマットはクローズアップにのみ使用してください。 フレームの大部分を人物が占める構図に調整されています。遠くの人物を見逃し、人物が写っていないクローズアップでも「person」と判定することがあります。それ以外では
matteSource: "instance"を維持してください。 - 抽象的または様式化された映像では、
confidence(たとえば0.5)を上げてください。デフォルトの0.3では、モデルが煙、目、惑星に「teddy bear」や「donut」といった曖昧なラベルを付けることがあります。 - 1 つの対象だけに関心がある場合は、
classesを制限してください。人物がフレームから外れたときに、対象が別のオブジェクトへ切り替わるのも防げます。
GPU または CPU
推論は、ハードウェアアダプターが利用できる場合は onnxruntime-web の WebGPU バックエンド(framefields のオプション依存関係ですが、デフォルトでインストールされます)を通じて GPU で実行され、それ以外の場合は onnxruntime-node を通じて CPU で実行されます。onnxruntime-web がない場合、アダプターがソフトウェアのみ(lavapipe、SwiftShader)の場合、または WebGPU が失敗した場合は、CPU が使われます。Apple Silicon 搭載 Mac では、GPU によりレンダリング時間がおよそ半分になります。同じ variant を使うレイヤー間ではモデルが共有され、同じピクセルを表示するレイヤー間では検出/セグメンテーションのパスが 1 つ共有されます。
| 変数 | 効果 |
|---|---|
FRAMEFIELDS_VISION_PROVIDER | auto(デフォルト)、webgpu、cpu、または cuda(Linux x64 上の onnxruntime-node の CUDA EP。CUDA 12 と cuDNN 9 のライブラリが必要です)。強制指定したバックエンドが失敗した場合は、フォールバックせずエラーをスローします。 |
FRAMEFIELDS_VISION_THREADS | モデルごとの CPU スレッド数。Linux でのデフォルトは、cgroup のクォータを含む、プロセスが使用できる CPU 数です。それ以外では ONNX Runtime のデフォルトが使われます。 |
レンダリング時の動作
- 1フレームの遅延。 Vision はレイヤーの 前回 のレンダリングフレームを読み取るため、最初のフレームでは結果が得られず(切り抜きは透明にレンダリングされます)、マスクは映像より1フレーム遅れます。通常の再生速度では気になりません。コンポジションが
comp.visionでも読み取るクリップのマットには、この遅延はありません(下記のクリップビジョンを参照)。 - Vision のフレームは順番にレンダリングしてください。
renderVideoを使うと自動的に処理されます。静止画の場合は、同じレンダラーで連続するフレームを少なくとも2つレンダリングし、最後のフレームを使用してください。後のフレームに直接ジャンプしたり、フレームグリッドを使用したりすると、直前にレンダリングされたフレームのピクセルが切り抜かれ、被写体が二重に残像として表示されます。 - 被写体の選択。
mask/matte/cropは最も大きい人物を使用し、人物がいない場合は最も信頼度の高いインスタンスを使用します。被写体と重なっていて、その大きさが被写体の2倍以下のインスタンスは統合されます(ドレス、手に持った楽器など)。被写体を囲む大きな物体(トンネル、窓枠など)は統合されません。classesは被写体になり得るものを制限しますが、被写体に統合されるものは制限しません。COCO には衣服のクラスがないため、流れるようなドレスは「kite」や「umbrella」として返されることがよくありますが、それでもclasses: ["person"]の切り抜きに統合されます。 - 各 Vision レイヤーはオブジェクトを個別に追跡します。2つのレイヤーのトラック ID に関連性はありません。
トラブルシューティング
| 症状 | 対処法 |
|---|---|
| 動きの速い衣服の一部が切り抜きから欠ける | variant: "m" を設定するか、keyBackground: true を設定して、つながった前景領域に被写体を広げます |
| 切り抜くオブジェクトが違う | classes: ["person"](または対象のクラス)を設定します |
| 暗い背景で切り抜きの周囲に薄いハローができる | featherRadius を下げるか、maskThreshold を上げます(例:0.6) |
| オフラインまたは CI でレンダリングする | runner.preload([...]) を使って $FRAMEFIELDS_MODELS_DIR に事前ダウンロードするか、FRAMEFIELDS_MODELS_BASE_URL をミラーに設定します |
| モデル自体を確認する | 新しいモデルディレクトリで await runner.preload([...]) を実行します。各モデルがダウンロードされ、SHA-256 が検証されます(すべて合わせて約380 MB) |
1. 被写体サンドイッチ(「被写体の後ろにテキストを配置」)
映像から前景の被写体を切り抜き、文字やグラフィックをそのすぐ後ろに挟み込みます:
comp.addSubjectSandwich({
source: "assets/dancer.mp4",
behind: [
Layer.text("HEADLINE BEHIND", {
fontSize: 120,
fill: "#FF5A1F",
fontWeight: 900
})
],
feather: 4,
fit: "cover"
});
2. スマートなリフレーミング(16:9から9:16への自動クロップ)
仮想カメラのダンピングで追跡対象の被写体を捉えながら、横向きの動画を縦型のショート動画に滑らかにリフレーミングします:
const vision = comp.withVision({ enableDetection: true });
comp.addSmartFraming({
source: "assets/action.mp4",
target: vision.objects.primary,
targetAspect: 9 / 16,
damping: 0.15,
leadHeadroom: 0.1
});
3. 被写体の輪郭グローとネオンパルス
セグメント化された被写体の輪郭に、オーディオに反応する輪郭グローを適用します:
const vision = comp.withVision({ enableSegmentation: true });
comp.addSubjectOutline(vision.segmentation.subject, {
source: "assets/character.mp4",
color: "#FF5A1F",
width: 6,
blur: 12
});
4. 追跡領域のぼかし
ライブトラックを追跡しながら、顔、ナンバープレート、または検出された任意のクラスをぼかします:
const vision = comp.withVision({ classes: ["person"] });
layer.blurRegion(vision.objects.byCategory("person"), { strength: 30 });
5. Clip Vision:フレームがレンダリングされる前に結果を得る
withVision はレイヤーの前にレンダリングされたフレームを解析するため、結果は1フレーム遅れで取得され、レンダリング中にのみ存在します。物理演算、レイアウト、キーフレームなど、フレーム時点の動きを把握する必要がある場合は、comp.vision を使って、クリップ自身のフレームを必要に応じて解析します。
const dancer = comp.vision("assets/dancer.mp4", { startFrame: 0 }); // pose + silhouette (person)
const person = dancer.person.place({ width: W, height: H, fit: "cover" });
person.point("rightWrist", 48); // { x, y, visibility } in composition px, smoothed over ±2 frames
person.signals("nose").x; // a signal for .signal("x", …)
person.sample(48, x, y); // silhouette alpha + inward gradient (dress and held things included)
await dancer.ready(0); // analyse a frame (or a range: ready(0, 120)) to read it at build time
- コンポジションは、すべてのレンダリング経路とプレビューで、描画の直前に各フレームのクリップを解析し、ライブ物理ワールド(
world.live(comp))ではステップ処理の前に解析します。事前処理は行われず、プレビューはすぐに開始します。 - 結果は Node 上で(
~/.cache/framefields/vision、または$FRAMEFIELDS_VISION_CACHE_DIRに)ファイルと設定をキーとして保存されるため、後続の実行やプレビュー後のレンダリングは瞬時に完了します(キャッシュを無効にするにはcacheDir: falseを指定します)。 - オプション:
startFrame/trimStartSec(クリップの再生位置)、pose、mask、maskCell(シルエットのグリッド、デフォルトは 8 px)、smoothing(フレーム数、デフォルトは 2)、variant。人物を見失った場合は、最後のポーズを最大1秒間保持します。 - 同じクリップの
withVision({ mode: "matte" })カットアウト(またはmask/crop)は、これらの結果を再利用します。コンポジションは描画対象フレームのクリップの被写体をカットアウトに渡すため、セグメンテーションは一度だけ行われ、レンダリング時に再実行されず、カットアウトとプレートは同じフレームで揃います。classes、keyBackground、matteSource: "selfie"、またはクリップと異なるモデル設定を持つレイヤーは、それぞれ独自の処理を行います。 - 解析には CPU でフレームあたり約 200 ms かかります(主にセグメンテーションが時間を要します)。WebGPU ではより高速です。ライブプレビューでは、まだ解析されていないフレームが解析されるまで、再生ヘッドが待機します。
6. 作成前に解析する
クリップに含まれる内容を一度の処理でレポートします(トラック、クラス、マスクのカバレッジ)。ffmpeg は不要です。
const report = await comp.analyzeVisionSequence("assets/street.mp4", {
tasks: ["detect", "pose"],
categories: ["person"]
});
report.tracks; // [{ trackId, category, frames: [start, end], centerPath, ... }]
リアクティブなシグナル変調
任意の Effect のユニフォームには、静的な値の代わりにリアクティブな Signal インスタンスを指定できます。シグナルが変化すると、パイプラインを再構築することなく GPU のユニフォームバッファーが自動的に更新されます。
import { Layer, Blur, sineSignal, computed } from "framefields";
// Oscillating breath blur
const blurSignal = sineSignal({
frequencyHz: 0.5,
min: 0,
max: 20
});
const layer = Layer.image("assets/bg.jpg")
.withEffect(new Blur({
strength: blurSignal,
blurType: "Gaussian"
}));
ベストプラクティス:
- エマルションは控えめに:
FilmGrain(0.04–0.08)とVignette(0.2–0.45)は控えめにします。フィルターをかけすぎると、素人っぽい仕上がりになります。 - 順序が重要: トーン補正(
Curves、ColorBalance)をレンズ光学効果(Blur、DepthOfField)の前に配置し、グレイン(FilmGrain)を最外層として適用します。 - 冗長なシェーダーを避ける: 静止画像を書き出す場合は、決定論的な静止レンダリングを維持するため、
FilmGrainのanimated: falseを設定します。