API REFERENCE · DECISIONS
Visual decisions
Who on screen is saying it, which text in the frame to translate, and whether the expressions follow the new line: the choices, with the frame they belong to.
01.What the model decides on screen
Every visual decision is planned to land in the decision record (in the works), each with the moment in the frame it belongs to. Your creative directors read the model's pick and change any of it.
- Who is actually saying it: which face a line is heard from, who narrates, who speaks from off screen.
- The lips follow the new words.
- The expressions and gestures follow the new line when the emphasis or the culture calls for it.
- The text in the frame: a phone screen, a book cover, a street sign, a store front, written in the terms you already chose.
02.The kinds
| KIND | WHAT IS DECIDED | THE OPTIONS |
|---|---|---|
speaker | Who on screen is saying the line. | The candidate faces, the narrator, off screen. |
on_screen_text | Each text item in the frame. | Translate in your terms, or keep as shot. |
expression | Whether expressions and gestures follow the new line. | Follow, or hold as shot. |
speaker: a line can be heard from the wrong face when three people share a shot. The options are the candidate faces; pick face 2 of 3 and the lips move there.
on_screen_text: a phone screen reads 내일 봐at 58 s. The model translates it as "See you tomorrow" in the terms you already chose, or you keep it as shot; a street sign and a store front come back the same way.
expression: an eyebrow raise can read differently in the target culture. Hold it as shot and the face keeps the original performance.
03.In the record
/v1/dubs/{dub_id}/decisions?type=visualThe decisions resource (in the works) filters to the visual kinds with type=visual. A speaker decision lists the candidate faces as its options.
{
"dub_id": "dub_31xk9m",
"lang": "en",
"decisions": [
{
"id": "dec_7h2k0d",
"type": "visual",
"kind": "speaker",
"start": 33.10,
"end": 35.40,
"speaker": "spk_1",
"source": "어디 갔다 왔어?",
"options": [
{ "id": "spk_1", "text": "face 1 of 3, center of frame", "reasoning": "Faces the camera as the line starts." },
{ "id": "spk_2", "text": "face 2 of 3, left of frame", "reasoning": "Turned away; the line could be theirs." },
{ "id": "spk_3", "text": "face 3 of 3, right of frame", "reasoning": "Silent through the shot." }
],
"chosen": "spk_1",
"chosen_by": "model",
"status": "open",
"memory": null
},
{
"id": "dec_7h2k0c",
"type": "visual",
"kind": "on_screen_text",
"start": 58.00,
"end": 61.50,
"speaker": null,
"source": "phone screen: 내일 봐",
"options": [
{ "id": "opt_1", "text": "See you tomorrow", "reasoning": "The message is read on camera; the terms you already chose apply." },
{ "id": "opt_2", "text": "keep as shot", "reasoning": "Leave the screen in Korean." }
],
"chosen": "opt_1",
"chosen_by": "model",
"status": "open",
"memory": null
}
],
"has_more": false
}04.Override
/v1/dubs/{dub_id}/decisions/{decision_id}The override (in the works) takes exactly one change per call. Add remember ("creator" | "job") to carry the choice to the next episode.
curl -X PATCH https://api.thefamiliarlab.com/v1/dubs/dub_31xk9m/decisions/dec_7h2k0d \
-H "Authorization: Bearer $FAMILIAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "speaker": "spk_2" }'{ "translate": false } // on_screen_text: keep as shot
{ "text": "See you tmrw", "remember": "creator" } // on_screen_text: your own wording
{ "hold": true } // expression: keep as shot{
"id": "dec_7h2k0d",
"type": "visual",
"kind": "speaker",
"chosen": "spk_2",
"chosen_by": "you",
"status": "settled",
"memory": null
}| FIELD | KIND | EFFECT |
|---|---|---|
speaker | speaker | A spk_… id from the options. |
translate: false | on_screen_text | The item stays as shot. |
text | on_screen_text | Your own wording for the item. |
hold: true | expression | Expressions and gestures stay as shot. |
PATCH is valid at in_review and complete; on a delivered dub, POST /render again and only the touched languages render. While the dub renders it returns 409 decision_locked; an unknown option returns 422 option_not_found.
05.Settings
Three request fields on POST /v1/dubs (in the works) set how each visual kind is handled. In multipart they are written dotted, as metadata.title is.
| FIELD | VALUES | DEFAULT |
|---|---|---|
decisions.visual.speaker | auto | ask | auto |
decisions.visual.on_screen_text | auto | translate | keep | ask | auto |
decisions.visual.expression | match | hold | ask | match |
speaker: ask: every close call on who is speaking comes back with the candidate faces.on_screen_text: translate: every readable item, in the terms you already chose;keepleaves them as shot.expression: match: the expressions and gestures follow the new line's emphasis or the culture;holdkeeps them as shot.
Any ask value requires review=manual, else 422 decision_setting_requires_review. The dub waits at in_reviewuntil every open decision is settled, or you render and the model's choice stands on the rest.
06.On the review screen
The review screen (in the works) shows each visual decision as a card with the frame and the item in it, the options with the reasoning, and the model's pick lit. One tap picks another face, types the on-screen text, holds the expression, or remembers the choice for this creator; the screen and the API share one record.
07.Access
The API is enterprise-only: private access under a Studio contract, with volume pricing, raised limits, ProRes masters on request, and a named point of contact. Book a call and your key is issued with the contract.