ピッカーカタログ
@nodaro/prompts を使って、Nodaro のピッカーを自分のアプリに実装します。選択をプロンプトの一節に変換し、ラベルを翻訳し、画像を表示します。API でカタログを読み取ることもできます。
ピッカーカタログは、ムード(Mood)、レンズ(Lens)、フレーミング(Framing)、人物(Person)といった、Nodaro のピッカー(クリエイティブコントロールのノード)の 1 つを支えるデータです。ピッカーの選択肢、各選択肢が追加するプロンプトのテキスト、そのカテゴリー、翻訳のキーを保持します。カタログは npm パッケージの中に単純なデータとして同梱されているため、自分のアプリに、自分のスタイルで同じピッカーを実装し、Nodaro が組み立てるのとまったく同じプロンプトを組み立てられます。
ピッカーがモデルを呼び出すことはありません。ピッカーは、自分がつながっている先のノードのプロンプトに、説明的な一節を追加するだけです。クリエイティブコントロールを参照してください。
パッケージをインポートするか、API を呼び出す
| あなたのアプリ | 方法 |
|---|---|
| npm パッケージを同梱できる | @nodaro/prompts からカタログをインポートします。型が付いていて、オフラインで動作し、API 呼び出しは不要です。 |
| パッケージを同梱できない(MCP 経由の AI エージェントなど) | 同じデータを、ディスカバリー用のインターフェースから読み取ります。REST エンドポイントの GET /v1/picker-catalogs、SDK の client.pickerCatalogs、CLI の nodaro pickers、または MCP ツールの get_picker_catalog です。 |
できる場合は、パッケージを優先してください。リリースのときにしか変わらないデータのために、往復通信を省けます。
npm install @nodaro/prompts @nodaro/shared @nodaro/sdk@nodaro/prompts にはカタログとプロンプト用の関数が、@nodaro/shared には翻訳が入っており、@nodaro/sdk が生成を実行します。
レジストリ
import { PICKER_CATALOGS, getPickerCatalog, listPickerCatalogs } from "@nodaro/prompts"| エクスポート | 返す内容 |
|---|---|
PICKER_CATALOGS | すべてのピッカーカタログです。単一次元のピッカーが 28 個、複数次元のピッカーが 11 個あります。 |
getPickerCatalog(nodeTypeOrCatalogId) | ノードタイプ("mood" など)またはカタログ ID で指定する、1 つのカタログです。 |
listPickerCatalogs() | そのすべてです。 |
カタログの型は、次のとおりです。
interface PickerOption {
id: string
label: string // English display text; translate it with the catalogId (see below)
description?: string
category?: string // group id, matching categoryOrder and categoryLabels
promptHint: string // the clause this option adds ("" for a no-op option such as "auto")
term: string // the short professional term Compact mode adds ("" for a no-op option)
icon?: string // reserved; pictures are served separately (see "Pictures")
}
interface PickerDimension { // multi-dimension pickers, and the secondary fields of a single-dimension picker
field: string // for example "shotSize"
label: string
options: readonly PickerOption[]
}
interface PickerCatalog {
nodeType: string // "mood", "framing", ...
label: string
catalogId: string // the key of the translations
kind: "single" | "multi"
valueField?: string // single: the field a selection writes
defaultValue?: string
categoryOrder?: readonly string[]
categoryLabels?: Readonly<Record<string, string>>
options?: readonly PickerOption[] // single-dimension pickers
fields?: readonly string[] // multi-dimension pickers: the dimension fields
dimensions?: readonly PickerDimension[] // multi-dimension pickers, and secondary fields
}label は画面に表示し、term または promptHint はモデルに送ってください。一方からもう一方を導き出さないでください。
単一次元のピッカーを実装する
ムードのような単一次元のピッカーは、フラットなリストから 1 つを選ぶもので、グループ分けされることもあります。options には、グリッドを描画するために必要なものがすべて入っています。
import { getPickerCatalog, getParameterPromptHint } from "@nodaro/prompts"
import { createClient, StaticTokenAuth } from "@nodaro/sdk"
const client = createClient({
baseUrl: "https://app.nodaro.ai",
auth: new StaticTokenAuth(process.env.NODARO_ACCESS_TOKEN!),
})
const mood = getPickerCatalog("mood")! // { nodeType: "mood", valueField: "mood", options, categoryOrder, categoryLabels }
// 1. Render your own tile grid, grouped by category
function MoodPicker({ value, onChange }: { value?: string; onChange: (id: string) => void }) {
return (mood.categoryOrder ?? [undefined]).map((cat) => (
<section key={cat ?? "all"}>
{cat && <h4>{mood.categoryLabels?.[cat]}</h4>}
{mood.options!
.filter((o) => !cat || o.category === cat)
.map((o) => (
<button key={o.id} aria-pressed={value === o.id} title={o.description} onClick={() => onChange(o.id)}>
{o.label}
</button>
))}
</section>
))
}
// 2. Selection, then prompt clause, then generation
const selected = "serene"
const clause = getParameterPromptHint({ type: "mood", data: { mood: selected } })
// or: mood.options!.find((o) => o.id === selected)!.promptHint
const prompt = ["a portrait of a woman", clause].filter(Boolean).join(", ")
const result = await client.nodes.runAndWait("generate-image", { prompt })
console.log(result.imageUrl)トランジション、キャラクター FX、キャラクターモーションの副次パラメーター
3 つの単一次元のピッカーには、主要な選択のほかに、追加のフィールドがあります。トランジション(Transition)とキャラクター FX(Character FX)には、それぞれ position、duration、intensity があります。キャラクターモーション(Character Motion)には position と pace があります。
これらのフィールドもカタログであり、ほかのすべての選択肢と同じ行の形を持ち、各リストの先頭には、何もしない auto があります。カタログはこれらを、options に加えて、dimensions として公開します。メインのピッカーは options から、ドロップダウンは dimensions から描画してください。ID だけを送るクライアントが、タイミングの一節を自分で書くことはありません。
const fx = getPickerCatalog("character-fx")!
fx.options // the effects of the main picker
fx.dimensions // [{ field: "position", ... }, { field: "duration", ... }, { field: "intensity", ... }]
// Each dimension's rows are also exported directly:
// TRANSITION_POSITIONS / TRANSITION_DURATIONS / TRANSITION_INTENSITIES
// CHARACTER_FX_POSITIONS / CHARACTER_FX_DURATIONS / CHARACTER_FX_INTENSITIES
// CHARACTER_MOTION_POSITIONS / CHARACTER_MOTION_PACESトランジションとキャラクター FX は、同じ ID を共有します。start、middle、end、full。instant、short、medium、long。subtle、natural、dynamic、crazy です。ただし、文言までは共有しません。トランジションの文言は「起こる」「クリップ全体にわたる」、エフェクトの文言は「現れる」「持続する」のように書かれています。行は必ず、そのノード自身のカタログから読み取ってください。キャラクターモーションは position の ID を共有し、それに加えて、独自の pace の ID(slow-motion、slow、natural、fast、explosive)を、独自の文言とともに持ちます。
複数次元のピッカーを実装する
複数次元のピッカーは、いくつかの独立したフィールドを同時に設定します。たとえばフレーミングは、ショットサイズ、アングル、カバレッジ、構図、撮影方向を設定します。そのカタログには、dimensions の中に、フィールドごとに 1 つの { field, label, options } エントリがあります。
import { getPickerCatalog, getParameterPromptHint } from "@nodaro/prompts"
const framing = getPickerCatalog("framing")!
// framing.dimensions = [
// { field: "shotSize", label: "Shot Size", options: [{ id: "close-up", ... }, ...] },
// { field: "angle", label: "Angle", options: [{ id: "low-angle", ... }, ...] },
// { field: "coverage", label: "Coverage", options: [...] },
// { field: "composition", label: "Composition", options: [...] },
// { field: "vantage", label: "Vantage", options: [...] },
// ]
function FramingPicker({ value, onChange }: {
value: Record<string, string>
onChange: (v: Record<string, string>) => void
}) {
return framing.dimensions!.map((dim) => (
<section key={dim.field}>
<h4>{dim.label}</h4>
{dim.options.map((o) => (
<button
key={o.id}
aria-pressed={value[dim.field] === o.id}
title={o.description}
onClick={() => onChange({ ...value, [dim.field]: o.id })}
>
{o.label}
</button>
))}
</section>
))
}
// Selection to clause: getParameterPromptHint composes every field that is set
const value = { shotSize: "close-up", angle: "low-angle", composition: "rule-of-thirds" }
const clause = getParameterPromptHint({ type: "framing", data: value })選択をプロンプトに変換する
getParameterPromptHint({ type, data }) は、単一次元でも複数次元でも、どの選択もその一節に変換します。Nodaro がサーバー上で実行しているのと同じ関数なので、あなたのプロンプトはエディターのものと一致します。カタログごとのビルダーもあります。複数次元のピッカー向けの buildFramingHints(value) や、1 つの選択肢向けの getMoodPromptHint(id) などです。
// Several pickers, one prompt, one generation
const clauses = [
getParameterPromptHint({ type: "mood", data: { mood: "serene" } }),
getParameterPromptHint({ type: "lens", data: { lens: "portrait-85mm" } }),
getParameterPromptHint({ type: "framing", data: { shotSize: "close-up", angle: "eye-level" } }),
]
const prompt = ["a portrait of a woman in a garden", ...clauses].filter(Boolean).join(", ")
const result = await client.nodes.runAndWait("generate-image", { prompt, provider: "nano-banana-2" })ピッカーの data に hintMode: "compact" を追加すると、完全な一節の代わりに、短い term を取得できます。これは、エディターのプロンプトヒントトグルのコンパクトモードです。フルとコンパクトを参照してください。
| 関数 | 内容 |
|---|---|
getParameterPromptHint({ type, data }) | どの選択も、組み立てられた一節に変換します。 |
build<Name>Hints(value) | buildFramingHints など、1 つのカタログの一節を組み立てます。 |
get<Name>PromptHint(id) | getMoodPromptHint など、1 つの選択肢の一節を返します。 |
PICKER_CATALOGS、getPickerCatalog、listPickerCatalogs | レジストリです。 |
ラベルを翻訳する
カタログのラベルは英語です。12 ロケール(en、es、fr、de、pt-BR、ru、hi、ja、ko、zh-CN、he、ar)の翻訳が、各カタログの catalogId をキーとして @nodaro/shared に同梱されています。promptHint と term の値は、モデルが読み取るため、英語のままです。
英語にはセットアップが不要です。それ以外のロケールでは、起動時に一度だけ翻訳バンドルを登録し、そのあとは同期的にラベルを取得します。フォールバックは英語です。
import { registerSidecarLoaders, ensureLocaleCatalogLoaded, resolveLabel } from "@nodaro/shared"
// 1. Once at startup, in a Vite app: wire the lazily loaded locale bundles
registerSidecarLoaders(import.meta.glob("/node_modules/@nodaro/shared/src/i18n/*.*.ts"))
// 2. Before rendering a locale, load that catalog's bundle
await ensureLocaleCatalogLoaded(mood.catalogId, "fr")
// 3. Resolve a label, synchronously; English when a translation is missing or not loaded yet
const label = resolveLabel(mood.catalogId, option.id, option.label, "fr")バンドルはオンデマンドで読み込まれるため、registerSidecarLoaders は、Vite の import.meta.glob が返すもののような、ローダーのマップを受け取ります。バックエンドとテストでは、翻訳を省略して、英語の label を使ってかまいません。
画像を表示する
自分のアプリでも、これらのピッカーについて、エディターと同じ画像を表示できます。
- 写真。人物、スタイリング(Styling)、手に持つ小道具(Held Prop)、素材(Material)、動物(Animal)に表示されます。
- アート。音楽と音声のピッカー、音楽ジャンル(Music Genre)、音楽のムード(Music Mood)、楽器編成(Instrumentation)、声の特徴(Voice Character)、話し方(Voice Delivery)に表示されます。
- プレビュー静止画。見た目系のピッカーに表示されますが、Nodaro Cloud だけです。対象は、スタイル(Style)、カラー/ルック(Color / Look)、年代/時代(Era / Period)、レンズ、ムードです。ほかに、大気効果(Atmosphere)、構図エフェクト(Composition Effect)、カメラ/フィルム(Camera / Film)、フレーミング、ライティング(Lighting)、カメラモーション(Camera Motion)も含まれます。
API 経由の場合、画像がある選択肢には、問い合わせたインストール環境上の絶対 URL である imageUrl が付き、画像がない選択肢には何も付きません。人物とスタイリングは sections も返します。これは、各トピックを順番に並べたもので、それぞれに丸い画像が付きます。URL の規則は、後述の API でカタログを読み取るにあります。
ライブラリの場合、@nodaro/prompts が、同じデータから同じ URL を組み立てます。
- 選択肢には
pickerOptionImageUrl(catalog, field, id, { baseUrl })。 - 人物やスタイリングのトピックには
pickerSectionImageUrl(topicLabel, { baseUrl })。
baseUrl は、ファイルを配信する Nodaro のインストール環境です。画像は npm パッケージにではなく、インストール環境に属します。lookPreviews: true は、Nodaro Cloud に対してだけ渡してください。それ以外のピッカーについては、label、description、category から、自分で見た目を作成してください。
API でカタログを読み取る
どちらのエンドポイントも公開されていて、トークンは不要で、5 分間キャッシュされます。
| メソッド | パス | 返す内容 |
|---|---|---|
GET | /v1/picker-catalogs | すべてのピッカーの一覧です。nodeType、label、catalogId、kind、valueField または fields、optionCount、そして画像がある選択肢の数である imageCount が含まれます。 |
GET | /v1/picker-catalogs/:nodeType | 1 つのピッカーのカタログです。不明なタイプには 404 not_found が返ります。 |
GET /v1/picker-catalogs/:nodeType は、3 つのクエリパラメーターを受け取ります。不正な値には 400 validation_error が返ります。
| パラメーター | 値 | 動作 |
|---|---|---|
detail | compact(デフォルト)または full | compact は id、label、category、term、icon、imageUrl を返します。full は、各選択肢の description と promptHint を追加します。 |
category | カテゴリー ID | 単一次元のピッカーを、1 つのカテゴリーに絞り込みます。 |
field | フィールド名 | 複数次元のピッカーの 1 つの次元、またはトランジション、キャラクター FX、キャラクターモーションの副次フィールドの 1 つを返します。 |
curl -s https://app.nodaro.ai/v1/picker-catalogs/mood | jq '.data.options[0]'{ "id": "happy", "label": "Happy", "category": "positive", "term": "happy expression",
"imageUrl": "https://cdn.nodaro.ai/cdn-cgi/image/width=480,format=auto,quality=80/images/710df65a-3c1e-485b-b8b7-29f7b3baf479.png" }画像の URL
| ピッカー | 画像 |
|---|---|
person、styling、held-prop、material、animal | 写真です。WebP、幅は最大 480 px です。 |
music-genre、music-mood、instrumentation、voice-character、voice-delivery | 3D の絵文字画像(WebP、128 px)または国旗の画像(WebP、幅 120 px)です。 |
style、color-look、lens、framing、lighting、mood、camera-format、camera-motion などの見た目系のピッカー | Nodaro Cloud では、Nodaro CDN から配信される、レンダリング済みプレビューの 480 px の静止画です。camera-motion の場合はクリップの 1 フレームです。セルフホスティング環境では、何も返りません。 |
- ホスト。インストール環境は、自分の画像を
/picker-art/の下で配信するため、imageUrlはその公開アドレスを使います。Nodaro Cloud ではhttps://app.nodaro.ai、セルフホスティング環境ではPUBLIC_URLです。各 URL は、与えられたとおりに使ってください。選択肢の ID から自分で組み立てないでください。 - キャッシュ。ファイル名にはコンテンツのハッシュが含まれるため、画像が変わると URL も変わります。ファイルは
Cache-Control: public, max-age=31536000, immutableとAccess-Control-Allow-Origin: *付きで配信されるため、どのオリジンからでも、<img>、fetch、キャンバスで読み込めます。 - トピック。
personとstylingはsectionsも返します。それぞれにlabel、まとめるfields、任意の丸いimageUrlが含まれます。
curl -s https://app.nodaro.ai/v1/picker-catalogs/person | jq '.data.sections[0], .data.dimensions[0].options[0]'{ "label": "Identity", "fields": ["type", "age", "ethnicity", "regionalAesthetic"],
"imageUrl": "https://app.nodaro.ai/picker-art/character/sections/identity.2d5ec1a4.webp" }
{ "id": "man", "label": "Man", "term": "man",
"imageUrl": "https://app.nodaro.ai/picker-art/character/person/man.441363db.webp" }デプロイメントのキュレーションされたカタログ
GET /v1/catalogs は、すべてのカタログを 1 回の呼び出しで、1 つのフラットな形として返します。デプロイメントは、選択肢を置き換え、追加、除外するベンダーパックを使って、自分のカタログをキュレーションでき、このエンドポイントはそのキュレーションを反映します。デプロイメントがパックを登録している場合、レスポンスには curated: true と、data にカタログが含まれます。登録していない場合は curated: false になり、同梱されているカタログは、ピッカーごとに /v1/picker-catalogs/:nodeType から読み取ります。SDK のメソッドは client.catalogs.list() です。
説明文からピッカーを埋める
POST /v1/text-to-picker は、シーンやショットの自由記述の説明文から、ピッカーの値を選びます。これは AI Fill 機能です。トークンが必要で、LLM の呼び出しとして課金されます。返されるのは、ピッカーのタイプ、次元、選ばれた ID の順にキーが付いた pickerJson と、どのカタログの選択肢にも当てはまらなかった説明内容である gaps です。SDK のメソッドは client.pickerCatalogs.analyzeText()、CLI のコマンドは nodaro pickers analyze です。
キャラクターモーションのメタデータ
キャラクターモーションのカタログの選択肢は、両方の詳細レベルで motion メタデータを持つことがあります。このメタデータは、動きを次のように説明します。
- 必要条件、開始と終了のポーズ、そして動作後の可視性と手の状態です。
- 手が空いている必要があるか、その種類、固定のペース、対になる動きです。
- 検索用の別名、そして ID が廃止されているかどうかと、その代わりとなる ID です。
フィールドがない場合は、不明を意味します。
保存されたワークフローを読み込むときは、廃止された ID も動作するようにし、新しい選択肢には表示しないでください。この型は CharacterMotionMetadata で、@nodaro/prompts からエクスポートされています。
よくある質問
関連ページ
クリエイティブコントロール
ムード
TypeScript SDK
MCP ツールリファレンス
コマンド
最終更新