הרצת רכיבים
הרצת כל רכיב של Nodaro מ-TypeScript בלי תהליך: גילוי סוגי רכיבים, התחלת הרצות, המתנה לתוצאות ושליחה של ייחוסים ושל הכוונת מצלמה.
client.nodes מחזיר את רשימת סוגי הרכיבים ששרת Nodaro תומך בהם, ומריץ כל אחד מהם ישירות, בלי לבנות תהליך. הרצה שולחת את הפרמטרים שלכם לנתיב של הרכיב עצמו, POST /v1/<type> ברוב סוגי הרכיבים, ומחזירה משימה שאפשר להמתין לה. זה אותו נתיב שה-CLI משתמש בו ב-nodaro nodes run ושכלי ה-MCP של Nodaro משתמשים בו. לגרסת ה-REST, ראו את דף ה-API הרצת רכיב יחיד.
מתודות
| מתודה | מה היא עושה |
|---|---|
nodes.list() | רשימת כל סוגי הרכיבים, עם המודלים והמחיר בקרדיטים של כל אחד |
nodes.get(type) | קריאת סוג רכיב אחד |
nodes.run(type, params?, options?) | התחלת רכיב והחזרה מיידית של מזהה המשימה שלו |
nodes.quote(type, params?) | אומדן מחיר להרצה לפני שמתחילים אותה |
nodes.runAndWait(type, params?, opts?) | התחלת רכיב, בדיקת הסטטוס של המשימה שלו והחזרת הפלט |
nodes.runMany(type, paramsList, opts?) | התחלה של כמה הרצות של רכיב אחד בבת אחת, והמתנה לכולן |
nodes.runBatchAndWait(type, params, opts?) | יצירת כמה תמונות בקריאה אחת לרכיב יצירת תמונה, והמתנה לכל אחת מהן |
client.nodes
list()
מחזירה את כל סוגי הרכיבים שהשרת תומך בהם. השרת עשוי לשמור את התשובה במטמון למשך 5 דקות. הקריאה לא עולה כלום ולא דורשת הרשאות.
list(): Promise<{ data: NodeDescriptor[] }>const { data: nodes } = await client.nodes.list()
const imageGenerators = nodes.filter((n) => n.category === "ai-image")
const takesReferences = nodes.filter((n) => n.capabilities?.includes("supports-reference-image"))לכל NodeDescriptor יש השדות האלה:
| שדה | סוג | תיאור |
|---|---|---|
type | string | הסוג ב-API, למשל generate-image. העבירו אותו ל-run(). |
label | string | השם של הרכיב בעורך. |
category | string | הקטגוריה, למשל ai-image, ai-video, ai-audio, ai-text, processing או parameter. |
description | string | תיאור בשורה אחת. |
outputType | string | text, image, video, audio, data או none. |
creditCost | number | string | המחיר בקרדיטים שנגבה על הרצה, אותו מספר שמופיע בכפתור הרצה של הרכיב: מספר כשהמחיר קבוע, או טווח כגון "3-682" כשהמחיר נקבע לפי המודל. ברכיבים קיצוץ וידאו, לולאת וידאו ושילוב סרטונים, הערך הוא במקום זאת המחיר של מדרגה אחת של 5 שניות, והרצה עולה כמה מדרגות כאלה. ב-Nodaro Cloud בלבד. |
estimate | boolean | הערך הוא true כשהשדה creditCost הוא אומדן: הקריאה הטיפוסית של רכיב LLM עם חיוב לפי השימוש, במודל ברירת המחדל שלו. הציגו אותו כ-≈N. רכיב LLM עם חיוב לפי השימוש, שלמודל ברירת המחדל שלו עדיין אין מחיר, מופיע ברשימה עם creditCost: "unpriced". |
creditRate | NodeCreditRate | לרכיב שהמחיר שלו נקבע לפי יחידה של מדד משלו, כגון רכיב מסגרות דוברים (עם creditCost שערכו "per-1000-frames"): { identifier, unit, creditsPerUnit, minUnits, rounding, note }. הרצה של N יחידות עולה Math.ceil(Math.max(minUnits, N) * creditsPerUnit), ומעגלים פעם אחת בלבד. |
providers | string[] | מזהי המודלים שהרכיב יכול להריץ, בשביל הפרמטר provider. |
capabilities | string[] | דגלים, כגון supports-reference-image או supports-end-frame. |
inputSchema | { fields } | שדות הקלט שאפשר לקבוע, כל אחד עם key, type, required ו-options. |
maxDurationSec | number | משך הזמן הארוך ביותר שהרכיב מקבל, ברכיבים שיש להם מגבלה כזו. |
providerResolutions | Record<string, string[]> | הרזולוציות שכל מודל מקבל, כשהן שונות בין המודלים. |
בהתקנות של מהדורת Community ומהדורת Business באירוח עצמי אין מערכת קרדיטים, ולכן המתארים שלהן לא כוללים את creditCost.
get(type)
מחזירה את המתאר של סוג רכיב אחד.
get(type: string): Promise<{ data: NodeDescriptor }>מאפיין
סוג
const { data: node } = await client.nodes.get("generate-video")
console.log(node.providers) // every video model id
console.log(node.creditCost) // Nodaro Cloud onlyכדי להציג מחירים ליד המודלים, העבירו את node.providers ל-client.credits.modelCosts().
run(type, params?, options?)
מתחילה רכיב אחד ומחזירה תשובה מיד. גוף הבקשה נשלח לנתיב של הרכיב, POST /v1/<type> ברוב סוגי הרכיבים. שמות השדות זהים לשדות הקלט של הרכיב.
run(type: string, params?: Record<string, unknown>, options?: { idempotencyKey?: string }): Promise<RunNodeResult>מאפיין
סוג
const result = await client.nodes.run("generate-image", {
prompt: "A snow leopard in the mountains",
provider: "nano-banana-2",
})
if ("jobId" in result) {
const { data: job } = await client.jobs.getStatus(result.jobId)
console.log(job.status)
}סוגי רכיבים עם נתיב משלהם. כמה סוגי רכיבים רצים בנתיב אחר, והמתודה run() שולחת אליו בשבילכם:
| סוגי רכיבים | נתיב |
|---|---|
generate-3d-scene, edit-3d-scene | /v1/3d-scene/generate, /v1/3d-scene/edit |
llm-chat, after-effects, motion-graphics, lottie-overlay, 3d-title | /v1/<type>/generate |
image-to-text | /v1/image-to-text/describe |
video-composer | /v1/scene-graph/generate |
telegram-channel-feed | /v1/telegram-channel/fetch |
כל רכיב suno-*, כגון suno-generate ו-suno-cover | /v1/suno/<name>. הרכיב suno-voice משתמש ב-/v1/suno/voice/generate. |
instagram-post, tiktok-post, youtube-upload, linkedin-post, x-post, facebook-post, telegram-post, publish-social | /v1/social/publish |
ugc-creator, ugc-script, ugc-clips, ugc-clip, ugc-cards | /v1/ugc/creator, /v1/ugc/script וכן הלאה. ב-Nodaro Cloud בלבד. |
render-video עם planType | /v1/render-video/plan |
נתיב הפרסום דורש platform. רכיב פרסום של רשת אחת, כגון x-post, ממלא אותו לפי הסוג שלו כשלא שולחים אותו. הרכיב publish-social מקבל את ה-platform ששולחים.
סוגי רכיבים שלא רצים לבד. קריאה לסוג רכיב בלי נתיב משלו נכשלת עם NodaroError שה-code שלו הוא node_not_runnable, בלי שום פנייה ל-API. ההודעה מציינת מה להריץ במקומו:
- הרכיב
modify-imageרץ דרךimage-to-image, או דרךedit-imageבמודלnano-banana-edit. - הרכיבים
upscale-imageו-remove-backgroundרצים דרךedit-image. - הרכיב
image-to-videoרץ דרךgenerate-video. - הרכיבים
composite,manual-editו-paint-maskרצים רק בתוך תהליך. הרכיביםsceneו-generative-pipelineרצים רק בתוך פייפליין.
קריאה לסוגי רכיבים שרצים רק בתוך תהליך, כגון קלטים, טריגרים, כלי עזר ובוררים (upload-image, combine-text), נכשלת באותו אופן ברגע שה-API עונה שאין לו נתיב בשבילם. שגיאת 404 על משאב חסר, כגון מזהה דמות שלא קיים, נשארת NotFoundError.
בקשה עם מודל שהפריסה הזו לא מציעה, או עם מודל שמנהל כיבה, נדחית לפני שמשוריינים קרדיטים. הקריאה נכשלת עם ModelUnavailableError, וה-code הוא model_not_available או model_disabled. בחרו מודל אחר: ניסיון חוזר לא ישנה כלום.
מה חוזר. רוב סוגי הרכיבים הם אסינכרוניים: התוצאה כוללת jobId, ו-worker מבצע את היצירה. בדקו את הסטטוס עם client.jobs.getStatus(jobId) מדי כמה שניות עד שהמשימה מסתיימת, או השתמשו ב-runAndWait(). כמה סוגי רכיבים סינכרוניים, כגון meta-ads-scrape, מחזירים את התוצאה המלאה שלהם מיד, בלי jobId. בדקו אם יש jobId, ופעלו לפי זה.
תיקוני פרמטרים. בסוגי רכיבי התמונה (generate-image, image-to-image ו-edit-image), השרת עשוי לתקן ערך שהמודל שנבחר לא מקבל. ההרצה ממשיכה עם הערך המתוקן, והקרדיטים שמשוריינים תואמים אותו. התוצאה כוללת אז את adjustments, פריט אחד לכל שדה שתוקן:
const result = await client.nodes.run("generate-image", {
prompt: "A snow leopard",
provider: "gpt-image-2",
aspectRatio: "3:2",
})
if ("adjustments" in result && result.adjustments?.length) {
for (const a of result.adjustments) {
console.warn(`${a.field}: ${a.from} -> ${a.to ?? "(dropped)"} (${a.reason})`)
}
}בכל תיקון יש field (aspectRatio, resolution, quality או duration), from, to ו-reason. כששום דבר לא השתנה, השדה adjustments לא מופיע.
המתודה זורקת InsufficientCreditsError כשאין בחשבון מספיק קרדיטים, StorageExceededError כשהאחסון מלא ו-JobBlockedError כשמדיניות תוכן של הפריסה דוחה את הבקשה. ראו את הדף שגיאות.
quote(type, params?)
נותנת אומדן מחיר להרצה לפני שמתחילים אותה, עם POST /v1/quote. העבירו בדיוק את גוף הבקשה שהייתם מעבירים למתודה run. הפלטפורמה מתמחרת אותו עם הקוד של נתיב ההרצה עצמו: אותה בדיקת תקינות, אותה מדידה של קליפי ייחוס, אותו מזהה קרדיטים ואותו סכום. שום דבר לא מתחיל, ולא נגבים קרדיטים. ב-Nodaro Cloud בלבד.
quote(type: string, params?: Record<string, unknown>): Promise<NodeQuote>למתודה יש טיפוסים ל-text-to-video, ל-generate-video, ל-video-to-video ול-video-upscale (ההשלמה ב-1080p של טיוטה ב-Seedance 2.5 מתומחרת לפי הטיוטה): הסוגים שהפלטפורמה יכולה לתת להם אומדן מחיר כרגע. קריאה עם כל סוג אחר נדחית עם 400 quote_unsupported.
const q = await client.nodes.quote("video-to-video", {
videoUrl, prompt: "make it black and white", provider: "seedance-2-5", resolution: "480p",
})
q.reserve // credits held when the run starts
q.expected // what the run should actually cost, when knownהטיפוס NodeQuote הוא { identifier, reserve, expected?, adjustments, warnings }. ראו בדף ה-API אומדני מחיר להרצה לכל השדות והקודים.
runAndWait(type, params?, opts?)
מריצה רכיב אסינכרוני אחד עד הסוף. המתודה קוראת ל-run(), לוקחת את ה-jobId ובודקת את הסטטוס עם client.jobs.getStatus() מדי כמה שניות, עד שהמשימה מסתיימת. כשהסטטוס הוא completed, היא מחזירה את הפלט של המשימה.
runAndWait(type: string, params?: Record<string, unknown>, opts?: RunAndWaitOptions): Promise<NodeJobOutput>מאפיין
סוג
const output = await client.nodes.runAndWait(
"generate-video",
{ prompt: "Rain falls on a neon street at night", provider: "seedance-2-fast", duration: 4 },
{ onProgress: (s) => console.log(`${s.progress ?? 0}%`) },
)
console.log(output.videoUrl, output.thumbnailUrl)במשימת תמונה, הטיפוס NodeJobOutput כולל גם את גודל התמונה בפיקסלים, כך שלקוח יכול לסדר רשת לפני שהתמונות נטענות:
| שדה | סוג | תיאור |
|---|---|---|
imageUrl | string | התמונה, או הראשונה מביניהן כשהמשימה יצרה כמה תמונות. |
imageUrls | readonly string[] | כל התמונות, כשהמשימה יצרה יותר מתמונה אחת. |
width, height | number | הגודל של imageUrl בפיקסלים, כפי שהקובץ שמור, אחרי שהכיוון לפי EXIF הוחל. סימן המים של המסלול החינמי כלול. |
images | readonly JobOutputImage[] | אובייקט { url, width?, height? } אחד לכל פריט ב-imageUrls, באותו סדר. בפריט בלי גודל, אי אפשר היה למדוד את התמונה. |
ארבעת שדות הגודל הם אופציונליים. במשימות ישנות יותר הם חסרים, והשרת אף פעם לא מנחש גודל שהוא לא הצליח לקרוא.
const output = await client.nodes.runAndWait("generate-image", { prompt: "a snow leopard in the mountains" })
console.log(output.imageUrl, output.width, output.height)
for (const image of output.images ?? []) console.log(image.url, image.width ?? "?", image.height ?? "?")הפלט הוא NodeJobOutput: השדה imageUrl ברכיבי תמונה, videoUrl ו-thumbnailUrl ברכיבי וידאו, audioUrl ברכיבי אודיו ועוד כל שדה אחר שהרכיב כותב. רכיב הפרדת אודיו, למשל, מוסיף כתובת לכל סטם, כגון vocalUrl ו-instrumentalUrl.
אלה השגיאות עם טיפוסים שהמתודה זורקת:
| שגיאה | מתי |
|---|---|
NodaroError עם הקוד batch_requires_run_batch_and_wait | בקשת generate-image עם count גדול מ-1 או עם models יוצרת כמה משימות. המתודה runAndWait() דוחה אותה לפני שנשלח משהו. השתמשו ב-runBatchAndWait(). |
InsufficientCreditsError, StorageExceededError, JobBlockedError | בקשת ההרצה נדחתה, לפני כל בדיקת סטטוס. |
ModelUnavailableError | הפריסה הזו לא מציעה את המודל, או שמנהל כיבה אותו. ההרצה נדחית לפני שמשוריינים קרדיטים. בחרו מודל אחר. |
JobFailedError | המשימה הסתיימה בסטטוס failed או cancelled. השגיאה כוללת את jobId ואת הודעת השגיאה של המשימה. |
JobTimeoutError | הזמן שב-maxMs עבר. המשימה לא מבוטלת. |
JobAbortedError | ה-signal שלכם ביטל את ההמתנה. המשימה לא מבוטלת. |
JobHeldError | המשימה ממתינה לבדיקה של אדם, בפריסות שיש להן מדיניות תוכן. |
התאוששות איטית. לפעמים מודל מוסר את התוצאה שלו אחרי שה-worker כבר ויתר עליה. המשימה נשארת אז בסטטוס processing עם recovering: true בזמן שהפלטפורמה מתקנת אותה, ובמודלים איטיים זה יכול לקחת עשרות דקות. אם השגיאה JobTimeoutError מסיימת את ההמתנה שלכם, שלפו את המשימה מאוחר יותר עם client.jobs.get(jobId), או הגדילו את maxMs.
runMany(type, paramsList, opts?)
מתחילה כמה הרצות של סוג רכיב אחד באותו זמן וממתינה לכולן, למשל כדי ליצור רשת של מועמדים. כל פריט רץ דרך runAndWait().
runMany(type: string, paramsList: Record<string, unknown>[], opts?: RunAndWaitOptions): Promise<RunManyResult[]>מאפיין
סוג
const results = await client.nodes.runMany("generate-image", [
{ prompt: "A snow leopard at sunrise" },
{ prompt: "A snow leopard at golden hour" },
{ prompt: "A snow leopard at blue hour" },
])
for (const { jobId, output } of results) console.log(jobId, output.imageUrl)המתודה מחזירה תשובה כשכל ההרצות הסתיימו: אובייקט { jobId, output } אחד לכל פריט, בסדר של הקלט. היא נכשלת ברגע שהרצה כלשהי נכשלת, עם אותן שגיאות כמו runAndWait(). פריט שהוא בעצמו אצווה, עם count גדול מ-1 או עם models, נדחה לפני שנשלח משהו. כדי לבחור אחר כך את התוצאה הטובה ביותר, העבירו את הכתובות ל-client.reduce.run().
runBatchAndWait(type, params, opts?)
יוצרת כמה תמונות בקריאה אחת לרכיב יצירת תמונה, וממתינה לכל אחת מהן. השתמשו ב-count כדי לקבל מ-1 עד 4 תמונות, כל אחת במשימה משלה. השתמשו ב-models כדי לשלוח את אותה בקשה אל 2–4 מודלי תמונה, במקום provider אחד. כשמשתמשים בשניהם, הפרמטר count חל על כל מודל, עד 8 תמונות בסך הכול.
runBatchAndWait(
type: "generate-image",
params: GenerateImageParams,
opts?: RunAndWaitOptions,
): Promise<GenerateImageBatchOutput>המתודה שולחת את האצווה פעם אחת, ואז ממתינה לכל משימה כמו ש-runAndWait() ממתינה. האצווה נבדקת מול היתרה שלכם, והיא מחויבת כולה או לא מחויבת בכלל. עם opts.idempotencyKey, המפתח של תמונה מספר i הוא <key>:<i>, ולכן ניסיון חוזר מחזיר את אותן משימות ולא נגבים קרדיטים פעם נוספת. הפרמטר presetId משתלב עם שתי האפשרויות: מספר תמונות לפי count מהבקשה של הערכה, או הערכה שמוחלת פעם אחת לכל מודל.
const { batch, results } = await client.nodes.runBatchAndWait(
"generate-image",
{ prompt: "a lighthouse at dusk", models: ["gpt-image-2", "flux-2-max"], count: 2, seed: 41 },
{ idempotencyKey: crypto.randomUUID() },
)
console.log(batch.batchId, batch.totalCredits)
for (const r of results) {
if (r.status === "completed") console.log(r.model, r.output.imageUrl)
else console.warn(r.model, r.jobId, r.error.message)
}המתודה מחזירה { batch, results }:
batchהוא התשובה לשליחה, מסוגGenerateImageBatchResult. יש בוjobId(המשימה הראשונה),jobIds(מודל אחר מודל, ובתוך כל מודל תמונה אחר תמונה),batchId,groups({ model, jobIds, credits?, adjustments? }לכל מודל) ו-totalCredits. גם המתודהnodes.run("generate-image", …)מחזירה את אותו אובייקט כשהפרמטרים קובעיםcountגדול מ-1 אוmodels.resultsכוללBatchJobOutcomeאחד לכל משימה, בסדר שלbatch.jobIds. כל אחד מהם הוא{ jobId, model, status: "completed", output }או{ jobId, model, status: "error", error }. השדהerrorהוא השגיאהJobFailedError,JobHeldErrorאוJobTimeoutErrorשסיימה את ההמתנה. תמונה אחת שנכשלה אף פעם לא מבטלת את התמונות האחרות.
המתודה נכשלת רק לפני שקיימת משימה כלשהי, עם השגיאות של השליחה עצמה, כגון InsufficientCreditsError עם הסכום הכולל של האצווה ב-required. היא נכשלת גם עם JobAbortedError כשה-signal שלכם מבטל את ההמתנה. בקשה לתמונה אחת נדחית לפני שנשלח משהו, עם הקוד not_a_batch: המתינו לה עם runAndWait(). עם seed, תמונה i מקבלת seed + i. כדי למצוא מאוחר יותר את המשימות של אצווה, השתמשו ב-client.jobs.list({ batchId }).
פרמטרים עם טיפוסים
לסוגי הרכיבים האלה יש פרמטרים עם טיפוסים, ולכן עורך הקוד שלכם משלים את השדות שלהם ובודק אותם. כל סוג רכיב אחר מקבל אובייקט רגיל, והשדות שלו הם שדות הקלט של הרכיב, שמפורטים ב-inputSchema ובדף שלו במדריך הרכיבים. גם לרכיבי סצנות התלת־ממד יש פרמטרים עם טיפוסים: ראו את הדף סצנות תלת־ממד.
| סוג הרכיב | טיפוס הפרמטרים | דף הרכיב |
|---|---|---|
generate-image | GenerateImageParams | יצירת תמונה |
image-to-image | ImageToImageParams | עריכת תמונה |
edit-image | EditImageParams | הגדלת תמונה |
split-image | SplitImageParams | |
generate-mask | GenerateMaskParams | יצירת מסכה |
generate-video | GenerateVideoParams | יצירת וידאו |
text-to-video | TextToVideoParams | יצירת וידאו |
video-to-video | VideoToVideoParams | וידאו לווידאו |
assemble-narrated-video | AssembleNarratedVideoParams | הרכבת וידאו עם קריינות |
video-depth | VideoDepthParams | עומק וידאו |
video-upscale | VideoUpscaleParams | הגדלת וידאו |
כל אובייקט פרמטרים עם טיפוסים מקבל גם שדות אחרים של הנתיב. השרת בודק את התקינות של גוף הבקשה כולו.
GenerateImageParams
מאפיין
סוג
גם השדות strength ו-guidanceScale מוגדרים בטיפוס GenerateImageParams.
ערכות ברכיב יצירת תמונה
הפרמטר presetId מחיל ערכה בדיוק כמו שהעורך מחיל אותה: הפרומפט, הטקסט לפני ואחרי, ערכי ברירת המחדל של המשתנים, הסגנון, הפרומפט השלילי וההגדרות. כך המשימה זהה לזו שהכפתור הרצה בעורך היה יוצר. השתמשו במזהה מובנה מ-presets.listFactory("generate-image"), או באחת הערכות שלכם. שדות שאתם מעבירים גוברים על הערכה.
משתנה בלי ברירת מחדל צריך ערך ב-presetVariables. בלי ערך, הקריאה נדחית עם 400 preset_variables_required, והשגיאה מציינת את המשתנה.
await client.nodes.runAndWait("generate-image", {
presetId: "generate-image/logo-wordmark",
presetVariables: { BRAND: "Acme" },
})GenerateVideoParams
הנתיב מתמונה לווידאו: פריים פתיחה, פריים סיום אופציונלי וייחוסים.
מאפיין
סוג
TextToVideoParams
הנתיב לווידאו מפרומפט בלבד, POST /v1/text-to-video. הפרומפט נדרש, ופריימי פתיחה וסיום שייכים ל-generate-video. בקשה למודל בלי מצב של טקסט לווידאו נדחית עם 400 image_required.
מאפיין
סוג
דחיות בגלל זכויות יוצרים
הטיפוס TextToVideoParams מקבל contentPolicyRewrite?: boolean. כשהשדה חסר או true, אחרי דחייה בגלל זכויות יוצרים יש ניסיון חוזר אחד עם פרומפט בניסוח אחר. עם false, דחייה בגלל זכויות יוצרים מכשילה את המשימה.
טיוטות ב-Seedance 2.5
הטיפוסים GenerateVideoParams ו-TextToVideoParams מקבלים draft: true. ב-seedance-2-5, ההרצה היא טיוטה ב-480p במחיר של הרצה ב-480p. השלימו את הטייק שאהבתם עם run("video-upscale", { provider: "seedance-2-5-hd", sourceJobId }): אותו טייק, מרונדר מחדש ב-1080p, במחיר שנקבע לפי האורך של הטיוטה. מקור שהוא לא טיוטה שלכם שהסתיימה נדחה עם קוד 4xx לפני שנגבים קרדיטים. ראו את הסעיף מצב טיוטה ב-Seedance 2.5 בדף יצירת וידאו.
const draft = await client.nodes.run("generate-video", { prompt, provider: "seedance-2-5", draft: true, duration: 8 })
// Wait for the draft and review it. When you like the take, finalize it at 1080p.
if ("jobId" in draft) {
const final = await client.nodes.runAndWait("video-upscale", { provider: "seedance-2-5-hd", sourceJobId: draft.jobId })
console.log(final.videoUrl)
}הגדלת וידאו עם Topaz. הטיפוס VideoUpscaleParams מקבל targetResolution ("720p", "1080p" או "4k", לפי הצלע הקצרה של הפריים; ברירת המחדל היא 1080p) ו-targetFps (מ-15 עד 60; ברירת המחדל היא הקצב של המקור עצמו): run("video-upscale", { videoUrl, targetResolution: "4k", targetFps: 60 }). ב-Topaz החיוב הוא לפי שימוש. ראו את הסעיף קרדיטים בדף הגדלת וידאו. הפרמטר upscaleFactor מיושן. השרת עדיין מקבל אותו ומחיל אותו על הצלע הקצרה של המקור.
VideoToVideoParams
נתיב עריכת הווידאו, POST /v1/video-to-video. עריכה ב-seedance-2-5 נבנית בשרת, ולכן שולחים את אותו גוף בקשה כמו לכל מודל עריכה אחר. ראו את הדף וידאו לווידאו.
מאפיין
סוג
הטיפוס כולל גם את audio, multiShots, videoEditDuration, audioSetting ו-promptExtend למודלים שמקבלים אותם, ובנוסף את sessionId ו-origin. כל מודל אחר דוחה את שלוש רשימות הייחוסים. המספור של הייחוסים והמגבלות מופיעים בדף וידאו לווידאו.
נתיבי תמונה עם טיפוסים
ל-image-to-image, ל-edit-image, ל-split-image ול-generate-mask יש ב-run overloads עם טיפוסים. לשלושת הסוגים שמתחילים משימה יש אותם גם ב-runAndWait. כל טיפוס פרמטרים מבוסס על רשימות הערכים של הפלטפורמה עצמה, כגון ModifyImageProvider, ImageEditProvider, ImageAspectRatio ו-ImageResolution, שה-SDK מייצא מחדש. כל שדה אחר של הנתיב עדיין עובר.
הבדיקה בזמן ההידור חלה כשגוף הבקשה מוגדר מטיפוס הפרמטרים: const params: EditImageParams = …, או { … } satisfies EditImageParams בתוך הקריאה. גוף בקשה שנכתב ישירות בתוך הקריאה, וה-overload עם הטיפוסים דוחה אותו, עדיין עובר הידור. הוא נופל ל-overload הכללי run(type: string, …), שאין לו טיפוסים, והנתיב מחזיר 400. השתמשו ב-satisfies כדי לקבל את הבדיקה.
image-to-image,edit-imageו-generate-mask. המתודהrunמחזירהImageJobStarted, כלומר{ jobId: string; adjustments? }, ולכן השדהresult.jobIdלא צריך המרת טיפוס.ImageToImageParamsדורשimageUrlו-prompt. השדהmaskUrlשלו (הלבן הוא האזור לשינוי) נשלח למודל כמסכה בפני עצמה, ולכן רק המודליםideogram-editו-flux-fillמשתמשים בו.EditImageParamsהוא אחת משתי צורות. הוא מקבלimageUrlבכל מודל, חוץ מפעולות ה-task של Grok. בהן הוא מקבלtaskIdעםprovider: "grok-2-edit" | "grok-2-segment": מזהה ה-task של יצירה קודמת ב-Grok Imagine 2, ששמור בנתוני הפלט של המשימה ההיא. גוף בקשה עם טיפוסים ששולח את שניהם, אוtaskIdעם מודל אחר, לא עובר הידור. מודל ברירת המחדל הואrecraft-upscale. השדהpromptנדרש ב-nano-banana-editוב-grok-2-edit. השדהmaskIndexesמיועד ל-grok-2-editבלבד.split-imageלא עולה כלום ומחזיר תשובה מיד. הוא לא יוצר משימה, ולכן המתודהrunAndWaitלא רלוונטית לו. המתודהrunמחזירהSplitImageResult, כלומר{ images: { name, url }[] }: קובץ PNG אחד לכל אריח, בסדר שלnames. ב-namesחייבים להיות בדיוקgridCols × gridRowsפריטים, וכל אחד מ-gridColsו-gridRowsהוא בין 1 ל-6.generate-maskהוא הדרך של ה-SDK להתחיל משימה של רכיב יצירת מסכה. הקריאהrunAndWait("generate-mask", …)מחזירהGenerateMaskJobOutput: השדהmaskUrl, קובץ ה-PNG של המסכה, שבו הלבן הוא הנושא, והשדהimageUrl, תמונת המקור, שמועברת בלי שינוי.
import type { EditImageParams, GenerateImageParams, GenerateMaskParams } from "@nodaro/sdk"
const { maskUrl } = await client.nodes.runAndWait("generate-mask", { imageUrl, prompt: "the red car" } satisfies GenerateMaskParams)
await client.nodes.runAndWait("generate-image", { prompt: "a blue car", baseImageUrl: imageUrl, maskUrl } satisfies GenerateImageParams)
const { jobId } = await client.nodes.run("edit-image", { imageUrl, provider: "topaz-image-upscale", upscaleFactor: "4" } satisfies EditImageParams)VideoDepthParams
הרכיב הופך קליפ לסרטון עומק, שבו מה שקרוב בהיר ומה שרחוק כהה (POST /v1/video-depth). במשימה שהסתיימה יש videoUrl ו-thumbnailUrl. המחירים ומגבלות האורך מופיעים בדף עומק וידאו.
מאפיין
סוג
השרת מתעלם מהגדרה שהספק שנבחר לא מקבל, ולכן החלפת ספק אף פעם לא מכשילה בקשה. ערך מחוץ לרשימות שלמעלה נדחה עם 400 validation_error. הקליפ נמדד לפני שמשוריינים קרדיטים. קליפ ארוך מדי נדחה עם 400 video_too_long: יותר מ-2,400 פריימים או מ-300 שניות ב-video-depth-anything ויותר מ-80 שניות ב-depth-anything-frames. קליפ שאי אפשר לקרוא נדחה עם 400 video_unreadable.
const { videoUrl } = await client.nodes.runAndWait("video-depth", {
videoUrl: "https://cdn.example.com/clip.mp4",
colormap: "turbo",
resolution: "720p",
})AssembleNarratedVideoParams
הרכיב מאחד מקטעי וידאו עם קריינות לסרטון אחד. המחיר של ההרצה נקבע לפי מספר המקטעים, והיא עולה 44–143 קרדיטים: 3 יחידות ועוד יחידה אחת לכל 6 מקטעים, או חלק מהם. איך כל מקטע מותאם לקריינות שלו מוסבר בדף הרכבת וידאו עם קריינות.
מאפיין
סוג
ייחוסים
הרכיבים generate-image, generate-video ו-text-to-video מקבלים ייחוסים כמו שהעורך מחבר אותם. השרת הופך אותם בפרומפט להוראות ממוספרות, כגון @image_1, כך שלא צריך לכתוב בעצמכם "Image 1 is..." (תמונה 1 היא…).
connectedReferencesהוא רשימה של רשומותConnectedReference, המבנה של ייחוס מחובר בעורך, שה-SDK מייצא. השרת מסיר כפילויות ומשאיר רק את מספר הייחוסים שהמודל מקבל. השדהreferenceOrderקובע את הסדר שלהם לפי מזהה.- נעילת זהות. רשומה יכולה לכלול
identityLock: { enabled: true, text? }. השרת מוסיף אז שורה קצרה שמבקשת מהמודל לשמור על הזהות של הייחוס הזה. השדהtextמחליף את הניסוח המובנה, והמשתנה{ref}בתוכו מייצג את השם של הייחוס. נעילת הזהות כבויה כברירת מחדל. describedReferencesמקבל עד 10 רשומות{ name, description }לנושאים שאפשר לתת להם שם אבל אין לכם תמונה שלהם, כגון תפקיד בתסריט. כל רשומה הופכת בפרומפט לשורהName — description.. השאירו את השם בטקסט של הפרומפט, כדי שהמודל יידע מי זה.descriptionOverrideברשומת ייחוס מחליף את התיאור השמור שלה, בהרצה הזו בלבד.- כיתובים לייחוסי וידאו ואודיו. השדות
referenceVideoCaptionsו-referenceAudioCaptionsתואמים לסדר שלreferenceVideoUrlsו-referenceAudioUrls. כל כיתוב מופיע בפרומפט כ-@video_1: caption.או כ-@audio_1: caption.. - אזכור של תמונת ייחוס בפרומפט. ב-
generate-image, תנו שם לייחוס והזכירו אותו כ-@<name>:<index>או כ-@<name>:<index>:<role>, למשל@town:1:background. האזכור מציב את הייחוס הזה, או את התפקיד שלו, בנקודה הזו של הפרומפט. הסימונים~lockו-~nolockעובדים כמו באזכורים של דמויות.
ראו את המדריך תפקידי ייחוס לתפקידים שאפשר להשתמש בהם ואת המדריך דמויות עקביות לשמירה על זהות.
הכוונה קולנועית
הרכיבים generate-image, generate-video ו-text-to-video מקבלים אובייקט direction של מזהי בוררים במקום מילים. Nodaro כותב לפרומפט ניסוח בדוק לכל מזהה, כך שהקוד שלכם שולח מזהים, והניסוח נשאר מעודכן.
await client.nodes.runAndWait("generate-image", {
prompt: "A detective waits under a street lamp",
direction: { shotSize: "wide-shot", timeOfDay: "golden-hour", mood: "suspicious" },
})- המפתחות הם ממדים של בוררים, כגון
shotSize,lightingStyle,style,mood,photographerאוera. נתיבי הווידאו מוסיפים מפתחות תנועה, כגוןcameraMotion,actionFx,transition,loopSubjectומפתחות ה-temporal. - הערכים הם מזהה אחד או מערך של מזהים. ממד שמקבל כמה ערכים שומר לכל היותר את מספר הערכים שהמגבלה שלו מאפשרת ומשמיט את השאר. הבקשה נדחית רק מעל 8 ערכים למפתח או 100 תווים למזהה.
- מפתחות ומזהים לא מוכרים מדולגים, ולא נדחים. אובייקט
directionריק לא משנה את הפרומפט שלכם. - מפה אחת משרתת גם תמונות וגם וידאו. מפתח שמיועד רק לתמונות ונשלח להרצת וידאו מתקבל ולא מוסיף כלום.
- הרכיב
extend-videoלא מקבלdirection, כי הפרומפט שלו ממשיך קליפ קיים. - הפלטות והמודבורדים שלכם עובדים ב-
generate-image. קבעו אתcolorLookל-paletteDirectionId(id), או אתstyleל-moodboardDirectionId(id). ראו את הסעיף פלטות ומודבורדים בדף בוררים, ערכות ופרומפטים.
את המזהים התקפים אפשר לקבל מ-client.pickerCatalogs. כל הממדים מפורטים בדף קטלוגי הבוררים.
הנושא
ב-GenerateImageParams וב-TextToVideoParams יש שדה אופציונלי subject, עם הטיפוס המיוצא Subject. השדה מתאר מי מופיע בשוט: האדם, הסטיילינג שלו והאביזרים בפריים, כמפה שטוחה משדה של בורר למזהה בקטלוג. אף פעם לא כותבים בשבילו טקסט של פרומפט. Nodaro כותב את הניסוח ומציב אותו מיד אחרי ה-prompt שלכם, לפני כל direction.
import type { Subject } from "@nodaro/sdk"
const subject: Subject = { type: "woman", age: "age-30s", hairBase: "base-short-straight", heldProp: "smartphone" }
await client.nodes.run("generate-image", { prompt: "on the seawall at dusk", subject })- שמות השדות והמזהים מגיעים מקטלוגי הבוררים. הקריאות
client.pickerCatalogs.get("person")ו-get("styling")מחזירות את ה-fieldשל כל ממד, עם ה-options[].idשלו. הקריאותget("held-prop"),get("material")ו-get("animal")כותבות את המזהים שלהן ל-valueFieldשל הקטלוג:heldProp,materialו-animal. - הערכים הם מזהה אחד או רשימה של מזהים. מזהים מעבר למגבלה של הממד נשמטים, ולא נדחים. השדה
customAgeהוא המספר היחיד, בשנים, והשרת משתמש בו רק עםage: "age-custom". - מגבלות. בלי ערכה, הנתיב בודק את המפה. בקשה עם יותר מ-128 מפתחות, עם מפתח ארוך מ-64 תווים, עם יותר מ-8 מזהים במפתח אחד או עם מזהה ארוך מ-100 תווים נדחית עם
400 validation_error. מפתחות ומזהים לא מוכרים בתוך המגבלות האלה מדולגים, והשדהinput_data.subjectשל המשימה שומר בדיוק את המזהים שהיו בשימוש. - עם
presetId, השדהsubjectשלכם מחליף את זה של הערכה ומתווסף לפרומפט של הערכה, כמוdirection. ערכים ארוכים מדי נשמטים במקום להידחות, והשדהinput_dataלא מתעד את הנושא.
כל המפתחות, והסדר שבו הניסוח מתווסף, מפורטים בדף ה-API רכיבים.
רכיבי מודל שפה
המתודה run(type, params) שולחת כל סוג של רכיב מודל שפה לנתיב שלו: הנתיב /v1/<type> ל-generate-script, ל-image-critic, ל-qa-check ול-describe-to-picker, ונתיב ארוך יותר לאחרים. לא צריך בשבילם את client.request():
| סוג הרכיב | נקודת קצה |
|---|---|
llm-chat | /v1/llm-chat/generate |
after-effects | /v1/after-effects/generate |
motion-graphics | /v1/motion-graphics/generate |
lottie-overlay | /v1/lottie-overlay/generate |
3d-title | /v1/3d-title/generate |
image-to-text | /v1/image-to-text/describe |
video-composer | /v1/scene-graph/generate |
await client.nodes.run("generate-script", {
prompt: "A 3-scene product launch script for a smart water bottle",
reasoningEffort: "high",
})reasoningEffortהוא"none","low","medium","high","xhigh"או"max", לפי המודל. השמיטו אותו, או שלחו רמה שהמודל לא תומך בה, כדי לקבל את ברירת המחדל של המודל. לרמת המאמץ אין מחיר משלה. כל קריאת LLM מחויבת לפי הטוקנים שהיא השתמשה בהם, בתעריף של המודל בשירות שהריץ אותה, ולכן רמה גבוהה יותר עולה יותר רק בגלל הטוקנים שהמודל כותב. במודל Claude, כל רמת מאמץ מריצה את הקריאה ב-API של היצרן עצמו, בתעריף של אותו שירות. המודלים מפורטים בדף יצירת טקסט - כל LLM, והחיוב מוסבר בסעיף איך מחויבות קריאות LLM בדף קרדיטים. חריג אחד: הרכיבdescribe-to-pickerוגרסת הטקסט שלו,text-to-picker, רצים ברמה"high"כשמשמיטים את השדה והמודל ב-llmModelהואclaude-opus-5.5. ההרצה הזו עוברת דרך ה-API של Anthropic עצמה, בתעריף של אותו שירות. שלחו רמה אחרת כדי לשנות אותה. כל מודל אחר שומר על ברירת המחדל שלו, כולל מודל ברירת המחדל של שני הסוגים האלה, Gemini 3.8 Flash.advancedMode: trueמריץ מודל Gemini או Claude ישירות ב-API של היצרן שלו. רק שםtemperature,maxTokensוכל טווח רמות המאמץ נכנסים לתוקף במלואם. הקריאה מחויבת בתעריף לטוקן של אותו שירות. בקשה עם מודל בלי האפשרות הזו נדחית עם400 advanced_mode_unsupported. כל עוד הספק של המודל עצמו לא יכול לקבל בקשות, הקריאה נכשלת עםadvanced_mode_unavailableבמקום לרוץ בשירות ברירת המחדל: עם הקוד400מראש, או502באמצע הקריאה, והקרדיטים מוחזרים אלא אם הספק חייב על הניסיון. כבו את המצב המתקדם כדי להריץ את המודל. רכיב תיאור לבורר הוא החריג: שם, הרצה של Claude שהספק דוחה עוברת ל-Gemini 3.8 Flash, כמו שקורה כשהמצב המתקדם כבוי.- אומדן מחיר לקריאה. הקריאה
client.credits.modelCosts([llmPriceKey(feature, model)])מחזירה אומדן של קריאה טיפוסית, שמופיע ב-estimates. הציגו אותו כ-≈N. הפונקציהllmPriceKeyמגיעה מ-@nodaro/shared/llm-models. ראו את הדף מודלים וקרדיטים. - אין מעטפת להזרמה. ה-SDK לא קורא את התשובה בהזרמה של רכיב יצירת טקסט - כל LLM. בשבילה, השתמשו ב-
fetchעם זרם קריא.
כללים לפי מודל
כמה מודלי וידאו מקבלים ערכים שמודלים אחרים לא מקבלים. בדף של כל מודל מופיעים כל האפשרויות והמחירים.
- Seedance 2 מקבל
resolution: "4k"ו-aspectRatio: "adaptive"או"21:9". Seedance 2 Fast ו-Seedance 2 Mini מרנדרים ב-480p או ב-720p בלבד. - Seedance 2.5 מרנדר ב-480p, ב-720p או ב-1080p, יוצר עד 30 שניות בקריאה אחת ומקבל 30 תמונות ייחוס, 10 סרטוני ייחוס ו-10 קטעי אודיו ייחוס. עם פריים פתיחה, הוא משתמש ביחס של הפריים הזה ודוחה
aspectRatioמפורש. - MiniMax H3 (
minimax-h3) מקבל 9 תמונות ייחוס, 3 סרטוני ייחוס ו-3 קטעי אודיו ייחוס, ב-resolution: "2K"(ברירת המחדל) או"768P". כל ערך אחר מרונדר ומתומחר כמו 2K. - Wan 3.0 (
wan-3ו-wan-3-primeהמהיר יותר) מקבל 10 תמונות ייחוס, 5 סרטוני ייחוס ו-5 קטעי אודיו ייחוס. אי אפשר לשלב את רשימות הייחוסים עםimageUrlאו עםendFrameUrl. הערך שלdurationהוא מספר שלם מ-2 עד 30, והערך שלresolutionהוא480p,720pאו1080p. - Gemini Omni Flash מקבל אותה בקשה כמו Gemini Omni: אורכים של 4, 6, 8 או 10 שניות, מ-720p עד 4K ורק 16:9 או 9:16.
- Kling 4.0 (
kling-4) רץ מטקסט בלבד, או מחומרי ייחוס. הוא מקבלreferenceImageUrls(עד 10),referenceVideoUrls(עד 5, כל אחד באורך של 2–30 שניות),characterReferences(עד 7, כנושאים עם שם) ו-referenceAudioUrls(עד 3). בקשה עם יותר מ-15 חומרים בסך הכול נדחית עם400לפני שמשוריינים קרדיטים. השדותimageUrlו-endFrameUrl, כשהם נשלחים, מצטרפים לתמונות הייחוס. ב-kling-4, כל ייחוס דמות נבנה מ-imageUrl, מ-bodyImageUrlומ-extraImageUrls(עד 3), מותר לשלוח פריים פתיחה, ואילו השדהvoiceנדחה. הערךkeepOriginalSound: trueשומר על הסאונד המקורי של סרטון ייחוס. קטע האודיו הראשון מתנגן כברירת מחדל כפסקול. הוא נשלח כעוד סרטון ייחוס, ולכן ההרצה מתומחרת כמו הרצה עם סרטון ייחוס, ושאר הקטעים נשארים קולות עם שם. הערךaudioSoundtrack: falseמשאיר כל קטע כדגימת קול. בהרצה עם סרטון ייחוס משלמים על הפלט ועוד על הארוך מבין הפלט והקליפים, בתעריף הייחוס. Kling 4.0 Keyframes (kling-4-keyframes) מקבלimageUrl, עד 8 פריימי ביניים ב-referenceImageUrls, לפי הסדר, ו-endFrameUrl. המספר הכולל של הפריימים מוגבל לפיduration: מ-4 ב-3 שניות ועד 10 מ-9 שניות ומעלה, ובקשה עם יותר פריימים נדחית עם400. שני המודלים מקבליםdurationמ-3 עד 30 (ברירת המחדל היא 5) ו-resolutionשל720pאו1080p; כל ערך אחר מרונדר ב-720p. הערך שלaspectRatioהואauto,16:9,9:16,1:1או21:9. האודיו תמיד מופעל, ואין זרע. - Gemini Omni ו-Gemini Omni Flash (
gemini-omni-videoו-gemini-omni-flash) שומרים על הפנים של אדם אמיתי עםcharacterReferences. העבירו עד 3 רשומות בצורה{ imageUrl, description, bodyImageUrl?, name?, voice? }. השדהvoiceהוא{ preset, description?, exampleLine? }, והשדהpresetהוא אחד המזהים שלGEMINI_OMNI_VOICE_PRESETSמ-@nodaro/shared. השדה הזה שומר על קול אחד לדמות בכל הקליפים. בכל מודל אחר הבקשה נדחית עם400, ואי אפשר לשלב אתcharacterReferencesעם פריים פתיחה (imageUrl). כל דמות תופסת יחידה אחת מתוך 7 יחידות הקלט של המודל, או 2 עםbodyImageUrl, ותמונות ייחוס וסרטון מקור חולקים את אותן יחידות. ייחוסי דמויות לא מוסיפים קרדיטים. השתמשו בהם במקום ב-referenceImageUrlsכשהפנים חייבות להישאר זהות.
טקסט לדיבור. כשמשמיטים את provider, רכיב טקסט לדיבור משתמש ב-ElevenLabs v4 לטקסט של עד 10,000 תווים. טקסט ארוך יותר עובר ל-ElevenLabs Turbo v2.5, שהמגבלה שלו היא 40,000 תווים, כך שהוא לא נחתך. כשאתם מציינים provider, הרכיב תמיד משתמש בו. שלחו provider: "elevenlabs-v3" כדי להישאר עם ElevenLabs v3, שהמגבלה שלו היא 5,000 תווים.
רציפות בין קליפים. רכיב טקסט לדיבור מקבל גם previousText ו-nextText: השורות שנאמרות ממש לפני הקליפ ואחריו, עד 1,000 תווים כל אחת. הן לא מוקראות. ElevenLabs v4, v4 Turbo, Turbo v2.5 ו-Multilingual v2 משתמשים בהן כדי לשמור על אינטונציה אחת בקליפים שנוצרו בנפרד. ElevenLabs v3 מתעלם מהן.
רכיבי גריפה ורכיבי קלט אחרים
רכיבי קלט רצים באותו אופן. רכיב גריפה, כגון גריפת אתר, עונה מיד: התוצאה כוללת jobId בשביל ההיסטוריה שלכם וגם את הנתונים עצמם, כך שאפשר להשתמש בהם בלי לבדוק את הסטטוס מדי כמה שניות. שדות הבקשה הם שדות הקלט של הרכיב, שמפורטים ב-inputSchema.
שאלות נפוצות
איך יוצרים תמונה עם ה-SDK של Nodaro?
קראו למתודה client.nodes.runAndWait עם סוג הרכיב generate-image ועם פרומפט. המתודה runAndWait מחזירה את הפלט של המשימה, וה-imageUrl שבפלט הוא התמונה שנוצרה.
מה ההבדל בין המתודה run למתודה runAndWait?
המתודה run מתחילה את הרכיב ומחזירה jobId מיד. המתודה runAndWait מתחילה אותו, בודקת את הסטטוס של המשימה כל 2 שניות ומחזירה את הפלט כשהמשימה מסתיימת.
כמה זמן המתודה runAndWait ממתינה?
המתודה runAndWait ממתינה עד 15 דקות כברירת מחדל. אפשר לשנות את הזמן עם האפשרות maxMs. פסק זמן לא מבטל את המשימה, ובדרך כלל היא עדיין מסתיימת בשרת.
אילו סוגי רכיבים אפשר להריץ?
קראו למתודה client.nodes.list() כדי לקבל כל סוג שהשרת תומך בו, עם הקטגוריה, סוג הפלט, המודלים והמחיר בקרדיטים שלו. לכל רכיב במדריך הרכיבים יש סוג ב-API.
איך יוצרים כמה תמונות בקריאה אחת?
קראו למתודה client.nodes.runBatchAndWait עם generate-image ועם count (מ-1 עד 4 תמונות) או models (בין 2 ל-4 מודלי תמונה). האצווה מחויבת כולה או לא מחויבת בכלל, ותמונה אחת שנכשלה אף פעם לא מבטלת את התמונות האחרות.
איך נמנעים מתשלום כפול כשמנסים שוב בקשה?
העבירו idempotencyKey באפשרויות של המתודה run או של המתודה runAndWait, והשתמשו באותו מפתח כשאתם מנסים שוב. הפלטפורמה מחזירה את ההרצה הראשונה במקום להתחיל הרצה שנייה.
דפים קשורים
משימות והרצות
מודלים וקרדיטים
רכיבים
מדריך הרכיבים
ה-CLI של Nodaro
עודכן לאחרונה