# קול ומדיה

> קולות, החלפת קול לדובר אחד או לכמה דוברים, דיבוב, ייבוא סרטונים, כתוביות, קיצוץ, כלי אודיו ופרסום ברשתות, כנקודות קצה ב-REST API של Nodaro.

Source: https://nodaro.ai/he/docs/developers/api/voice-and-media

**נקודות הקצה של קול ומדיה** מציעות את כלי הקול והמדיה של Nodaro כ-REST פשוט. הן כוללות את קטלוג הקולות, החלפת קול והחלפת הקולות של כמה דוברים, דיבוב, עיצוב קול, ייבוא סרטונים, כתוביות, קיצוץ, כלי אודיו, תמלול ופרסום ברשתות החברתיות. רובן רצות כמשימות: ה-`POST` מחזיר מיד `{ jobId }`, בודקים את הסטטוס מדי כמה שניות עם `GET /v1/jobs/:id/status` עד שהוא `completed`, ומקבלים את התוצאה מ-`output_data`.

הנתיבים עובדים בכל מהדורה, חוץ מהחריגים שמסומנים בהמשך, ומקבלים אסימון Bearer. ראו את דף ה-API [אימות](https://nodaro.ai/docs/developers/api/authentication), ולבדיקת הסטטוס של משימות רבות בבת אחת, ראו בדף ה-API [משימות](https://nodaro.ai/docs/developers/api/jobs#poll-many-jobs-at-once). כדי לשלוח קבצים מקומיים, העלו אותם קודם. ראו את דף ה-API [העלאות](https://nodaro.ai/docs/developers/api/uploads).

## קולות
| שיטה | נתיב | מה היא עושה |
| --- | --- | --- |
| `GET` | `/v1/voices` | קטלוג הקולות המוכנים מראש: שם, `voice_id`, מגדר, מבטא וגיל. |
| `GET` | `/v1/voices/library` | חיפוש בספריית הקולות המשותפת עם `search`, `gender`, `language`, `page`, `page_size` ועוד. |
| `GET` | `/v1/voice-clones` | הקולות המשוכפלים שיצרתם לפני ששכפול הקולות הוצא משימוש. |
| `PATCH` | `/v1/voice-clones/:id` | שינוי השם או עריכה של אחד מהקולות האלה. |
| `DELETE` | `/v1/voice-clones/:id` | מחיקה של אחד מהקולות האלה. |
| `POST` | `/v1/voice-clones`, `/v1/voice-clones/from-url` | הוצאו משימוש. שני הנתיבים מחזירים `410 voice_cloning_retired`. |

בכל נתיב שמקבל קול, שלחו את ה-`voice_id` של קול מהקטלוג, את השם של קול מוכן מראש, למשל `Rachel`, או את ה-`elevenlabsVoiceId` של קול משוכפל. קולות משוכפלים שנוצרו לפני שהשכפול הוצא משימוש ממשיכים לעבוד בכל מקום.

תוצאה מספריית הקולות יכולה לכלול את `recommendedProvider`: מודל הטקסט לדיבור שהקול אומת עליו. כשאין באפליקציה שלכם תפריט בחירת מודל, שלחו אותו כ-`provider` לרכיב [טקסט לדיבור](https://nodaro.ai/docs/nodes/audio/text-to-speech), כדי שהקול יישמע כמו בדוגמה שלו. השדה `verifiedProviders` מפרט את כל המודלים שהקול אומת עליהם. כשיש באפליקציה שלכם תפריט בחירה, החליפו את הבחירה של המשתמש רק כשהמודל שבחר לא נמצא ברשימה הזו. השדה `hasMore` בתגובה קובע אם להציג אפשרות לטעינת תוצאות נוספות.

```ts

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

const { voices, hasMore } = await client.voices.searchLibrary({ search: 'deep', language: 'en' })
const voice = voices[0]
await client.nodes.run('text-to-speech', {
text: 'Hello!',
voice: voice.voice_id,
voiceType: 'library',
...(voice.recommendedProvider ? { provider: voice.recommendedProvider } : {}),
})
```

## עיצוב קול, או הקראה בקול לפי תיאור
| שיטה | נתיב | גוף הבקשה | תוצאה |
| --- | --- | --- | --- |
| `POST` | `/v1/voice-design` | `{ text, voiceDescription, model?, loudness?, guidanceScale?, seed?, quality?, shouldEnhance? }` | האזנה מקדימה ומזהה קול לשימוש חוזר. |
| `POST` | `/v1/voice-remix` | `{ text, voiceDescription }` | דיבור בקול שתואר, בלי שכפול. |

בנתיב של רכיב [עיצוב קול](https://nodaro.ai/docs/nodes/audio/voice-design), השדה `text` הוא שורה להאזנה מקדימה באורך של 100–1,000 תווים, `loudness` נע מ-`-1` עד 1, ו-`guidanceScale` מ-0 עד 100. בנתיב של רכיב [רמיקס קול](https://nodaro.ai/docs/nodes/audio/voice-remix), השדה `text` הוא באורך של 1–5,000 תווים. שני הנתיבים מחזירים משימה.

## החלפת הקול בהקלטה
הנתיב `POST /v1/voice-changer` מחליף את הקול ברצועת אודיו, או בסרטון שלם עם דיבור, בקול יעד אחד. שלחו בדיוק אחד מהשניים, `audioUrl` או `videoUrl`. כששולחים את שניהם, הסרטון גובר. בסרטון, Nodaro מחלץ את האודיו, מחליף את הקול ומחזיר אותו לתמונה המקורית, וב-`output_data` של המשימה יש גם `videoUrl` וגם `audioUrl`.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/voice-changer \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "videoUrl": "https://cdn.nodaro.ai/uploads/talking.mp4", "voiceId": "Aria", "removeBackgroundNoise": false }'
```

**TypeScript SDK**

```ts
const { jobId } = await client.voices.change({
videoUrl: 'https://cdn.nodaro.ai/uploads/talking.mp4',
voiceId: 'Aria',
})
```

**CLI**

```bash
nodaro voice changer --voice Aria --video https://cdn.nodaro.ai/uploads/talking.mp4 --watch
```

| שדה | מה הוא עושה |
| --- | --- |
| `voiceId` | נדרש. קול היעד. |
| `audioUrl` או `videoUrl` | נדרש אחד מהשניים. ההקלטה שבה הקול מוחלף. |
| `model` | מודל ההמרה מדיבור לדיבור. |
| `stability`, `similarityBoost` | בין 0 ל-1. כמה יציבה ההגשה, וכמה התוצאה קרובה לקול היעד. |
| `style` | בין 0 ל-1, ברירת המחדל היא 0. מעצים את ההגשה, במחיר של מעט מהירות ויציבות. |
| `useSpeakerBoost` | מחדד את הדמיון לקול היעד, וההמרה איטית מעט יותר. |
| `seed` | מספר שלם שבעזרתו אפשר לקבל שוב את אותה תוצאה. |
| `removeBackgroundNoise` | הערך `true` מחזיר רק את הקול הנקי; הערך `false` שומר את המוזיקה והאפקטים מתחת לקול החדש. |

למחירים ולטיפים, ראו את הדף [משנה קול](https://nodaro.ai/docs/nodes/audio/voice-changer).

## החלפת הקולות של כמה דוברים
רכיב [משנה קול Pro](https://nodaro.ai/docs/nodes/audio/voice-changer-pro) מזהה כל דובר בהקלטה, נותן לכל אחד מהם קול אחר ושומר על המילים ועל התזמון. הרכיב רץ ב-Nodaro Cloud. התקנה באירוח עצמי שמחוברת ל-Nodaro Cloud יכולה להריץ דרך החיבור הזה את החלפת הקולות בשלב אחד; שלבי הניתוח והייצוא דורשים את Nodaro Cloud עצמו. ראו את הדף [חיבור ל-Nodaro Cloud](https://nodaro.ai/docs/self-hosting/cloud-connect).

| שיטה | נתיב | מה היא עושה |
| --- | --- | --- |
| `POST` | `/v1/voice-changer-pro` | החלפת הקולות של כל הדוברים ששויכו להם קולות, כסרטון מוגמר או כסטמים נפרדים. |
| `POST` | `/v1/voice-changer-pro/analyze` | זיהוי הדוברים בלי להחליף קולות. ב-Nodaro Cloud בלבד. |
| `POST` | `/v1/voice-changer-pro/export` | רינדור סרטון מוגמר מהמיקס שלכם של הסטמים. ב-Nodaro Cloud בלבד. |
| `POST` | `/v1/voice-changer-pro/translate` | תרגום התמלול שזוהה לשפה אחרת, כדי להקריא מחדש את הסרטון בשפה הזו. ב-Nodaro Cloud בלבד. |

### שיוך קולות לדוברים
השדה `orderedVoices` משייך קולות לדוברים לפי סדר הזיהוי: דובר 0 מקבל את פריט 0, דובר 1 את פריט 1, וכן הלאה. ברשימה יש בין 1 ל-8 פריטים. דוברים שמעבר לסוף הרשימה שומרים על הקול שלהם. כל פריט הוא אחד מאלה:

- **מזהה קול**, למשל `"Rachel"`.
- **`null`**, פריט שמירת מקור: הדובר הזה שומר על הקול שלו, והקולות של הדוברים שאחריו עדיין מוחלפים. פריטי שמירת מקור לא עולים כלום, אבל לפחות פריט אחד חייב להיות קול.
- **אובייקט** עם הגדרות לכל דובר: `{ voiceId, engine?, stability?, similarityBoost?, style?, useSpeakerBoost?, seed?, volumeMode?, volume?, languageCode? }`. השדה `engine` הוא `sts` (ברירת המחדל, המרה מדיבור לדיבור), `v3` או `v4`. המנוע `v3` יוצר ביצוע חדש של השורה מהתמלול עם ElevenLabs v3, ומקבל רק `stability` של 0, 0.5 או 1. המנוע `v4` עושה את אותו הדבר עם ElevenLabs v4, מקבל כל `stability` בין 0 ל-1 ומחיל את `similarityBoost`. השדה `languageCode` מתקבל רק עם `v4`, כדי להקריא שורה מתורגמת, כמו שמתואר בהמשך. השדה `volumeMode` הוא `match` (ברירת המחדל), `normalize` או `manual`, עם `volume` בטווח 0%–200%.

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

| שדה | מה הוא עושה |
| --- | --- |
| `audioUrl` או `videoUrl` | נדרש אחד מהשניים. בסרטון, האודיו עם הקולות החדשים חוזר לתמונה המקורית. |
| `preserveBackground` | מחזיר את המוזיקה ואת האפקטים למיקס, מתחת לקולות החדשים. ברירת המחדל היא `true`. |
| `separationQuality` | `fast` (ברירת המחדל, שומר יותר מהקול) או `best` (הפרדה עדינה יותר). |
| `removeBackgroundNoise` | מסיר גם רעשים מהתוצאה. |
| `musicVolumeMode`, `musicVolume` | העוצמה של הרקע שנשמר: `match` (ברירת המחדל), `normalize` או `manual` עם ערך בטווח 0%–200%. |
| `voiceFx` | ריוורב או הד על הקולות בלבד: `{ preset, wetDryMix?, delayMs?, decay? }`. ערכות ריוורב כגון `room`, `hall` או `church` משתמשות ב-`wetDryMix`, והערכות `echo` ו-`custom` משתמשות ב-`delayMs` וב-`decay`. |
| `output` | `video` (ברירת המחדל, התוצאה המוגמרת) או `stems` (רצועות יבשות, בלי איזון עוצמה, למיקס משלכם). |
| `analysis` | ה-`output_data` של משימת ניתוח קודמת. החלפת הקולות משתמשת שוב בדוברים ובסטמים שלה, במקום לזהות אותם מחדש. |

החלפת הקולות מחויבת לפי מספר הדוברים ששויכו להם קולות; לניתוח ולייצוא יש מחיר קבוע. למחירים, ראו את הדף [משנה קול Pro](https://nodaro.ai/docs/nodes/audio/voice-changer-pro).

**הקראה מחדש בשפה אחרת.** הנתיב `POST /v1/voice-changer-pro/translate` מתרגם את השורות של הדוברים בניתוח לשפת יעד אחת, מקטע אחרי מקטע. לכל שורה יש מגבלת אורך, כדי שהשורה שמוקראת מחדש תיכנס בחלון הזמן שלה. גוף הבקשה הוא `{ speakers, targetLanguage, sourceLanguage?, tier? }`, כשהשדה `speakers` מגיע מהניתוח והשדה `tier` הוא `economy`, `standard` או `premium`. ב-`output_data.speakers` של המשימה נשמרים כל הדוברים, המקטעים והתזמונים, עם ה-`text` המתורגם, עם המקור ב-`sourceText` ועם `untranslated`, המזהים של השורות שנשארו בשפת המקור. בדקו את הטקסט, ואז שלחו את הדוברים האלה בתור `analysis.speakers` של החלפת הקולות, עם `engine: "v4"` ועם `languageCode` שערכו שפת היעד בכל קול שמוקרא מחדש. בקשה עם `languageCode` ב-`sts` או ב-`v3`, או עם שפה שהמודל לא מציע, נדחית עם `400`. מחיר התרגום נקבע לפי אורך הטקסט, עם מחיר מינימום ומחיר מקסימום לכל 1,000 תווים, או חלק מהם, ששניהם נקבעים לפי ה-`tier`. מחוץ ל-Nodaro Cloud, ארבעת הנתיבים של `voice-changer-pro` מחזירים `404`.

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

### זיהוי הדוברים
קראו ל-`POST /v1/voice-changer-pro/analyze` עם `audioUrl` או `videoUrl`, ובאופן אופציונלי גם עם `separationQuality` ו-`suggestTitle`. ב-`output_data` של המשימה שהסתיימה מופיעים `vocalsUrl` ו-`backgroundUrl` המופרדים, וגם `languageCode` ו-`languageProbability` שזוהו. ברשימה `speakers` מופיעים לכל דובר `id`, `segments`, `firstStartSec`, `wordCount` ו-`snippet`. כשביקשתם, יש שם גם `suggestedTitle`. חפשו ״דוברים״ שהם לא אנשים, כגון מחיאות כפיים.

### החלפת הקולות לסטמים
קראו ל-`POST /v1/voice-changer-pro` עם `output: "stems"` ועם כל ה-`output_data` של הניתוח בתור `analysis`. החלפת הקולות מדלגת על הזיהוי, ולכן אפשר להחליף שוב את הקולות בקולות אחרים בלי לשלם שוב על הזיהוי.

### מיקס וייצוא
קבעו את העוצמה של כל סטם בממשק שלכם; זה לא עולה כלום. אחר כך קראו ל-`POST /v1/voice-changer-pro/export` עם ה-`videoUrl` של המקור ועם עד 16 רצועות ב-`tracks`, כל אחת `{ url, gain, muted, kind? }`. הערך `gain` הוא בין 0 ל-200, השדה `kind` הוא `voice` או `background`, ולפחות רצועה אחת צריכה להיות לא מושתקת. שדה `voiceFx` אופציונלי חל רק על רצועות הקול. זרם הווידאו מועתק ואף פעם לא מקודד מחדש, ולכן הייצוא תואם את התצוגה המקדימה שלכם. התוצאה היא `output_data.videoUrl` של המשימה שהסתיימה.

**curl**

```bash
AUTH="Authorization: Bearer $NODARO_API_KEY"
VIDEO="https://cdn.nodaro.ai/uploads/panel.mp4"

# 1. Detect the speakers
JOB=$(curl -s -X POST https://app.nodaro.ai/v1/voice-changer-pro/analyze -H "$AUTH" \
  -H 'Content-Type: application/json' -d "{\"videoUrl\":\"$VIDEO\",\"suggestTitle\":true}" | jq -r .jobId)
# ...poll until completed, then keep the analysis
ANALYSIS=$(curl -s "https://app.nodaro.ai/v1/jobs/$JOB/status" -H "$AUTH" | jq .data.output_data)

# 2. Recast to stems: speaker 2 keeps their own voice
JOB=$(curl -s -X POST https://app.nodaro.ai/v1/voice-changer-pro -H "$AUTH" -H 'Content-Type: application/json' \
  -d "{\"videoUrl\":\"$VIDEO\",\"orderedVoices\":[\"Rachel\",null,\"Aria\"],\"output\":\"stems\",\"analysis\":$ANALYSIS}" | jq -r .jobId)

# 3. Export your mix
curl -s -X POST https://app.nodaro.ai/v1/voice-changer-pro/export -H "$AUTH" -H 'Content-Type: application/json' -d "{
\"videoUrl\": \"$VIDEO\",
\"tracks\": [
{ \"url\": \"<voice stem 0>\", \"gain\": 100, \"muted\": false },
{ \"url\": \"<voice stem 1>\", \"gain\": 90, \"muted\": false },
{ \"url\": \"<background stem>\", \"gain\": 70, \"muted\": false, \"kind\": \"background\" }
],
\"voiceFx\": { \"preset\": \"hall\", \"wetDryMix\": 25 }
}"
```

**TypeScript SDK**

```ts
const { jobId: analyzeJob } = await client.voices.analyze({ videoUrl, suggestTitle: true })
const analysis = (await client.jobs.get(analyzeJob)).output_data // once completed

const { jobId: recastJob } = await client.voices.recast({
videoUrl,
orderedVoices: ['Rachel', null, 'Aria'],
output: 'stems',
analysis,
})
const stems = (await client.jobs.get(recastJob)).output_data // once completed

await client.voices.exportMix({
videoUrl,
tracks: [
{ url: stems.tracks[0].url, gain: 100, muted: false },
{ url: stems.tracks[1].url, gain: 90, muted: false },
{ url: stems.backgroundUrl, gain: 70, muted: false, kind: 'background' },
],
voiceFx: { preset: 'hall', wetDryMix: 25 },
})
```

**CLI**

```bash
nodaro voice analyze --video https://cdn.nodaro.ai/uploads/panel.mp4 --watch --json > analyze.json
jq .output_data analyze.json > analysis.json

nodaro voice recast --video https://cdn.nodaro.ai/uploads/panel.mp4 --voices Rachel,keep,Aria \
  --analysis-file analysis.json --output stems --watch

nodaro voice export --source https://cdn.nodaro.ai/uploads/panel.mp4 --tracks-file mix.json \
  --voice-fx hall --voice-fx-mix 25 --watch
```

ב-CLI, המילה `keep` ב-`--voices` היא פריט שמירת מקור.

## דיבוב לשפה אחרת
הנתיב `POST /v1/dubbing` מתרגם רצועת אודיו או סרטון שלם ומדבב אותם מחדש, ושומר על הקול של כל דובר. שלחו מקור אחד בדיוק: `audioUrl`, `videoUrl` או `sourceUrl` (קישור ציבורי לדף שבו נמצא סרטון, או קישור ישיר לקובץ מדיה, שמודל הדיבוב מושך בעצמו). שליחת `sourceUrl` היא ייבוא של הקישור הזה: שלחו את ה-`confirmationId` שאושר עבורו. ראו את דף ה-API [זכויות תוכן](https://nodaro.ai/docs/developers/api/content-rights). סרטון חוזר כסרטון מדובב: `output_data.videoUrl`, ובנוסף רצועת הדיבוב לבדה ב-`output_data.audioUrl`.

| שדה | מה הוא עושה |
| --- | --- |
| `targetLanguage` | נדרש. קוד ISO, למשל `es` או `pt-BR`. |
| `sourceLanguage` | השפה המדוברת. כשלא שולחים אותה, היא מזוהה אוטומטית. |
| `numSpeakers` | הערך `0` (ברירת המחדל) מזהה את הדוברים אוטומטית; ערך בין 1 ל-20 משפר את ההפרדה כשאתם יודעים כמה דוברים יש. |
| `startTime`, `endTime` | דיבוב של חלון הזמן הזה במקור בלבד, בשניות. |
| `disableVoiceCloning`, `dropBackgroundAudio` | ויתור על שחזור הקול של כל דובר, או השמטה של המוזיקה והאפקטים. |
| `highestResolution` | שמירה על הרזולוציה של המקור בסרטון. |
| `useProfanityFilter`, `targetAccent`, `watermark` | מסנן ניבולי פה, מבטא לשפת היעד, וסימן המים של מודל הדיבוב על סרטון. |

המחיר של דיבוב נקבע לפי דקות הקטע המדובב, עם מינימום של דקה אחת. הקטע יכול להיות באורך של עד 30 דקות; בקשה עם קטע ארוך יותר נדחית עם `413`, ולכן דבבו חלון זמן עם `startTime` ו-`endTime`. ראו את הדף [דיבוב](https://nodaro.ai/docs/nodes/audio/dubbing).

## ייבוא סרטון מקישור
הנתיב `POST /v1/download-video` מייבא לאחסון שלכם את הסרטון שמאחורי קישור: הדף של הסרטון או קישור ישיר לקובץ וידאו. הנתיב מחזיר `{ downloadId }`, לא מזהה משימה. הקובץ המוגמר נשמר בספרייה שלכם.

| שדה | מה הוא עושה |
| --- | --- |
| `url` | נדרש. הדף או הקובץ לייבוא. |
| `maxHeight` | תקרה לרזולוציה, למשל `720`. השמיטו אותו כדי לקבל את הרזולוציה הטובה ביותר שזמינה. |
| `sectionStartSec`, `sectionEndSec` | ייבוא של הטווח הזה בלבד, בשניות, עם כמה שניות נוספות בכל צד, כי החיתוך נופל על פריימי מפתח. שלחו את שניהם או אף אחד מהם, וקצצו את התוצאה כדי לקבל חיתוך מדויק. |
| `exactSection` | הערך `true` חותך במקום זאת את הקטע בדיוק בטווח שביקשתם, בלי שוליים. |
| `requireAudio` | כברירת מחדל, תוצאה בלי סאונד נכשלת, כי בדרך כלל היא מעידה על מקור באיכות ירודה. שלחו `false` כדי שגם קליפ שקט יתקבל. |
| `confirmationId` | אישור זכויות התוכן לקישור הזה, מ-`POST /v1/content-rights/confirm`. ראו את דף ה-API [זכויות תוכן](https://nodaro.ai/docs/developers/api/content-rights). |

ייבוא של קישור מריץ את בדיקת זכויות התוכן לפני שמשהו נמשך. אישור שלא מתאים, או אתר שהפריסה לא מתירה, נדחים עם `403` ועם הקוד שמסביר למה. ראו בדף ה-API [זכויות תוכן](https://nodaro.ai/docs/developers/api/content-rights#errors).

האזינו להתקדמות ההורדה ב-`GET /v1/download-video/progress/:downloadId`, זרם של אירועי שרת (SSE). בערך כל 500 אלפיות שנייה הזרם שולח `{ phase, percent, videoUrl?, thumbnailUrl?, error? }`, והוא מסתיים ב-`completed`, עם ה-`videoUrl` השמור, או ב-`failed`, עם ה-`error`. התחילו להאזין ברגע שהייבוא מתחיל, כי ההתקדמות נשמרת רק לזמן קצר אחרי שההורדה מסתיימת. בכל חשבון רצות לכל היותר 4 הורדות במקביל; הורדה חמישית נדחית עם `429 too_many_downloads`.

**curl**

```bash
DL=$(curl -s -X POST https://app.nodaro.ai/v1/download-video \
  -H "Authorization: Bearer $NODARO_API_KEY" -H 'Content-Type: application/json' \
  -d '{ "url": "https://www.youtube.com/watch?v=VIDEO_ID", "maxHeight": 720 }' | jq -r .downloadId)

curl -sN https://app.nodaro.ai/v1/download-video/progress/$DL \
  -H "Authorization: Bearer $NODARO_API_KEY"
```

**TypeScript SDK**

```ts
const { downloadId } = await client.media.downloadVideo({
url: 'https://www.youtube.com/watch?v=VIDEO_ID',
maxHeight: 720,
})
for await (const event of client.media.downloadVideoProgress(downloadId)) {
console.log(`${event.phase} ${event.percent}%`)
if (event.phase === 'completed') console.log('stored at', event.videoUrl)
}
```

**CLI**

```bash
nodaro media download "https://www.youtube.com/watch?v=VIDEO_ID" --max-height 720 --watch
nodaro media metadata "https://www.youtube.com/watch?v=VIDEO_ID"
```

שני נתיבים קשורים עונים מיד:

- הנתיב `POST /v1/video-metadata` עם `{ url }` קורא את משך הסרטון, את הגודל ואת הכותרת שלו, ואם הוא שידור חי, בלי להוריד אותו. השתמשו בו כדי להחליט אם לייבא רק קטע.
- הנתיב `POST /v1/save-to-storage` עם `{ mediaUrl, filename?, mediaType? }` מעתיק לאחסון שלכם, בצד השרת, מדיה מכל כתובת URL חיצונית. הנתיב מחזיר משימה.

## עריכת וידאו
| שיטה | נתיב | מה היא עושה | מחיר |
| --- | --- | --- | --- |
| `POST` | `/v1/trim-video` | קיצוץ סרטון לטווח. | [קיצוץ וידאו](https://nodaro.ai/docs/nodes/video/trim-video) |
| `POST` | `/v1/add-captions` | צריבת כתוביות בסרטון. | [הוספת כתוביות](https://nodaro.ai/docs/nodes/video/add-captions) |
| `POST` | `/v1/still-to-video` | תמונה אחת ורצועת אודיו אחת הופכות ל-MP4. | 0 קרדיטים |
| `POST` | `/v1/slideshow` | 2–100 תמונות ורצועת אודיו אופציונלית הופכות ל-MP4. | 0 קרדיטים |
| `POST` | `/v1/video-overlay` | הצבה של 1–20 שכבות תמונה מתוזמנות על סרטון. | 22 קרדיטים |
| `POST` | `/v1/media/process` | קיצוץ או חיתוך של קובץ ששמרתם, עם תשובה מיידית. | חינם |
| `POST` | `/v1/edit-plan` | תכנון עריכה של הקלטה לפי התמלול שלה: הידוק, מציאת קליפים, סימון פרקים או חיתוך טריילר. התוצאה היא רשימת עריכה (EDL), לא מדיה. | [תוכנית עריכה](https://nodaro.ai/docs/nodes/video/edit-plan) |
| `POST` | `/v1/camera-switch` | העברה של כל חיתוך בעריכה למצלמה של מי שמדבר. הסאונד אף פעם לא משתנה. | [מחליף מצלמות](https://nodaro.ai/docs/nodes/video/camera-switch) |
| `POST` | `/v1/apply-edl` | רינדור של רשימת עריכה לקובץ וידאו או אודיו אחד, באיכות `final` או כתצוגה מקדימה ב-`proxy`. | [החלת רשימת עריכה](https://nodaro.ai/docs/nodes/video/apply-edl) |
| `POST` | `/v1/tighten-episode` | הידוק של פודקאסט או ראיון בקריאה אחת: תמלול, הסרת שתיקות ומילות מילוי, רינדור הפרק, ואם רוצים גם הוספת כתוביות ומוזיקת רקע. | [הידוק פרק](https://nodaro.ai/docs/nodes/video/tighten-episode) |
| `POST` | `/v1/speaker-view` | רינדור של עריכה עם הדוברים שלה על המסך, בפריסה, עם מעבר בכל החלפת דובר. המחיר נקבע לפי דקות הפלט. | [תצוגת דוברים](https://nodaro.ai/docs/nodes/video/speaker-view#credits) |
| `POST` | `/v1/split-media` | חיתוך של סרטון, קובץ אודיו או שניהם לחלקים שהאורך שלהם בין מינימום למקסימום, או של סרטון לחלק אחד לכל שוט. | 22 קרדיטים להרצה |
| `POST` | `/v1/video-mask` | מעקב אחרי נושא שמתואר בטקסט, והחזרה של סרטון מסכה בשחור־לבן. המחיר נקבע לפי אורך הקליפ. | [מסכת וידאו](https://nodaro.ai/docs/nodes/video/video-mask) |
| `POST` | `/v1/mask-composite` | הצבה של סרטון חזית על סרטון רקע דרך סרטון מסכה. | 11 קרדיטים לכל 5 שניות, או חלק מהן |
| `POST` | `/v1/video-depth` | הפיכה של סרטון לסרטון עומק: מה שקרוב בהיר, ומה שרחוק כהה. המחיר נקבע לפי אורך הקליפ. | [עומק וידאו](https://nodaro.ai/docs/nodes/video/video-depth) |

רכיבי תוכנית עריכה ומחליף מצלמות, ושלב התכנון של רכיב הידוק פרק, רצים ב-Nodaro Cloud. התקנה באירוח עצמי מריצה אותם דרך [החיבור ל-Nodaro Cloud](https://nodaro.ai/docs/self-hosting/cloud-connect) שלה, ובלי חיבור כזה היא מחזירה `503 nodaro_connection_required`.

הנתיב `POST /v1/split-media` מקבל `videoUrl`, `audioUrl` או את שניהם, `chunkDuration` (האורך המקסימלי של חלק, לפחות שנייה אחת), `minPartDuration` (ברירת המחדל 4, אף פעם לא יותר מ-`chunkDuration`) ו-`audioFormat` (`mp3`, `wav` או `aac`). ב-`output_data` של המשימה שהסתיימה יש `videoUrls`, `audioUrls`, `chunkCount` ו-`partDurationsSec`.

בקשה עם `{ videoUrl, mode: "shots" }` חותכת במקום זאת סרטון לחלק אחד לכל שוט, בנקודות החיתוך שנמדדות מהקובץ. המצב הזה לא מקבל אורך חלק, ומקבל סרטון בלבד: בקשה עם `audioUrl` נפרד נדחית עם `400 validation_error`. כל חלק שומר על הסאונד של הסרטון עצמו. סרטונים יכולים להיות באורך של עד 30 דקות, עם 200 שוטים לכל היותר, באותו מחיר. הפלט כולל אז גם `shotCount` ו-`shots: [{ index, startSec, endSec, durationSec }]`. על האופן שבו החלקים נחתכים, ראו את הדף [פיצול למקטעים](https://nodaro.ai/docs/nodes/video/split-into-chunks).

הנתיב `GET /v1/edit-plan/capabilities` מציג את המצבים של רכיב תוכנית עריכה שהשרת הזה יכול לתכנן: `{ modes, source, perMinute }`. הערכים `tighten`, `clips` ו-`chapters` תמיד מופיעים, ו-`trailer` רק כשהשרת יכול לתכנן טריילר. השדה `perMinute` הוא `true` כשהחיוב על רכיב תוכנית עריכה נקבע לפי כל דקה של ההקלטה, או חלק ממנה. בקשה ל-`POST /v1/edit-plan` עם מצב שהשרת לא מציג נדחית עם `400 mode_not_available`, לפני כל חיוב.

### הידוק פרק
הנתיב `POST /v1/tighten-episode` מריץ את רכיב [הידוק פרק](https://nodaro.ai/docs/nodes/video/tighten-episode) על הקלטה אחת. גוף הבקשה הוא `{ mediaUrls: [<recording URL>], musicUrl?, output?, framing?, captions?, captionStyle?, reviewBeforeRender?, planTier?, instructions?, styleGuide?, musicDuckAmount? }`. השדה `framing` הוא `{ aspect, layout }` או `null`. הנתיב מחזיר `202` עם `{ jobId, executionId }`.

- **בדקו את מצב המשימה** עם `GET /v1/jobs/:id/status`. ב-`output_data` שלה נמצאים הפרק (`videoUrl`, או `audioUrl` לפרק אודיו), העריכה (`json`), התמלול (`transcript`) ו-`quality`: הערך `proxy` לתצוגה המקדימה של הרצה שעוצרת לבדיקה, ו-`final` בכל מקרה אחר. הרצה שנכשלה שומרת את מה שהושלם, ומציינת את השלב שנכשל ב-`failedStep`.
- **נסו שוב בבטחה.** כותרת `Idempotency-Key` גורמת לכך שניסיון חוזר של אותה בקשה יחזיר את אותו `jobId` עם `"deduped": true`, בלי להתחיל שום דבר.
- **קבלו קודם אומדן מחיר.** הנתיב `POST /v1/tighten-episode/estimate` מקבל את אותו גוף בקשה ומחזיר `{ data: { totalCredits, stepsCredits, feeCredits, durationSec } }`, בלי להתחיל שום דבר. כששלב מסוים הוא אומדן של קריאת LLM שמחויבת לפי השימוש, התגובה כוללת גם `estimate: true`: הציגו את הסכום הכולל כ-`≈N`. האומדן מתמחר את הרינדור לפי האורך המלא של ההקלטה, ולכן ההרצה בדרך כלל עולה פחות.
- **המשיכו הרצה.** הנתיב `POST /v1/tighten-episode/continue` עם `{ jobId, mode }` ממשיך אחת ההרצות שלכם. הערך `"mode": "from-failed"` מריץ רק את מה שהרצה שנכשלה לא השלימה. הערך `"mode": "render-final"`, עם `editedEdl` אופציונלי ובו העריכה שלכם לתוכנית, מרנדר את הגרסה הסופית של הרצה שעצרה לבדיקה.

בקשה לרינדור סופי של הרצה שלא הייתה תצוגה מקדימה נדחית עם `render_final_not_preview`, ובקשה לרינדור סופי של עריכה שכבר רונדרה נדחית עם `render_final_already_rendered`. בקשה להמשיך הרצה שלא נכשלה נדחית עם `409 continuation_not_failed`.

בתוך תהליך, רכיב הידוק פרק שהמתג **סקירה לפני רינדור** מופעל בו צריך שמישהו יבדוק אותו, בעורך או בדף של אפליקציה. בהרצת תהליך שהתחילה מה-API, מה-SDK, מכלי ה-MCP `run_workflow` או מטריגר, הרכיבים שלפניו רצים ומשלמים עליהם, ואז הרכיב נכשל עם `preview_review_required`, ולא משלמים עליו כלום. בהרצות כאלה, כבו את האפשרות **סקירה לפני רינדור**. רכיב שהאפשרות הזו מופעלת בו ושמוזן מרכיב רשימה נדחה עוד לפני שאחת ההרצות שלו מתחילה, עם `use_case_review_list_driven`. ה-SDK קורא לאותם נתיבים עם `client.edit.tightenEpisode`, `client.edit.estimateTightenEpisode` ו-`client.edit.continueUseCase`, וה-CLI עם `nodaro edit tighten-episode` ו-`nodaro edit continue-use-case`. דרך MCP, השתמשו בכלים `tighten_episode` ו-`continue_use_case`.

### קיצוץ סרטון
הנתיב `POST /v1/trim-video` מקבל `videoUrl` ואת הטווח ביחידה שנוחה לכם: השדות `startTime` ו-`endTime` בשניות, `trimStartFrames` ו-`trimEndFrames`, `trimStartSeconds` ו-`trimEndSeconds`, או `keepFirstSeconds` או `keepLastSeconds`.

### צריבת כתוביות
הנתיב `POST /v1/add-captions` מקבל `videoUrl`, ולוקח את המילים מהמקור הראשון שהוא מוצא, בסדר הזה: `captions` (רשומות עם תזמון לכל מילה), `transcript`, `text` בסגנון `subtitle`, ואחר כך תמלול אוטומטי של הדיבור.

| שדה | מה הוא עושה |
| --- | --- |
| `style` | `subtitle` (גוש טקסט סטטי), או סגנון מונפש: `word-highlight`, `karaoke`, `tiktok-words`, `word-pop` או `bouncy`. |
| `text` | בסגנון `subtitle`: הכתובית עצמה, שנצרבת כגוש סטטי אחד לכל אורך הסרטון. בסגנון מונפש: רק חלופה, כשהתמלול לא מוצא כלום. |
| `captions` | רשומות עם תזמון למילים, `{ text, startMs, endMs }`, אחת לכל מילה בסגנונות המונפשים. השדה `words` של תמלול מתאים כמו שהוא. |
| `auto_transcribe`, `transcribe_provider` | תמלול הדיבור כששום מקור אחר לא נותן את המילים. סגנון מונפש צריך תזמון לכל מילה: המנוע `incredibly-fast-whisper` (ברירת המחדל) או `elevenlabs-stt`. |
| `look` | `outline` (ברירת המחדל בסגנונות המונפשים) או `clean` (ברירת המחדל בסגנון `subtitle`). |
| `maxWordsPerLine` | 1–20 מילים בשורה, בנוסף למגבלה של רוחב הפריים. 1 או 2 נותנים כתוביות קצרות וקולעות. |
| `highlightColor`, `animate` | בסגנונות מונפשים בלבד; בסגנון `subtitle` הם נדחים עם `400`. |
| `position`, `positionY`, `fontSize`, `fontFamily`, `fontWeight`, `color`, `backgroundColor`, `strokeColor`, `strokeWidth`, `uppercase` | המראה של הטקסט. |
| `segments` | סגנון, מראה ומיקום משלהם לטווחים מסוימים בסרטון. |

סגנון `subtitle` עם טקסט פשוט, בלי עיצוב, הוא הרינדור הזול. סגנון מונפש, כל שדה עיצוב, כתוביות מתוזמנות, תמלול אוטומטי או `segments` מרונדרים במחיר הגבוה יותר ושומרים על קצב הפריימים של המקור. לכל האפשרויות ולשני המחירים, ראו את הדף [הוספת כתוביות](https://nodaro.ai/docs/nodes/video/add-captions).

### הפיכת תמונות נייחות לווידאו
- **`POST /v1/still-to-video`** מקבל `{ imageUrl, audioUrl, motion?, intensity?, resolution?, aspectRatio?, fps?, fit?, padColor? }`. הסרטון ארוך בדיוק כמו האודיו; אין שדה של משך. השדה `motion` הוא `none` (ברירת המחדל), `zoom-in`, `zoom-out`, `pan-left`, `pan-right` או `ken-burns`, עם `intensity` מ-1 עד 10. ראו את הדף [תמונה נייחת לווידאו](https://nodaro.ai/docs/nodes/video/still-to-video).
- **`POST /v1/slideshow`** מקבל `imageUrls` (2–100), `audioUrl` אופציונלי, `imageDurations` (שניות לכל תמונה, `null` לחישוב אוטומטי) או `perImageDuration`, `transition` ואת אותם שדות מראה. עם אודיו, המצגת ארוכה בדיוק כמו האודיו; משכים קבועים שהסכום שלהם לא מתאים מותאמים באופן יחסי, והפלט של המשימה מציין זאת. בלי אודיו, המצגת נמשכת מספר התמונות כפול `perImageDuration`, בשקט. ראו את הדף [מצגת](https://nodaro.ai/docs/nodes/video/slideshow).

שני הנתיבים מרנדרים בשרת, בלי מודל AI, ועולים 0 קרדיטים. השדה `resolution` הוא `720p`, `1080p` או `4K`, השדה `fps` הוא `24` או `30`, והערך `fit: "contain"` מוסיף פסים בצבע של `padColor` במקום לחתוך.

### שכבות תמונה על סרטון
הנתיב `POST /v1/video-overlay` מציב 1–20 שכבות תמונה על סרטון ברינדור אחד, ולא נוגע באודיו של סרטון הבסיס. כל שכבה היא `{ imageUrl, start, end?, preset?, corner?, anchor?, x?, y?, width?, height?, fit?, opacity?, animate?, zIndex? }`. הערכים `start` ו-`end` הם בשניות; בלי `end`, השכבה נמשכת עד סוף הסרטון. השדה `preset` הוא `card`, `corner-badge` או `full-frame`, ומיקום או גודל מפורשים גוברים עליו. שכבה בלי אף אחד מהם היא תג פינה, בפינה הימנית התחתונה, אלא אם השדה `corner` מציין פינה אחרת.

השדה `outputAspect` (`16:9`, `9:16`, `1:1` או `4:5`) משנה את יחס הגובה־רוחב של הפריים, יחד עם `baseFit` ו-`backgroundColor`. המשימה מחזירה `{ videoUrl, thumbnailUrl, width, height, durationSec, warnings }`. הנתיב עולה 22 קרדיטים להרצה, בלי קשר למספר השכבות, וכל משתמש יכול לשלוח עד 30 בקשות בדקה. ראו את הדף [שכבה על וידאו](https://nodaro.ai/docs/nodes/video/video-overlay).

### קיצוץ או חיתוך של קובץ ששמרתם, עם תשובה מיידית
הנתיב `POST /v1/media/process` מקצץ או חותך קובץ ששמרתם, ועונה באותה בקשה, בחינם. גוף הבקשה הוא `{ sourceUrl, type, trim?, crop?, format?, deleteSource? }`: השדה `type` הוא `video` או `audio`, השדה `trim` הוא `{ startTime, endTime }`, השדה `crop` הוא `{ x, y, width, height }`, והשדה `format` הוא `mp4`, `webm`, `mp3`, `wav`, `m4a` או `aac`. הנתיב מחזיר `{ data: { url, thumbnailUrl, assetId, sizeBytes, mimeType, metadata } }`. הערך `deleteSource: true` מוחק אחר כך את קובץ המקור, כשהוא שלכם ושום דבר אחר לא משתמש בו.

## עריכת אודיו
כל נתיב מחזיר משימה.

| שיטה | נתיב | גוף הבקשה | מה היא עושה |
| --- | --- | --- | --- |
| `POST` | `/v1/audio-separation` | `{ audioUrl, mode?, quality? }` | פיצול רצועה: `vocal_instrumental` (ברירת המחדל) או `stems` מלאים, באיכות `auto`, `fast` או `best`. ראו את הדף [הפרדת אודיו](https://nodaro.ai/docs/nodes/audio/audio-separation). |
| `POST` | `/v1/audio-isolation` | `{ audioUrl }` | שמירה על הקול הראשי והסרת הרקע. ראו את הדף [מחלץ קול](https://nodaro.ai/docs/nodes/audio/voice-extractor). |
| `POST` | `/v1/audio-fx` | `{ audioUrl, preset?, mix?, delayMs?, decay?, eqLow?, eqHigh? }` | אפקט ריוורב, הד, טלפון או מגפון. ראו את הדף [אפקטי אודיו](https://nodaro.ai/docs/nodes/audio/audio-fx). |
| `POST` | `/v1/mix-audio` | `{ audioUrls, trackVolumes?, duck?, endAt? }` | שילוב של 2–20 רצועות בשכבות, כל אחת בעוצמה של 0%–200%. השדה `duck` הוא `{ under, amount?, thresholdDb?, ratio?, attackMs?, releaseMs? }`: כל רצועה חוץ מ-`audioUrls[under]` מונמכת כל עוד הרצועה הזו חזקה. המחיר זהה עם `duck` ובלעדיו. השדה `endAt` הוא `"longest"` (ברירת המחדל) או `"voice"`, שמסיים את המיקס כשהרצועה `duck.under` מסתיימת, ודורש את `duck`. ראו את הדף [מיקס אודיו](https://nodaro.ai/docs/nodes/audio/mix-audio). |
| `POST` | `/v1/adjust-volume` | `{ audioUrl or videoUrl, volume?, normalize?, fadeIn?, fadeOut? }` | שינוי העוצמה, נרמול או עמעום. ראו את הדף [כוונון עוצמה](https://nodaro.ai/docs/nodes/audio/adjust-volume). |
| `POST` | `/v1/pitch-tempo` | `{ audioUrl or videoUrl, semitones?, tempo?, preserveFormants? }` | הזזה של גובה הצליל בין `-12` ל-12 חצאי טונים, או שינוי הטמפו מ-0.5 עד 2 בלי לשנות את גובה הצליל. סרטון שומר על התמונה שלו, והטמפו שלו נשאר 1. 22 קרדיטים לכל דקה של הקלט, או חלק ממנה, עד 30 דקות. ראו את הדף [גובה צליל וטמפו](https://nodaro.ai/docs/nodes/audio/pitch-tempo). |
| `POST` | `/v1/combine-audio` | `{ segments: [{ url, startTime?, endTime? }] }` | איחוד מקטעים ברצף, זה אחרי זה. ראו את הדף [שילוב אודיו](https://nodaro.ai/docs/nodes/audio/combine-audio). |
| `POST` | `/v1/trim-audio` | `{ audioUrl or videoUrl, startTime?, endTime?, audioFormat? }` | קיצוץ אודיו, או חילוץ שלו מסרטון, בפורמט `mp3` (ברירת המחדל), `wav` או `aac`. ראו את הדף [קיצוץ אודיו](https://nodaro.ai/docs/nodes/audio/trim-audio). |
| `POST` | `/v1/silence-detect` | `{ audioUrl, thresholdDb?, minSilenceMs?, padMs? }` | מציאת הטווחים השקטים בהקלטה. 11 קרדיטים. ראו את הדף [זיהוי שקט](https://nodaro.ai/docs/nodes/audio/silence-detect). |
| `POST` | `/v1/audio-sync` | `{ sources: [{ id, url }], reference? }` | מדידת ההיסטים בין 2–6 הקלטות של שיחה אחת. ראו את הדף [סנכרון אודיו](https://nodaro.ai/docs/nodes/audio/audio-sync). |

ברירות המחדל של `silence-detect` הן `thresholdDb: -35`, `minSilenceMs: 700` ו-`padMs: 120`, והנתיב מקבל אודיו או וידאו. ה-`output_data.json` שלו הוא `{ version, ranges: [{ startMs, endMs }], durationMs }`.

הנתיב `audio-sync` עולה 11 קרדיטים לכל מקור אחרי הראשון: 11 ל-2 מקורות, 33 ל-4 ו-55 ל-6. המזהים חייבים להיות ייחודיים, והשדה `reference` חייב להיות אחד מהם (כברירת מחדל, המקור הראשון). ה-`output_data.json` שלו הוא `{ version, reference, offsets: [{ sourceId, offsetMs, confidence, driftMsPerHour }], notes }`, כשזמן בהקלטת הייחוס שווה לזמן בהקלטת המקור ועוד `offsetMs`. הסחיפה נמדדת ומצוינת בהערות, אבל אף פעם לא מתוקנת.

## תמלול דיבור
הנתיב `POST /v1/transcribe` הופך דיבור לטקסט ומחזיר משימה. גוף הבקשה הוא `{ audioUrl, provider?, language?, diarize?, tagAudioEvents?, wordTimestamps?, confirmationId? }`, והשדה `audioUrl` יכול להיות גם סרטון. שליחת `audioUrl` שמקשר לדף של סרטון היא ייבוא של הקישור הזה: שלחו את ה-`confirmationId` שאושר עבורו. ראו את דף ה-API [זכויות תוכן](https://nodaro.ai/docs/developers/api/content-rights).

| `provider` | תזמון לכל מילה | הערות |
| --- | --- | --- |
| [`elevenlabs-stt`](https://nodaro.ai/docs/models/audio/elevenlabs-stt) | תמיד | המנוע היחיד שתומך ב-`diarize` (מי אמר כל מילה) וב-`tagAudioEvents` (צחוק, מחיאות כפיים). |
| [`incredibly-fast-whisper`](https://nodaro.ai/docs/models/audio/incredibly-fast-whisper) | עם `wordTimestamps: true` | בלי הדגל, המשימה מצליחה, משלמים עליה, והיא מחזירה רק מקטעים ברמת המשפט. |
| [`whisper`](https://nodaro.ai/docs/models/audio/whisper) | אף פעם | מקטעים ברמת המשפט בלבד. בקשה עם `wordTimestamps: true` נדחית עם `400 validation_error` עוד לפני שמוציאים קרדיטים. |

בקשה בלי `provider` רצה על `whisper`, ולכן ציינו מנוע בכל פעם שאתם צריכים תזמון לכל מילה. ב-`output_data` של המשימה שהסתיימה יש `text`, `language`, `words` (רשומה `{ text, startMs, endMs, speaker? }` אחת לכל מילה, באלפיות שנייה), `json` (התמלול המנורמל, גם הוא באלפיות שנייה), ובמנועים הישנים בלבד גם `segments` בשניות. אפשר להעביר את `words` כמו שהוא ל-`captions` ב-`POST /v1/add-captions`.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/transcribe \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "audioUrl": "https://cdn.nodaro.ai/uploads/talk.mp3", "provider": "elevenlabs-stt", "diarize": true }'
```

**TypeScript SDK**

```ts
const { jobId } = await client.audio.transcribe({
audioUrl: 'https://cdn.nodaro.ai/uploads/talk.mp3',
provider: 'elevenlabs-stt',
})
// once completed, burn the words in as kinetic captions
const words = (await client.jobs.get(jobId)).output_data.words
await client.media.addCaptions({
videoUrl: 'https://cdn.nodaro.ai/uploads/talk.mp4',
captions: words,
style: 'word-highlight',
autoTranscribe: false,
})
```

**CLI**

```bash
nodaro audio transcribe --audio https://cdn.nodaro.ai/uploads/talk.mp3 --provider elevenlabs-stt --watch
nodaro jobs get <jobId> --json | jq '.output_data.words' > words.json
nodaro media add-captions https://cdn.nodaro.ai/uploads/talk.mp4 \
  --captions-file words.json --style word-highlight --no-auto-transcribe --watch
```

## פרסום ברשתות החברתיות
זרימות החיבור פותחות חלונות קופצים, והן מיועדות לאפליקציית הווב. פרסום עובד עם אסימון API אישי. אסימונים של אפליקציות OAuth לא יכולים לנהל את החשבונות המחוברים.

| שיטה | נתיב | מה היא עושה |
| --- | --- | --- |
| `GET` | `/v1/social/providers` | הרשתות הנתמכות, ואם כל אחת מהן זמינה בפריסה הזו. |
| `GET` | `/v1/social/connections` | החשבונות המחוברים שלכם. |
| `DELETE` | `/v1/social/connections/:id` | ניתוק חשבון. |
| `POST` | `/v1/social/telegram/connect` | חיבור טלגרם עם אסימון בוט: `{ botToken }`. |
| `POST` | `/v1/social/connect/custom` | חיבור רשת שמשתמשת בשדות במקום בהתחברות: `{ platform, fields }`. |
| `POST` | `/v1/social/publish` | פרסום מיד. מחזירה משימה. 11 קרדיטים. |
| `POST` | `/v1/social/scheduled-posts` | תזמון פוסט. 11 קרדיטים, שנגבים כשהפוסט מתפרסם. |
| `GET` | `/v1/social/scheduled-posts` | הפוסטים המתוזמנים שלכם, עם סינון לפי `from`, `to` ו-`status`. |
| `PATCH` | `/v1/social/scheduled-posts/:id` | עריכת פוסט כל עוד הסטטוס שלו `queued` או `draft`. |
| `DELETE` | `/v1/social/scheduled-posts/:id` | ביטול פוסט שממתין בתור. ההיסטוריה שלו נשמרת. |

הנתיב `GET /v1/social/providers` מחזיר כל רשת עם `{ id, label, connectKind, editor, category, capabilities, available }`. השדה `category` הוא `social` (פיד שמפרסמים בו פוסטים) או `publishing` (אתר שמפרסמים בו מאמרים). רשת שהפריסה לא הגדירה מופיעה עם `available: false`, ואף פעם לא מוסתרת. רשתות שמתחברים אליהן עם שדות (Bluesky, Dev.to, Hashnode, Medium, WordPress ו-Lemmy) מתארות את השדות שלהן ב-`customFields`, ו-Nodaro בודק את פרטי הגישה מול הרשת לפני שהוא שומר אותם.

הנתיב `POST /v1/social/publish` מקבל `{ platform, action, connectionId?, caption?, mediaUrl or mediaItems, … }`. שני כשלים דורשים טיפול שונה:

- **`503 publish_retryable`**: שום דבר לא פורסם. אפשר לשלוח שוב את אותה בקשה בדיוק בלי חשש.
- **`500 publish_failed`**: התוצאה לא ידועה. שליחה חוזרת עלולה לפרסם פעמיים, ולכן בדקו קודם ברשת.

פוסט מתוזמן מקבל `{ connectionId, action, scheduledAt, caption?, media? }`, וכל פריט מדיה הוא `{ type, r2Key or url }`. המדיה חייבת להיות קבצים ששמורים בפריסה הזו, ו-Nodaro הופך אותם לקישורים חדשים כשהפוסט יוצא; קישורים לאתרים אחרים נדחים. עריכה של פוסט שכבר מתפרסם נדחית עם `409 not_editable`. ראו את הדף [פרסום לרשתות](https://nodaro.ai/docs/nodes/publish/publish-to-social) ואת המדריך [פרסום ברשתות החברתיות](https://nodaro.ai/docs/guides/publishing-to-social).

## המקבילות ב-SDK וב-CLI
| תחום | SDK ל-TypeScript | CLI |
| --- | --- | --- |
| קולות והחלפת קול | `client.voices.list`, `searchLibrary`, `listClones`, `deleteClone`, `change`, `recast`, `analyze`, `exportMix`, `design`, `remix`, `dub` | `nodaro voice list`, `changer`, `recast`, `analyze`, `export`, `design`, `remix`, `dub`, `clones` |
| מדיה | `client.media.downloadVideo`, `downloadVideoProgress`, `videoMetadata`, `trimVideo`, `trimAudio`, `addCaptions`, `stillToVideo`, `slideshow`, `videoOverlay`, `saveToStorage`, `process` | `nodaro media download`, `metadata`, `trim-video`, `trim-audio`, `add-captions`, `still-to-video`, `slideshow`, `video-overlay`, `save` |
| אודיו | `client.audio.separate`, `isolate`, `applyFx`, `mix`, `adjustVolume`, `pitchTempo`, `combine`, `transcribe` | `nodaro audio separate`, `isolate`, `fx`, `mix`, `adjust-volume`, `pitch-tempo`, `combine`, `transcribe` |
| כלי עזר לעריכה | `client.edit.silenceDetect`, `audioSync` | `nodaro edit silence-detect`, `audio-sync` |

דרך MCP, אותם נתיבים זמינים ככלים, כגון `voice_changer`, `voice_changer_pro`, `voice_changer_pro_analyze`, `voice_changer_pro_export`, `dubbing`, `transcribe`, `add_captions` ו-`separate_audio`. ראו את [מדריך כלי ה-MCP](https://nodaro.ai/docs/mcp/tools).

## שגיאות
| סטטוס | קוד | משמעות |
| --- | --- | --- |
| `400` | `validation_error` | שדה חסר או לא תקין, למשל `wordTimestamps` ב-`whisper`, שדה עיצוב שדורש סגנון כתוביות מונפש, או ייצוא שכל הרצועות בו מושתקות. |
| `400` | `provider_not_configured` | הפריסה לא הגדירה את הרשת החברתית הזו. |
| `401` | `unauthorized` | האסימון חסר, לא תקין או מבוטל. |
| `402` | `insufficient_credits` | ב-Nodaro Cloud בלבד. אין בחשבון מספיק קרדיטים למשימה. |
| `404` | `not_found` | נשלחה קריאה לנתיב של משנה קול Pro בפריסה שלא מציעה אותו. |
| `409` | `not_editable` | הפוסט המתוזמן כבר מתפרסם. |
| `410` | `voice_cloning_retired` | שכפול קולות כבר לא זמין. |
| `413` | — | הקטע לדיבוב ארוך מ-30 דקות. |
| `429` | `too_many_downloads` | כבר רצים בחשבון שלכם 4 ייבואים של סרטונים. |
| `500` | `publish_failed` | התוצאה של הפוסט לא ידועה. בדקו ברשת לפני שאתם שולחים אותו שוב. |
| `503` | `publish_retryable` | שום דבר לא פורסם. אפשר לשלוח שוב את אותה בקשה בדיוק בלי חשש. |

## שאלות נפוצות

### איך מחליפים את הקולות של כמה דוברים בסרטון אחד?

שלחו בקשה ל-POST ‎/v1/voice-changer-pro עם השדה orderedVoices, פריט אחד לכל דובר שזוהה, לפי הסדר. פריט null משאיר לדובר הזה את הקול שלו. כדי לבדוק קודם את הדוברים, הריצו את שלב הניתוח, ואז החליפו את הקולות לסטמים וייצאו מיקס משלכם.

### האם אפשר לשכפל קול דרך ה-API?

לא. שכפול קולות הוצא משימוש, והנתיבים של השכפול מחזירים 410 voice_cloning_retired. קולות משוכפלים שנוצרו לפני כן עדיין עובדים כמזהי קול. במקום זאת, עצבו קול חדש לפי תיאור עם POST ‎/v1/voice-design.

### איזה מנוע תמלול נותן תזמון לכל מילה?

המנוע elevenlabs-stt תמיד מחזיר תזמון לכל מילה, והמנוע incredibly-fast-whisper מחזיר אותו כששולחים את wordTimestamps עם הערך true. המנוע whisper מחזיר רק מקטעים ברמת המשפט. בקשה בלי provider רצה על whisper, ולכן ציינו מנוע כשאתם צריכים תזמון לכל מילה.

### מה האורך המרבי של קליפ מדובב?

הקטע המדובב יכול להיות באורך של עד 30 דקות, והמחיר שלו נקבע לפי דקה, עם מינימום של דקה אחת. במקור ארוך יותר, דבבו רק חלון זמן אחד עם השדות startTime ו-endTime.

### אילו כלי מדיה הם חינמיים?

הכלים תמונה נייחת לווידאו ומצגת, והנתיב הסינכרוני POST ‎/v1/media/process לקיצוץ ולחיתוך, עולים 0 קרדיטים. הכלי שכבה על וידאו עולה 22 קרדיטים להרצה, והכלי זיהוי שקט עולה 11 קרדיטים.
