# Skill: full/voice-story — "סיפור השראה בקול שלכם — מנאום, עם רגש" (Complete video)

A famous talk becomes a two-minute reel in Hebrew, told in your own voice — the way the owner's Jack Ma reel was made. The talk is transcribed with who said what; Gemini picks one speaker's story from his own sentences — the failures, the turn, the lesson, a closing line — in the order he said them; the Hebrew is written for the ear and read by a native editor. Your cloned voice reads every passage twice with direction (calm in the story, conviction at the peak), Gemini listens to every take and throws out any that misreads a name or a word. Then the speaker's own footage is cut to follow your voice — his face full screen, the shots without him left out, the original sound muted — with an opening hook in your voice over a fast cut of him, music whose drop lands on the key line, key words in lime and the CC BY credit on screen. Only a talk you may use: your own, Creative Commons by its owner, or with permission.

**Includes:** one speaker's story picked from a whole talk — his own sentences only, in the order he said them · the Hebrew written for the ear and read by a native editor · your own cloned voice, two directed takes a passage, with emotion · Gemini listens to every take — names and numbers right · the speaker's own footage, cut to follow your voice, his face full screen · the original sound muted · an opening hook in your voice over a fast cut of him · music whose drop lands on the key line · key words in lime · the CC BY credit on screen
**Built on:** the talk itself cut with `keep` (time order) and pushed in on the speaker (`zoom` 3 at his face, `fit: "blur"`), your cloned voice's directed takes in `voiceover` with the original muted, captions `keyword-pop` on the source clock with the key words in lime, a `lower-third` name, a licensed track in two cuts and the CC BY credit as a `texts` pill
**Price:** 340–460 credits per finished minute · 30 s ≈ 200–325 credits
**Uses:** `/v1/youtube/videos/{id}/file` · `/v1/speech/transcripts` · `/v1/ai/text` · `/v1/ai/voices/clone` · `/v1/ai/voice` · `/v1/studio/uploads` · `/v1/studio/convert` · `/v1/studio/edit`

Base URL: `https://apihub.co.il` · Auth: `Authorization: Bearer <API key>` · Docs: `/docs`
Send the same `X-Tag: <job name>` header on every call of one video; `GET /v1/usage?tag=<job name>` then
returns exactly what it cost. Times in request bodies are **seconds on the edited (output) timeline**.
Unknown fields are rejected with the name of the right field — read the error instead of guessing.
**Files are kept 24 hours** (renders, uploads, generated clips/images/music) — download the finished video.

**Models.** AssemblyAI transcribes the talk with its speakers; Gemini 3.1 Pro (`quality: "best"`) picks the story, writes the
Hebrew, reviews it and listens to every take; your ElevenLabs clone reads it on eleven_v4 with the Hebrew director inside
the call; Gemini 3.5 Flash watches each passage on YouTube for the speaker's place; the cut and the mix are one render. The
transcript and the story are priced by the talk's length, everything else by the reel's.

---

## 1. The talk, and the licence it is used under

**Rights first.** The footage is someone else's talk: use only a video the customer owns, one published under **Creative
Commons (CC BY)** by its owner, or one with written permission for a translated version — ask which, never choose for
them. A "Creative Commons" label on a re-upload by a compilation channel does not count: only the owner can license it
(the World Economic Forum and UC Berkeley, for example, publish their talks under CC BY). The voice is the customer's
own clone — never a clone of the speaker.

```jsonc
GET  /v1/youtube/videos/{id or link}                       // license: "youtube" (standard) or "creative-commons"
POST /v1/youtube/videos/{id}/file { "kind": "video", "license": "creative-commons",
  "credit": "Jack Ma at Davos 2015 — World Economic Forum, CC BY 3.0" }      // ≈ 10 credits → output.url (24 hours)
// "The media host temporarily blocked this request" is transient: send it again with a NEW Idempotency-Key
```

No YouTube file on the account (`403 youtube_files_not_enabled`)? Download it from the owner's page and upload it:
`POST /v1/studio/uploads { …, "license": "creative-commons", "source_url": "<the link>", "credit": "<the credit line>" }`.

## 2. Who said what

```jsonc
POST /v1/speech/transcripts { "audio_url": "<the talk>", "language_code": "en", "speaker_labels": true,
  "keyterms_prompt": [ "Jack Ma", "Alibaba" ] }            // ≈ 1.75 credits a minute of the talk, speakers included
GET  /v1/speech/transcripts/{id}/sentences                  // [{ text, start, end (ms), speaker: "A" | "B" }]
```

`speaker_labels` matters: an interview is two voices, and only the speaker's own sentences may be voiced. The speaker
is the letter with the most words.



## 3. Gemini picks the story

```jsonc
POST /v1/ai/text { "quality": "best", "json": true,
  "system": "You edit a vertical motivational reel about ONE speaker: the main speaker of the numbered transcript (the speaker letter with the most words). It will be voiced in Hebrew in the narrator's own cloned voice, over the speaker's own footage.\nPick 7-10 passages of the main speaker's own sentences that tell ONE story with a strong arc — where he started, the failures and rejections, the turn, what he learned, a closing line that gives goosebumps — about 100-130 seconds of his speech in total.\nRules: only the main speaker's sentences (never the interviewer); each passage = consecutive sentences [from..to] that make sense alone, 5-30 seconds; passages in the order they were said (the picture is cut in time order); skip filler, jokes that need context, politics, religion, anything said about a third person that could be unfair.\nAlso: \"peak\" = the index (0-based) of the passage with the line the music should explode on, and \"hook\" = who he is + the one fact that makes people stay, for a 10-second opening the narrator says (no invented facts — only what the talk or his public title says).\nReturn JSON only: {\"speaker\":\"B\",\"passages\":[{\"from\":12,\"to\":14,\"role\":\"failure\",\"why\":\"...\"}],\"peak\":6,\"hook\":{\"who\":\"...\",\"fact\":\"...\"}}",
  "prompt": "<every sentence on its own line: i [m:ss] speaker: text>" }     // ≈ 1 credit a minute of the talk
// → { speaker, passages: [ { from, to, role } ], peak, hook: { who, fact } }
```

The passages come back **in the order they were said** — the render cuts the talk with `keep`, which runs forward in
time. The example: 8 passages, 105 seconds of his speech — the exam failed three times, 30 jobs, the police, KFC,
Harvard ten times, three years of zero revenue, 18 people in his apartment, "we never give up", "the one who checks
himself has hope".

## 4. The Hebrew, written for the ear — then read twice

```jsonc
POST /v1/ai/text { "quality": "best", "json": true,
  "system": "You write the Hebrew voice-over of a motivational reel: the narrator speaks the speaker's words in the FIRST PERSON, as if he were the speaker, in natural spoken Israeli Hebrew — written for the ear, not for the page. Speaker's gender: <male|female> (use the matching first-person forms).\nFor every passage write lines (one subtitle each, 2-7 words, a sentence may span lines) with two versions:\n- \"show\": the subtitle as written (digits allowed, names as Israelis write them); mark {key words} SPARINGLY — one {mark} on about every third line, on the word that carries the emotion (never on every line);\n- \"say\": what the voice reads — numbers in words with the right gender, foreign names spelled for a Hebrew voice (Jack = ג׳ק with the Hebrew geresh ׳, KFC = קיי אף סי), no {} marks.\nFaithful to the meaning, short and punchy, no translated syntax, no word that an Israeli would not say out loud; the interviewer's words never appear. Keep each passage's Hebrew no longer than about 1.15× the English time.\nAlso the opening \"hook\" lines (narrator speaking about the speaker, 3rd person): start with \"סרטון מוטיבציה מטורף.\" then who he is + the fact you were given, end with \"תקשיבו עד הסוף.\" — 4-5 lines, at most 24 words in all; state the fact exactly as given — add no adjective, number or detail that is not in it.\nReturn JSON only: {\"hook\":[{\"show\":\"...\",\"say\":\"...\"}],\"passages\":[{\"i\":0,\"lines\":[{\"show\":\"...\",\"say\":\"...\"}]}]}",
  "prompt": "Hook facts: <who> — <fact>\n\nPassages (English, as said):\n0. (7.5 s) <the passage, the interviewer's lines marked [interviewer]>…" }   // ≈ 45
POST /v1/ai/text { "quality": "best", "json": true,
  "system": "You are a native Israeli subtitle editor. For each passage you get the English the speaker said and the Hebrew lines. Check: meaning faithful (small clarifications are fine), natural spoken Israeli Hebrew (not translated syntax), the speaker's gender in first person, numbers and names. Return JSON only: {\"fixes\":[{\"i\":0,\"line\":2,\"was\":\"the line as it is now\",\"show\":\"the CORRECTED subtitle (digits allowed, keep {marks})\",\"say\":\"the CORRECTED line for the voice (numbers in words, names spelled for a Hebrew voice)\",\"why\":\"...\"}]} — only real problems; \"i\" is the passage index or \"hook\"; \"show\" and \"say\" are both the new text, never the old one.",
  "prompt": "hook (narrator, 3rd person): <lines>\n\n0. EN: <passage>\nHE: [0] <line> / [1] <line>…" }   // ≈ 40 — apply each fix by i and line
```

**Then read it yourself, once** — what neither model caught in the example:
- **A number next to the right noun.** "in my apartment 18, 15 years ago" came back as "15 או 18 שנה": the 18 are the
  people (אמרתי ל-18 האנשים שלי, לפני 15 שנה).
- **The interviewer's words are gone** — "tell them the story" was his question, not the speaker's line.
- **Spoken, not written:** "היינו בטירוף להמשיך" → "היינו כל כך נלהבים להמשיך".
- **A woman speaker** gets feminine first-person forms and a woman's voice (step 5) — never the narrator's male clone saying "בעלי".

## 5. The voice — your clone, two takes a passage

Your voice is cloned once (`/skills/full-natural-voice.md` step 1, ≈ 282 credits, kept for the account). Every
passage is one call, with its neighbours so the voice flows across them, two takes at once:

```jsonc
POST /v1/ai/voice { "text": "<the passage's say lines joined>", "voice_id": "<your voice_id>", "language_code": "he",
  "stability": 0.3, "timestamps": true,
  "mood": "powerful motivational voice-over: intense, emotional, deliberate, dramatic pauses, building conviction; natural Israeli Hebrew from the heart, no shouting",
  "previous_text": "<the passage before>", "next_text": "<the passage after>" }     // ×2 at once · ≈ 1 credit a second of speech a take
// the hook: the same call with "mood": "the opening hook of a viral motivational reel: energetic, punchy, confident, natural spoken Israeli Hebrew, not an ad"
// → output.url, output.words [{ text, start, end }] (seconds), output.duration_seconds, output.directed.tts
```

`mood` is at most 200 characters. The director inside the call adds the niqqud and the delivery tags (the example:
[storytelling, emotional] for the exam, [intense, deliberate] for "we never give up"); write none yourself.

## 6. Listen before you choose

```jsonc
POST /v1/ai/text { "quality": "best", "json": true, "temperature": 0.2, "max_tokens": 6000,
  "system": "You are a demanding native Israeli voice director. You hear several takes of the same Hebrew text, in order (take 1, take 2, …). For EACH take: list every word that is heard differently from the text (the word as written and what was heard, in Latin letters) — foreign names especially (Jack = \"Jak\", never \"Gek\"), score naturalness 1-10 (sounds like a real Israeli person, not a robot or a radio announcer) and delivery 1-10 (fits the intended mood). Then rank the takes, best first. Return JSON only: { \"takes\": [ { \"n\": 1, \"wrong_words\": [ { \"word\": \"...\", \"heard\": \"...\" } ], \"naturalness\": 8, \"delivery\": 7, \"note\": \"...\" } ], \"ranking\": [2, 1] }",
  "prompt": "The text: <the passage>. The intended delivery: a powerful, emotional motivational voice-over.",
  "media": [ { "url": "<take 1 mp3>", "type": "audio" }, { "url": "<take 2 mp3>", "type": "audio" } ] }   // ≈ 15 credits a passage
```

- **The best-ranked take with no wrong word.** In the example the hook's take 1 said "Gek Ma" — the check caught it and
  take 2 ("Jak Ma") was used.
- **A word wrong in both takes is the text:** put niqqud on that one word in `output.directed.tts` and read it again
  with `"prepare": false`, two takes (the example: "להרווארד" heard as "le-Howard" → לְהַרְוָארְד, "le-HAR-vard").
- **A natural form flagged as wrong is not wrong:** "ve'ani" for ואני is how Israelis say it.

## 7. Where the speaker is

Gemini watches each passage on YouTube where it is — nothing is uploaded; **one YouTube link per call**, so one call a
passage, all at once — plus the minute and a half before the story for the opening's shots:

```jsonc
POST /v1/ai/text { "quality": "balanced", "json": true, "temperature": 0.1,
  "system": "You watch one clip of a talk. The main speaker: <who>. Return:\n- \"x\": the horizontal centre of his face when the camera shows him close, 0 = left edge … 1 = right edge;\n- \"away\": every stretch (seconds from the clip's start) where the picture does NOT show him close (a wide shot of the stage, the interviewer, the audience, a slide), as [from, to];\n- (the clip before the story only) \"moments\": 5 instants (seconds from the clip's start), at least 8 s apart, where he is in a close shot with a strong expression or gesture, each with its \"x\".\nReturn JSON only: {\"x\":0.62,\"away\":[[12.5,16]],\"moments\":[{\"t\":3.2,\"x\":0.6}]}",
  "prompt": "The clip.", "media": [ { "url": "<the YouTube link>", "type": "video", "start": <passage start s>, "end": <passage end + 25>, "fps": 1 } ] }   // ≈ 5 credits a clip
```

Asking about the uploaded file instead timed out (the whole talk is sent to the model for every clip).

## 8. The music

**A licensed track** — Pixabay's free tracks are allowed on social media, but most of the popular "epic motivational"
ones say **"Content ID Registered"** on their page: Instagram and YouTube may claim or mute the reel. Take one without
it, upload it with its licence, and cut it twice:

```jsonc
POST /v1/studio/uploads { "filename": "<track>.mp3", "content_type": "audio/mpeg", "size_bytes": <bytes>, "license": "licensed",
  "source_url": "<the track's page>", "credit": "<title — artist · Pixabay Content License>" }
POST /v1/studio/convert { "video_url": "<track>", "trim": { "start": <the drop>, "end": <the drop + the opening + 0.8> }, "output": { "format": "mp3" } }   // the opening's punch
POST /v1/studio/convert { "video_url": "<track>", "trim": { "start": <m0>, "end": <its end> }, "output": { "format": "mp3" } }               // the bed
```

`m0` puts the track's drop on the peak passage — **unless the track would then end before the reel**: it must cover
everything after the opening, so `m0 = min(drop − (peak − opening), length − (reel − opening))`. In the example the drop
landed on "we never give up". Or make the score: `POST /v1/ai/music` with `sections` on the story's turns (≈ 0.77 a second).

## 9. The timeline — the picture follows the voice (no call)

Each passage lasts **0.4 s + its chosen take's speech + 0.35 s** (the last one 0.9 s); the speaker's own footage runs on
under the Hebrew from where he said it, so a long Hebrew line simply shows more of him. Walk the passages in order:

- **`keep`** — from the passage's start (or just after the previous span, whichever is later) for that length, jumping
  over every `away` stretch. The opening: one short span per beat of the hook line, each at one of the `moments`.
- **`zoom`** — every span `{ "from": 3, "to": 3, "x": <its x>, "y": 0.5 }` with `output.fit: "blur"`: the whole frame over a
  blurred copy, pushed in on his face — full screen with a hair of blur at the edges. (`fit: "crop"` always crops the centre;
  a zoom cannot move it.) The last zoom runs on through `hold_end`, or the held frame drops back to the blurred layout.
- **`voiceover`** — every chosen take at its span's start + 0.4 − its first word's start (never below 0).
- **`captions.captions`** — each subtitle from its first to its last word (the say/show lines laid over the take's
  words by their letters). **With `keep` they are on the SOURCE clock** — they are re-timed through the cuts like a
  transcript — so turn every reel second into the source second it shows (`span.start + t − span's reel start`), and
  give every shown word its share of the line. Sent on the reel's clock they all fall outside the cut and vanish.
- **`panels`** — a white flash (0.12 s) on every cut of the opening and as the story starts.

## 10. One render

```jsonc
POST /v1/studio/edit { "video_url": "<the talk>", "keep": [ … ], "zoom": [ … ], "panels": [ … ],
  "audio": { "mute": true, "normalize": false }, "voiceover": [ { "url": "<take>", "start": 8.71, "volume": 1 }, … ],
  "sounds": [ { "url": "<the opening's punch>", "start": 0, "volume": 0.27, "normalize": false } ],
  "music": { "url": "<the bed>", "start_ms": <opening − 500>, "volume": 0.11, "normalize": false, "duck": false, "fade_in_ms": 500, "fade_out_ms": 1800 },
  "captions": { "style": { "preset": "keyword-pop", "keywords": [ <the {marked} words> ], "keyword_color": "#D0F808",
    "keyword_scale": 1.22, "position": "bottom", "margin": 24, "animation": "pop", "max_lines": 2 }, "captions": [ … ] },
  "effects": [ { "id": "lower-third", "params": { "name": "ג׳ק מא", "title": "מייסד עליבאבא", "y": 14 }, "start": <the name in the hook>, "duration": 2.6 } ],
  "texts": [ { "id": "credit", "text": "נערך עם *apihub.co.il*\n<speaker> · <talk> · <owner> · CC BY 3.0", "preset": "pill", "effect": "box",
    "style": { "y": 92.5, "size": 3.4, "weight": 800, "color": "#FFFFFF", "background": "#0B0B14E6", "accent_color": "#D0F808" },
    "start": 0, "duration": <the reel + hold_end> } ],
  "color": { "preset": "cinematic" }, "hold_end": 2,
  "output": { "aspect_ratio": "9:16", "resolution": "1080", "fit": "blur", "quality": "high" } }   // ≈ 1.26 credits a second
```

**The captions** are the `keyword-pop` look — white words, the key words bigger and in colour; `"style": "keyword-pop"`
alone gives them in yellow, the overrides above make them lime, a little bigger, and lift the line clear of the credit.

**The level, measured.** A mastered track is loud (the example's: −9.4 LUFS) and the takes are ≈ −12.6: with
`normalize: false`, the bed at 0.11 sits ≈ 18 dB under the voice and the opening's punch at 0.27 ≈ 10 dB under the hook
(`normalize: true` at 0.2 left the music 29 dB under — gone). **The pill needs `"color": "#FFFFFF"`** on its dark
background, or the credit is dark on dark. **The CC BY credit stays on screen the whole reel** and goes into the post.

## What the example cost

The example: 119 seconds from a 45-minute talk (Jack Ma at Davos 2015, World Economic Forum, CC BY 3.0), in
the owner's own clone, made by this recipe on dev — **683 credits**, the clone made before. The transcript and the
story pick are priced by the TALK's length; everything else by the reel's.

| Step | Credits |
| --- | ---: |
| The YouTube file | 10 |
| The transcript with speakers (44 min) | 78 |
| The story (Gemini 3.1 Pro over 689 sentences) | 44 |
| The Hebrew script | 45 |
| The native editor's review | 40 |
| The voice: 9 parts × 2 takes + one word re-read | 110 |
| The check (Gemini 3.1 Pro listens to every take) | 137 |
| Where the speaker is (9 clips) | 46 |
| The music (a licensed track, two cuts) | 23 |
| The render (119 s, 1080p) | 150 |
| **Total** | **683** |

The clone itself is ≈ 282 credits, once per voice.

## Tune it

The story length (`STORY_BRIEF`: "about 100-130 seconds") · the hook's first words · `mood` per passage · `stability` ·
the keywords' colour · the music's level · a woman speaker: a woman's voice (Shira `1WOvbtTEb49xcgFUMDu9`, a ready Israeli
voice) and feminine forms.

Send `x-wait-ms: 110000` to wait for the render in the same call; if the response is still
`processing`, poll `GET /v1/executions/{id}` until `status` is `completed` and read `output.url`.

## Check the bill

`GET /v1/usage?tag=<job name>` — per call, per operation and the total, in credits. Quote that to the
customer, not the estimate above.

## Rules that keep captions readable on every platform

- **Safe zone.** Keep text inside the middle 80% of the frame: `side_margin` ≥ 6 handles the sides; `margin`
  ≥ 12 keeps the bottom clear of the platform UI (username, buttons, progress bar).
- **A line never leaves the frame** — a line too wide for the side margins is set smaller automatically. Do
  not shrink the size yourself, wrap instead (`max_chars_per_line`).
- **Hebrew has no capitals** — keep `uppercase: false`; it only breaks Latin words mixed into a sentence.
- **Fonts.** `GET /v1/studio/fonts` lists the bundled families and which scripts they draw. A font that
  cannot draw the caption's language is swapped and reported in `warnings`.
- The customer's transcript wins: to fix a word, `GET /v1/speech/transcripts/{id}/captions`, edit the text,
  and send the list back as `captions.captions` — timing is kept when the word count is unchanged.
