דילוג לתוכן
תיעוד Nodaro
תיעודמדריך הרכיביםמודליםתבניותסוכני AI (MCP)מפתחיםאירוח עצמימחקרהשוואות
REST API

הפקות Studio

קריאה ועריכה של הפקות Studio ב-REST API: פעולות אטומיות, יצירת תמונות סטילס וקליפים, הכנסת תוצאות להפקה, תכנון הייצוא, שיתוף והעתקה.

זמין ב-Nodaro Cloud

ה-API של הפקות Studio קורא וכותב את הסרטים שאתם בונים ב-Nodaro Studio. הפקה היא תהליך של Nodaro שבהגדרות שלו נמצאת רשימה של שוטים לפי הסדר. לכל שוט יש תמונת סטילס של הפריים, קליפ מונפש אופציונלי, והתוכנית, המראות, הליהוק והקול שיצרו אותם. סקריפט, עוזר AI ועורך ה-Studio עובדים כולם על אותה הפקה דרך הנתיבים האלה, באותו זמן.

הפקות Studio זמינות רק ב-Nodaro Cloud. פריסה שלא מספקת אותן מחזירה 404 בכל נתיב, ולכן בדקו פעם אחת עם נתיב הרשימה אם היכולת קיימת. בהתקנה באירוח עצמי, בנו את הסרט כתהליך עם רכיבים כמו סצנה, יצירת וידאו ושילוב סרטונים. הנתיבים מקבלים אסימון Bearer; אסימונים של אפליקציית OAuth צריכים workflows:read לקריאה ו-workflows:write לכתיבה. ראו את דף ה-API אימות.

כשאין לכם גישה להפקה, כל נתיב מחזיר 404, ולעולם לא 403, כך שאי אפשר לברר אם מזהה מסוים קיים.

המילים של העורך והמפתחות של המסמך

העורך והמסמך קוראים לאותם דברים בשמות שונים. בקוד השתמשו במפתחות של המסמך, ומול אנשים השתמשו במילים של העורך.

בעורךבמסמך
סרטההפקה
סצנה, למשל ״סצנה 3״רשומה ב-shots[], שמזוהה לפי ה-shotId שלה
הפריים של סצנה, והטייקים שלותוצאות ה-still של השוט
התנועה של סצנה, והטייקים שלהתוצאות ה-clip של השוט
השוטים שבתוך תנועהה-beats[] של השוט

נקודות קצה

שיטהנתיבמה היא עושה
GET/v1/studio/productions/skillהמדריך לכתיבה, הקטלוג, ה-JSON Schema של התוכנית ורשימת הפעולות. הנתיב חינמי.
GET/v1/studio/productions/capabilitiesאילו פעולות אופציונליות הפריסה הזו תומכת בהן.
POST/v1/studio/productions/validateבדיקת תוכנית. הנתיב חינמי ולא שומר כלום.
GET/v1/studio/productionsרשימת ההפקות שלכם, מהחדש לישן.
POST/v1/studio/productionsיצירת הפקה, מתוכנית או בלעדיה.
GET/v1/studio/productions/:idקריאת הפקה. הנתיב אף פעם לא כותב.
POST/v1/studio/productions/:id/opsהחלת אצווה של פעולות, או תצוגה מקדימה שלה.
POST/v1/studio/productions/:id/reconcileהפיכת משימות שהסתיימו לתוצאות.
POST/v1/studio/productions/:id/importהוספת השוטים של תוכנית להפקה.
POST/v1/studio/productions/:id/describeכתיבת התוכנית מתוך בריף.
POST/v1/studio/productions/:id/generateיצירת תמונת סטילס או קליפ לשוט, או אומדן מחיר ליצירה.
POST/v1/studio/productions/:id/frameשליפת פריים מקליפ.
POST/v1/studio/productions/:id/voiceהקראת שורה על גבי שוט.
POST/v1/studio/productions/:id/revoiceהחלפת הקולות בקליפ של שוט.
POST/v1/studio/productions/:id/musicיצירת הפסקול.
GET/v1/studio/productions/:id/export-planהשלבים שמרכיבים את הסרט, עם המחיר של כל אחד.
POST/v1/studio/productions/:id/shareהפעלה או כיבוי של שיתוף בקישור.
POST/v1/studio/productions/:id/unshareכיבוי של שיתוף בקישור.
POST/v1/studio/productions/:id/cloneהעתקת הפקה.

אין נתיב מחיקה. העברה לארכיון היא פעולה, ואפשר לבטל אותה.

קריאת הפקה

כל תגובה עטופה כ-{ "data": { "production": { … } } }. ה-SDK פותח את המעטפת: מתודה שמחזירה הפקה מחזירה ישירות את ההפקה עצמה. ברמה העליונה של ההפקה נמצאים:

שדהמה יש בו
id, name, version, updatedAtהזהות של ההפקה, והמונה שכל כתיבה בודקת.
thumbnailUrl, shared, archivedתמונת הפוסטר, האם השיתוף בקישור מופעל, והאם ההפקה בארכיון.
film, cast, folders, storyboard, music, musicPlan, cutsמראה הסרט, התפקידים, התיקיות בציר הזמן, הבריף, הפסקול וגרסאות העריכה שיוצאו.
trash{ count, items? }: מה שהוסר ואפשר לשחזר.
pending{ stills, clips, music, draft }: מה שנמצא כרגע ביצירה.
shots[]השוטים לפי הסדר בציר הזמן, כל אחד עם still, clip, startFrame, endFrame, plan, beats, look, voice ועוד.

הנתיב GET /v1/studio/productions/:id מקבל detail=summary (ברירת המחדל: ספירות והכתובות הפעילות) או detail=full (כל תוצאה בהיסטוריה של כל שוט, עם ההקשר שיצר אותה). הפרמטר shot_id מחזיר שוט אחד, וזו הדרך הזולה לקרוא שוב אחרי יצירה. הנתיב GET /v1/studio/productions מקבל limit, cursor ו-includeArchived.

התוצאות מצטברות. יצירה אף פעם לא מחליפה: תמונות הסטילס של שוט הן כל המועמדות שהיו לו אי פעם, וכך גם הקליפים שלו. מחיקה של תמונת סטילס אף פעם לא נוגעת בקליפים. תוצאה מזוהה לפי מפתח התוצאה שלה, שהוא מזהה המשימה שלה כשיש לה כזה, ואחרת הכתובת שלה, ולעולם לא לפי המיקום שלה.

curl "https://app.nodaro.ai/v1/studio/productions/5d8f2b4a-7c1e-4a9d-8b3f-2e6c9a1d4f7b?detail=summary" \
  -H "Authorization: Bearer $NODARO_API_KEY"
import { createClient, StaticTokenAuth } from '@nodaro/sdk'

const client = createClient({
  baseUrl: 'https://app.nodaro.ai',
  auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})

const production = await client.studio.productions.get(id, { detail: 'full' })
const shot = await client.studio.productions.get(id, { shotId: 'shot-2' })

ה-SDK מגדיר טיפוסים למעטפות (version, rebased, receipts, warnings, ה-credits של אומדן מחיר, ה-jobIds של הרצה), ומשאיר את מסמך ההפקה כ-JSON פתוח.

עריכה בפעולות

כל שינוי בהפקה הוא פעולה: עריכה עם שם, כמו שינוי השם של שוט, הזזה שלו, שיוך של תפקיד בליהוק או שמירה של מועמד. הנתיב POST /v1/studio/productions/:id/ops בודק ומחיל אצווה של פעולות. רשימת הפעולות מגיעה מהשרת ולא מודפסת כאן: קבלו את החלק operating מ-GET …/skill, שתמיד תואם לפריסה שאתם עובדים מולה.

# batch.json: { "ops": [ ...operations from GET /v1/studio/productions/skill... ], "baseVersion": 7 }
curl -X POST https://app.nodaro.ai/v1/studio/productions/5d8f2b4a-7c1e-4a9d-8b3f-2e6c9a1d4f7b/ops \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d @batch.json
const { production, version, rebased, receipts } =
  await client.studio.productions.ops(id, { ops, baseVersion: 7 })

התגובה היא { production, version, rebased, receipts, warnings }. שישה כללים חלים על כל אצווה:

  1. הכול או כלום. פעולה לא תקינה אחת גורמת לדחיית האצווה כולה, ושום דבר לא נכתב. השגיאה מציינת את הפעולה לפי opIndex שלה, שנספר מ-0. אצווה יכולה לכלול עד 100 פעולות.
  2. החלה מחדש על הגרסה העדכנית, כברירת מחדל. השדה baseVersion הוא למידע בלבד: אצווה שנכתבה מול גרסה ישנה יותר מוחלת על המסמך החדש ביותר, והתגובה מציינת rebased: true. שלחו strict: true כדי לקבל במקום זאת 409 workflow_conflict.
  3. זהו כל דבר לפי מפתח יציב. שוט לפי המזהה שלו, תיקייה או גרסת עריכה לפי המזהה שלהן, אלמנט בליהוק לפי ה-slug של התפקיד שלו, תוצאה לפי מפתח התוצאה שלה. אף פעם לא לפי מיקום, כי ייתכן שהעורך וסקריפט עורכים את אותה הפקה באותו זמן.
  4. צרו את המזהים בעצמכם. פעולה שיוצרת שוט, תיקייה, גרסת עריכה או עותק מקבלת את המזהה שאתם נותנים לה. כך העותק המקומי שלכם והשרת מסכימים על כל מזהה.
  5. מחיקות עוברות לפח. הסרה מעבירה את מה שהוסר לפח של ההפקה, ופעולה משחזרת אותו. רק מחיקה סופית מפורשת משמידה משהו.
  6. אמצו את התגובה. החליפו את העותק שלכם ב-production במקום למזג, ושלחו את version בתור ה-baseVersion הבא.

שיתוף הוא לא פעולה; אצווה שמנסה לשנות אותו נדחית. באישורי הביצוע (receipts) יש שורה אחת בזמן עבר לכל פעולה, { op, summary, ids?, impact? }: הציגו אותם לכל מי שרוצה לדעת מה עוזר עשה. השדה warnings מפרט דברים שכדאי לציין אבל הם לא כשלים, כמו פעולה שלא שינתה כלום.

אישור ביצוע יכול לכלול גם detail, { template, vars }: אותה שורה כנתונים. התשובה יכולה לכלול warningDetails, אותו דבר עבור warnings. כך לקוח יכול לנסח את התשובה בשפה של האדם שמולו. השדות summary ו-warnings נשארים בניסוח האנגלי, והם תמיד מופיעים. לכן לקוח שאין לו ניסוח ל-template, או שה-vars שלו לא ממלאים אותו, מציג את השורה באנגלית ולא מפסיד כלום.

  • מזהה של תבנית ניסוח הוא קבוע. שינוי במקומות למילוי שלה או במשמעות שלה מתפרסם עם מזהה חדש.
  • השדה warningDetails נשלח רק כשהאורך שלו זהה בדיוק לאורך של warnings. רשומה i מנסחת את אזהרה i, והערך null מסמן אזהרה שיש לה רק ניסוח באנגלית. התייחסו לרשימה בכל אורך אחר כאילו היא לא קיימת.
  • פריסה ישנה יותר מהשדות האלה לא שולחת אף אחד מהם.

תצוגה מקדימה של אצווה לפני ההחלה

הערך dryRun: true שואל מה האצווה הייתה עושה. השרת מריץ את הכתיבה עצמה, באותו הקשר ועם אותן דחיות, ועוצר לפני השמירה. התשובה היא { dryRun: true, version, receipts, warnings }, בלי production. כל אישור ביצוע מוסיף class, הסיווג של הפעולה (S בטוחה, D מוחקת, P משנה את מי שיכול לגשת לעבודה, $ מוציאה קרדיטים), ובמחיקה שאפשר לבטל, גם restorable: true. גם כאן אישורי הביצוע כוללים detail והתשובה כוללת warningDetails, כמו בהחלה.

פריסה ישנה יותר מהתצוגות המקדימות מתעלמת מ-dryRun ומחילה את האצווה. לכן בדקו קודם את הדגל עם אצווה ריקה, שלא משנה כלום באף פריסה:

{ "ops": [], "dryRun": true }

רק תשובה שכוללת dryRun: true היא ״כן״. כל דבר אחר הוא ״לא״: אמרו לאדם שאי אפשר לראות כאן תצוגה מקדימה, ואל תשלחו את האצווה. בדקו את הסימון גם בתשובה של התצוגה המקדימה האמיתית, כי בפריסה שמתעדכנת, ייתכן שהבקשה הבאה תטופל בשרת אחר. תשובה עם production במקום הסימון פירושה שהאצווה הוחלה: אמצו אותה ואל תשלחו את האצווה שוב. ה-SDK מבצע את שתי הבדיקות בשבילכם וזורק StudioPreviewUnavailable או StudioPreviewAppliedError.

const preview = await client.studio.productions.ops(id, { ops, baseVersion, dryRun: true })
for (const r of preview.receipts) console.log(r.class, r.summary, r.restorable ?? false)

יצירת תמונות סטילס וקליפים

יצירה היא הרצה ואחריה תשאול. הנתיב POST /v1/studio/productions/:id/generate עם kind: "still" או kind: "clip" ועם shotId שולח את המשימות, רושם אותן בהפקה כממתינות, וחוזר מיד עם { jobIds, lane?, deduped?, production? }.

  • הבקשה נבנית מהשוט. השרת מרכיב את הבקשה מהתוכנית, מהמראות, מהליהוק ומהוראות הבימוי של השוט. לכן קריאה מסקריפט ולחיצה בעורך יוצרות את אותה תמונה. השדה overrides משנה הרצה אחת בלי לשנות את השוט.
  • קודם אומדן מחיר. הערך dryRun: true מתמחר את ההרצה ולא כותב כלום. התשובה היא { dryRun: true, provider, count, credits, lane? }. הערך credits: null אומר שלמודל אין מחיר, כלומר המחיר לא ידוע, ולא שהוא חינם.
  • ניסיון חוזר בטוח. השדה clientRequestId, מחרוזת של 8–128 תווים מתוך A-Za-z0-9_.:- שאתם יוצרים, הופך ניסיון חוזר לבטוח: אותו מזהה מחזיר את המשימות של הקריאה הראשונה עם deduped: true, ולא נגבים קרדיטים. לעולם אל תנסו שוב קריאה בתשלום בלעדיו.
  • הכניסו את התוצאות להפקה. הנתיב POST /v1/studio/productions/:id/reconcile הופך משימות שהסתיימו לתוצאות ומנקה משימות שנכשלו. הוא מחזיר { landed, pending, failed, warnings, production, version }. בקשת GET אף פעם לא כותבת, ולכן קראו ל-reconcile כשאתם מחכים למשהו.
  • השיטה של הקליפ נבחרת בשבילכם. בקליפ, נתיב המודל (generate-video או text-to-video) נקבע לפי הקלטים של השוט, וחוזר כ-lane. השדה mode רק אומר מאיזו קבוצת קלטים לביים ("start" או "references").
curl -X POST https://app.nodaro.ai/v1/studio/productions/5d8f2b4a-7c1e-4a9d-8b3f-2e6c9a1d4f7b/generate \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "kind": "still", "shotId": "shot-2", "count": 2, "clientRequestId": "still-shot-2-take-1" }'

curl -X POST https://app.nodaro.ai/v1/studio/productions/5d8f2b4a-7c1e-4a9d-8b3f-2e6c9a1d4f7b/reconcile \
  -H "Authorization: Bearer $NODARO_API_KEY"
import { isStudioGenerateEstimate } from '@nodaro/sdk'

const quote = await client.studio.productions.generateStill(id, 'shot-2', { count: 2, dryRun: true })
if (isStudioGenerateEstimate(quote)) console.log(quote.credits)

const run = await client.studio.productions.generateStill(id, 'shot-2', {
  count: 2,
  clientRequestId: crypto.randomUUID(),
})
// ...once the jobs finish:
const { landed, pending } = await client.studio.productions.reconcile(id)

נתיבי המדיה האחרים עובדים על שוט אחד:

נתיבגוף הבקשהמה הוא עושה
frame{ shotId, mode?, timestamp?, target?, clientRequestId? }שולף פריים מקליפ. ממתין כמה שניות ומחזיר { production, url? }.
voice{ shotId, text, voiceId?, voiceType?, ttsProvider?, delivery?, clientRequestId? }מקריא שורה על גבי השוט. ממתין ומחזיר { production }.
revoice{ shotId, plan, clientRequestId? }מחליף את הקולות בקליפ של השוט. מחזיר { jobId, production }; התוצאה נכנסת להפקה דרך reconcile.
music{ prompt, duration?, instrumental?, vocalGender?, model?, clientRequestId? }יוצר את הפסקול. מחזיר { jobId, production }; התוצאה נכנסת להפקה דרך reconcile.

כל הנתיבים בתשלום כאן מקבלים clientRequestId, כולל frame ו-voice.

קליפים מקושרים וצילומים חוזרים

יש פריסות שתומכות בקליפים שנעים בין שני פריימים שנבדקו. בדקו קודם את GET /v1/studio/productions/capabilities: השדות operations.generateLinkedClips ו-operations.retakeLinkedClips מציינים אם הם זמינים.

  • קבלו אומדן מחיר לקליפ מקושר. הנתיב generate עם kind: "clip", עם ה-shotId ועם dryRun: true בודק את שני הפריימים ומחזיר אומדן מחיר עם inputHash. כששולחים את הבקשה האמיתית, החזירו אותו כ-expectedInputHash. אם ההגדרות או הפריימים השתנו בינתיים, הנתיב מחזיר 409 sequence_quote_changed לפני שהוא שולח משהו.
  • בצעו צילום חוזר של קליפ. הוסיפו retakeResultKey כדי לקבל אומדן מחיר לטייק חדש של קליפ מקושר קיים, עם ההגדרות והפריימים המקוריים שלו. אחר כך שלחו את הבקשה עם ה-inputHash מהאומדן ועם clientRequestId חדש. אל תשלחו mode, overrides או count. אי אפשר לבצע צילום חוזר של טייק שהבקשה המקורית שלו או הפריימים שלו לא נשמרו.

מבריף להפקה

קריאת המדריך

הנתיב GET /v1/studio/productions/skill מחזיר { skill, catalog, schema, operating, generatedFrom }: איך כותבים תוכנית, כל בורר, מודל וערך מותר, ה-JSON Schema של התוכנית ורשימת הפעולות.

בדיקת תוכנית

הנתיב POST /v1/studio/productions/validate עם { plan } מחזיר { valid, errors, warnings, summary? }. תקנו את השגיאה בכל path, עד שהשדה valid הוא true. השמות שבליהוק נבדקים מול הספרייה שלכם.

יצירת ההפקה

הנתיב POST /v1/studio/productions עם { name?, plan? } יוצר את ההפקה ומכניס אליה את התוכנית. הנתיב POST …/:id/import עם { plan, mode: "append" } מוסיף את השוטים של תוכנית להפקה קיימת. אף אחד מהם לא יוצר מדיה.

או לתת לבמאי לכתוב את התוכנית

הנתיב POST …/:id/describe עם { brief, llmModel, mode?, label?, clientRequestId? } מתחיל הרצה של הבמאי ומחזיר { jobId, production }. כשהמשימה מסתיימת, קראו ל-reconcile כדי להכניס להפקה את השוטים שהבמאי ניסח.

const { production } = await client.studio.productions.create({ name: 'The Lighthouse' })
const { jobId } = await client.studio.productions.describe(production.id, {
  brief: 'A keeper, a storm, and a light that will not start.',
  llmModel: 'gpt-5-mini',
  mode: 'replace',
})
// poll jobId with client.jobs.getStatus, then:
await client.studio.productions.reconcile(production.id)

תכנון הייצוא

הנתיב GET /v1/studio/productions/:id/export-plan מחזיר לפי הסדר את השלבים שמרכיבים את הסרט: מיזוגי האודיו של כל שוט, האיחוד וגימור אופציונלי ב-4K עם upscale. הנתיב לא מריץ כלום.

{
  "canExport": true,
  "steps": [
    {
      "id": "voice-shot-2",
      "node": "merge-video-audio",
      "label": "Voice over shot 2",
      "credits": 20,
      "params": { "videoUrl": "https://cdn.nodaro.ai/studio/shot-2.mp4", "audioUrl": "https://cdn.nodaro.ai/studio/vo.mp3" }
    },
    {
      "id": "combine",
      "node": "combine-videos",
      "label": "Join 2 shots",
      "credits": 4,
      "params": {
        "videoUrls": [{ "fromStep": "voice-shot-2" }, "https://cdn.nodaro.ai/studio/shot-3.mp4"],
        "transition": "cut",
        "audioMode": "keep"
      }
    }
  ],
  "resultStepId": "combine",
  "estimate": 24,
  "unpriced": []
}

הריצו את השלבים לפי הסדר עם נתיבי הרכיבים הרגילים, כמו אלה של הרכיבים מיזוג וידאו ואודיו ושילוב סרטונים. ערך { "fromStep": "…" } הוא הפלט של שלב קודם: החליפו אותו בכתובת שהשלב הזה הפיק. אחר כך רשמו את הקובץ המוגמר בהפקה כגרסת עריכה, עם הפעולה שמוסיפה גרסת עריכה.

הערך של canExport הוא false כשאין מה להרכיב, כלומר כשיש פחות משני קליפים. השדה estimate הוא null כשלשלב כלשהו אין מחיר, והשדה unpriced מציין את המודלים האלה, כי סכום חלקי היה מציג עלות נמוכה מהעלות בפועל.

שיתוף והעתקה של הפקה

  • שיתוף. הנתיב POST …/:id/share עם { shared: true } מפעיל את קישור השיתוף לקריאה בלבד; הערך { shared: false } או הנתיב POST …/:id/unshare מכבים אותו. רק הבעלים או מנהל של סביבת העבודה יכולים לשנות את השיתוף (אחרת הבקשה נדחית עם 403 forbidden). כשהשדה operations.revisionedSharing זמין, הוסיפו expectedVersion כדי לקשור את השינוי לגרסה שבדקתם; אם בינתיים הייתה עריכה חדשה יותר, הבקשה נדחית עם 409 workflow_conflict.
  • אפשרו עותקים לעריכה. עם operations.editableSharedCopies, הבעלים יכולים לשלוח גם allowEditableCopy: true, יחד עם shared: true ו-expectedVersion. אז צופים מחוברים שנכנסים דרך הקישור יכולים להעתיק את התוכנית, הפרומפטים, תיאורי הליהוק, הקלטים השמורים והיסטוריית הטייקים. הפח והערות הבדיקה הפרטיות לא מועתקים, וביטול השיתוף עוצר עותקים חדשים.
  • העתקה. הנתיב POST …/:id/clone עם { name? } מעתיק הפקה כפי שאתם רואים אותה. העותק פרטי בהתחלה ולא בארכיון, והוא משתמש באחסון שלכם.

ייצוא ציר זמן לתוכנת עריכה

הנתיב POST /v1/freecut-export הופך ציר זמן של קליפי סצנות לקובץ פרויקט עריכה, כדי שתוכלו להשלים את העריכה בתוכנת עריכה חיצונית. הנתיב כותב קובץ FreeCut JSON (freecut-v1) או Final Cut Pro XML (fcpxml-v1.10) לאחסון שלכם ומחזיר את הכתובת שלו. הייצוא לא עולה קרדיטים, והנתיב מקבל עד 10 בקשות לדקה. כמו כל השאר בדף הזה, הוא דורש Nodaro Cloud; מהדורות אחרות מחזירות 404.

curl -X POST https://app.nodaro.ai/v1/freecut-export \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "json",
    "name": "The Lighthouse, cut 1",
    "timeline": {
      "musicAssetUrl": "https://cdn.nodaro.ai/studio/score.mp3",
      "scenes": [
        {
          "sceneEntityId": "scene-1",
          "compositeUrl": "https://cdn.nodaro.ai/studio/scene-1.mp4",
          "shots": [{ "shot_id": "s1", "duration_seconds": 4 }]
        },
        {
          "sceneEntityId": "scene-2",
          "compositeUrl": "https://cdn.nodaro.ai/studio/scene-2.mp4",
          "shots": [{
            "shot_id": "s2",
            "duration_seconds": 6,
            "cut_decision": { "in_offset_sec": 0, "out_offset_sec": 0.5, "transition_to_next": "dissolve" }
          }]
        }
      ]
    }
  }'
const file = await client.request('POST', '/v1/freecut-export', {
  body: { format: 'json', name: 'The Lighthouse, cut 1', timeline },
})
{
  "url": "https://cdn.nodaro.ai/exports/7b2d4f6a/freecut-3c5e7a9b-1d2f-4a6c-8e3b-5f7a9c1e2d4b.json",
  "format": "json",
  "assetId": "1e3a5c7b-9d2f-4b4a-8c6e-5f7d9b1a3c2e"
}

השדה assetId הוא הרשומה של הקובץ בספרייה שלכם, או null כשאי אפשר היה ליצור את הרשומה הזו; ה-url תקף בכל מקרה.

שדהמה יש בו
formatנדרש. הערך json ל-FreeCut JSON, או fcpxml ל-Final Cut Pro XML.
timelineנדרש. ציר הזמן, כמפורט בהמשך.
nameשם לזיהוי, עד 200 תווים.
timeline.scenesנדרש. סצנה אחת לפחות, לפי סדר ההשמעה. כל סצנה הופכת לקליפ אחד ברצועת הווידאו.
timeline.musicAssetUrlרצועת המוזיקה. מחרוזת ריקה, ברירת המחדל, משמיטה אותה.
timeline.narrationAssetUrlרצועת קריינות, שמוצבת ברצועת אודיו נפרדת.
timeline.fadeOutDurationSecעמעום היציאה בסוף המוזיקה, 0.8 שנייה כברירת מחדל. ב-FreeCut JSON בלבד.
scene.sceneEntityId, scene.compositeUrlנדרשים. המזהה של הסצנה והקליפ הממוזג שלה.
scene.shotsנדרש. שוט אחד לפחות, { shot_id, duration_seconds, cut_decision? }. סכום האורכים של השוטים הוא האורך של הסצנה.
cut_decision.in_offset_sec, cut_decision.out_offset_secנדרשים ב-cut_decision. הקיצוץ בהתחלה (נלקח מהשוט הראשון של הסצנה) ובסוף (נלקח מהשוט האחרון שלה).
cut_decision.transition_to_nextנדרש ב-cut_decision. המעבר לסצנה הבאה: hard_cut, dissolve, match_cut או overlap.
cut_decision.transition_duration_secמחליף את אורך ברירת המחדל של המעבר: 0 ל-hard_cut ול-match_cut, 0.5 שנייה ל-dissolve, שנייה אחת ל-overlap.

המעברים dissolve ו-overlap יוצרים חפיפה בין שני הקליפים באורך המעבר; המעברים hard_cut ו-match_cut מצמידים אותם זה לזה. כשלאף שוט אין cut_decision, הייצוא הוא שרשור פשוט: קליפ אחד לכל סצנה, זה אחרי זה, עם חיתוכים חדים ומוזיקה לאורך כל ציר הזמן. קיצוצים בתוך סצנה לא מוחלים, כי כל קליפ של סצנה כבר ממוזג.

רשומות לשיתוף ולרימיקס

רשומת שוט שומרת את המצב של שוט שבניתם: הבחירות בבוררים, הפרומפטים, מודלי היעד, הנכסים שאוזכרו עם @ והתוצאות. הרשומה נמצאת מאחורי מזהה קצר שאי אפשר לנחש, שעליו מבוססים קישורי השיתוף /s/:id ורימיקסים בלחיצה אחת. הנתיבים האלה נפרדים מההפקות.

שיטהנתיבאימותמה היא עושה
POST/v1/shotsאסימון Bearerיצירת רשומה. התגובה היא { id }.
GET/v1/shots/:idאיןקריאת רשומה. בקשה לרשומה פרטית ממי שהוא לא הבעלים שלה נדחית עם 404. יש מגבלה לכל כתובת IP.
PATCH/v1/shots/:idהבעליםעדכון של כל שדה, כולל visibility.
DELETE/v1/shots/:idהבעליםמחיקת הרשומה.

גוף הבקשה כולל את mode (single, multi-shot, frame-to-motion או storyboard), את selectionState (הערך שנבחר בכל בורר, כ-{ pickerNodeType: valueId } או { pickerNodeType: { field: valueId } }), ואופציונלית גם את freeText, negativePrompt, assembledPrompt, perModelPrompts, models, entityRefs ו-resultUrls. השדה visibility הוא private כברירת מחדל; הגדירו אותו ל-public כדי שאפשר יהיה לשתף את הרשומה.

השדה resultUrls מקבל רק כתובות URL ציבוריות פשוטות של http או https. כתובות חתומות נדחות, כך שאסימון אף פעם לא דולף לרשומה משותפת. לכל רשומה יש schemaVersion. כשרשומה מציינת פריט בקטלוג שכבר לא קיים, דלגו עליו והוסיפו הערה, במקום להכשיל את הרימיקס.

curl -X POST https://app.nodaro.ai/v1/shots \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "single",
    "selectionState": { "mood": "melancholy", "lighting": { "timeOfDay": "blue-hour" } },
    "freeText": "a woman at a bus stop",
    "models": ["nano-banana-pro"],
    "visibility": "public"
  }'
const { id: shotId } = await client.shots.create({
  mode: 'single',
  selectionState: { mood: 'melancholy', lighting: { timeOfDay: 'blue-hour' } },
  freeText: 'a woman at a bus stop',
})
await client.shots.update(shotId, { visibility: 'public' })
const { shot } = await client.shots.get(shotId)
nodaro shots create --file shot.json --visibility public
nodaro shots get <id> --json
nodaro shots delete <id>

שימוש דרך MCP

עוזרי AI עובדים על אותן הפקות דרך כלים כמו get_studio_production_skill, validate_studio_plan, create_studio_production, edit_studio_production, generate_studio_still, generate_studio_clip ו-plan_studio_export. קריאה של הפקה עם הרשאת כתיבה גם מכניסה להפקה משימות שהסתיימו. ראו את הדף הפקות Studio דרך MCP.

שגיאות

סטטוסקודמשמעות
400validation_errorגוף הבקשה או התוכנית שגויים. השדה path מציין את השדה השגוי; בנתיב הייצוא, השדה issues מפרט את הבעיות.
400op_invalid, op_target_missingב-…/ops: אחת הפעולות הייתה שגויה, והשדה opIndex מציין אותה. שום דבר לא נכתב. תקנו אותה ושלחו את האצווה שוב.
402insufficient_creditsאין בחשבון מספיק קרדיטים ליצירה.
403forbiddenרק הבעלים או מנהל של סביבת העבודה יכולים לשנות את השיתוף.
404not_foundאין הפקה כזו שזמינה לכם, או שהפריסה לא מספקת הפקות.
404op_target_missingבנתיב יצירה או מדיה: השוט, התוצאה או התפקיד שציינתם לא נמצאים בהפקה.
409workflow_conflictנשלח strict: true או expectedVersion, וההפקה השתנתה. קבלו אותה שוב והחילו את השינויים מחדש.
409production_busyההפקה המשיכה להשתנות בזמן הכתיבה. קבלו אותה מחדש ונסו שוב.
409sequence_quote_changedההגדרות או הפריימים של קליפ מקושר השתנו מאז האומדן. בקשו אומדן מחיר חדש.
413storage_exceededהחשבון חרג ממגבלת האחסון שלו.
429rate_limit_exceededיותר מ-10 ייצואים של ציר זמן בדקה. המתינו את הזמן שמופיע ב-Retry-After.

ב-SDK השגיאות האלה מגיעות כשגיאות עם טיפוס: StudioOpError (עם opIndex), WorkflowConflictError לשני קודי ה-409 של כתיבה, InsufficientCreditsError, StorageExceededError ו-NotFoundError.

שאלות נפוצות

מה זו הפקת Studio?

הפקת Studio היא סרט שבונים ב-Nodaro Studio. ההפקה היא תהליך שבהגדרות שלו נמצאת רשימה של שוטים לפי הסדר, שהעורך קורא להם סצנות. לכל שוט יש תמונת סטילס של הפריים, קליפ מונפש אופציונלי, והתוכנית, המראות, הליהוק והקול שיצרו אותם.

למה צריך לקרוא ל-reconcile אחרי יצירה?

בהפקת Studio, קריאת יצירה חוזרת מיד, והיצירה רצה ברקע. נקודת הקצה POST /v1/studio/productions/:id/reconcile הופכת את המשימות שהסתיימו לתוצאות בשוטים שלהן. בקשת GET רגילה אף פעם לא כותבת, ולכן משימה שהסתיימה נשארת ממתינה עד שקוראים ל-reconcile.

איך מנסים שוב בבטחה יצירה בתשלום?

ביצירה בתשלום בהפקת Studio, שלחו את השדה clientRequestId, מחרוזת של 8–128 תווים שאתם יוצרים בעצמכם. שליחה חוזרת של אותו מזהה מחזירה את המשימות שהקריאה הראשונה התחילה, עם הסימון deduped, ולא נגבים עליה קרדיטים.

האם אפשר לראות תצוגה מקדימה של מה שאצוות פעולות תעשה?

כן, כששולחים את אצוות הפעולות עם השדה dryRun שמוגדר ל-true. קודם שלחו אצווה ריקה עם dryRun, כדי לוודא שהשרת תומך בתצוגות מקדימות, כי שרת שלא תומך בהן יחיל את האצווה.

האם אפשר לייצא ציר זמן של Studio ל-Final Cut Pro או לתוכנת עריכה אחרת?

כן. נקודת הקצה POST /v1/freecut-export הופכת ציר זמן של קליפי סצנות לקובץ FreeCut JSON או Final Cut Pro XML באחסון שלכם. הייצוא לא עולה קרדיטים.

עודכן לאחרונה

בדף הזה