הפקות 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.jsonconst { production, version, rebased, receipts } =
await client.studio.productions.ops(id, { ops, baseVersion: 7 })התגובה היא { production, version, rebased, receipts, warnings }. שישה כללים חלים על כל אצווה:
- הכול או כלום. פעולה לא תקינה אחת גורמת לדחיית האצווה כולה, ושום דבר לא נכתב. השגיאה מציינת את הפעולה לפי
opIndexשלה, שנספר מ-0. אצווה יכולה לכלול עד 100 פעולות. - החלה מחדש על הגרסה העדכנית, כברירת מחדל. השדה
baseVersionהוא למידע בלבד: אצווה שנכתבה מול גרסה ישנה יותר מוחלת על המסמך החדש ביותר, והתגובה מציינתrebased: true. שלחוstrict: trueכדי לקבל במקום זאת409 workflow_conflict. - זהו כל דבר לפי מפתח יציב. שוט לפי המזהה שלו, תיקייה או גרסת עריכה לפי המזהה שלהן, אלמנט בליהוק לפי ה-slug של התפקיד שלו, תוצאה לפי מפתח התוצאה שלה. אף פעם לא לפי מיקום, כי ייתכן שהעורך וסקריפט עורכים את אותה הפקה באותו זמן.
- צרו את המזהים בעצמכם. פעולה שיוצרת שוט, תיקייה, גרסת עריכה או עותק מקבלת את המזהה שאתם נותנים לה. כך העותק המקומי שלכם והשרת מסכימים על כל מזהה.
- מחיקות עוברות לפח. הסרה מעבירה את מה שהוסר לפח של ההפקה, ופעולה משחזרת אותו. רק מחיקה סופית מפורשת משמידה משהו.
- אמצו את התגובה. החליפו את העותק שלכם ב-
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.
שגיאות
| סטטוס | קוד | משמעות |
|---|---|---|
400 | validation_error | גוף הבקשה או התוכנית שגויים. השדה path מציין את השדה השגוי; בנתיב הייצוא, השדה issues מפרט את הבעיות. |
400 | op_invalid, op_target_missing | ב-…/ops: אחת הפעולות הייתה שגויה, והשדה opIndex מציין אותה. שום דבר לא נכתב. תקנו אותה ושלחו את האצווה שוב. |
402 | insufficient_credits | אין בחשבון מספיק קרדיטים ליצירה. |
403 | forbidden | רק הבעלים או מנהל של סביבת העבודה יכולים לשנות את השיתוף. |
404 | not_found | אין הפקה כזו שזמינה לכם, או שהפריסה לא מספקת הפקות. |
404 | op_target_missing | בנתיב יצירה או מדיה: השוט, התוצאה או התפקיד שציינתם לא נמצאים בהפקה. |
409 | workflow_conflict | נשלח strict: true או expectedVersion, וההפקה השתנתה. קבלו אותה שוב והחילו את השינויים מחדש. |
409 | production_busy | ההפקה המשיכה להשתנות בזמן הכתיבה. קבלו אותה מחדש ונסו שוב. |
409 | sequence_quote_changed | ההגדרות או הפריימים של קליפ מקושר השתנו מאז האומדן. בקשו אומדן מחיר חדש. |
413 | storage_exceeded | החשבון חרג ממגבלת האחסון שלו. |
429 | rate_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 באחסון שלכם. הייצוא לא עולה קרדיטים.
דפים קשורים
הפקות Studio
פייפליינים
משימות
קול ומדיה
תהליכים
עודכן לאחרונה