Update to Frameo.AI
Snapshot Oct 24, 2026 · 13:00 UTC · version 1.2.5
Collection source: downloaded plugin package.
Instructions updated for talking-presenter
Full description — Now says: One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length. Use for...
Observed in instructions or declared skills. Runtime behavior has not been tested.
Up to 10 plugins free · no card required.
All fields and original values.
Full description
Oct 8, 2026 · 18:02 UTC
One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length.
Oct 24, 2026 · 13:00 UTC
One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length. Use for explainers, founder messages, course intros and announcements, or to put the user on scree...
Skill instructions
Oct 8, 2026 · 18:02 UTC
length." Needs: a script; a photo of the presenter or a description; optionally a brand colour or logo Credits: about 1,000–2,100 for a 30–60 second piece (lipsync is the main cost: ~20 credits per second of clip) Time: 10–20 minutes Not...
Oct 24, 2026 · 13:00 UTC
length. Use for explainers, founder messages, course intros and announcements, or to put the user on screen over footage they already have." To put the user, from their photo, on screen in a corner of footage they already have, follow `g...
Supporting files
Oct 8, 2026 · 18:02 UTC
[{"relative_path":"agents/openai.yaml","size_in_bytes":372},{"relative_path":"assets/icon.svg","size_in_bytes":405}]
Oct 24, 2026 · 13:00 UTC
[{"relative_path":"agents/openai.yaml","size_in_bytes":375},{"relative_path":"assets/icon.svg","size_in_bytes":405},{"relative_path":"references/overlay.md","size_in_bytes":5045}]
Compare saved observations
Download comparison JSONSKILL.md text changes
− removed · + added
--- before +++ after @@ -1,26 +1,28 @@ --- name: talking-presenter -description: "One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length." +description: "One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length. Use for explainers, founder messages, course intros and announcements, or to put the user on screen over footage they already have." --- -Needs: a script; a photo of the presenter or a description; optionally a brand colour or logo -Credits: about 1,000–2,100 for a 30–60 second piece (lipsync is the main cost: ~20 credits per second of clip) -Time: 10–20 minutes - ## When Use for one person speaking to camera: an explainer, a founder message, a course intro, an announcement, a customer-support answer. Any language the voice catalog covers. -Not for: several characters in scenes (`script-to-video`), or narration over other footage -(`faceless-story-video`). +To put the user, from their photo, on screen in a corner of footage they already have, follow +`get_skill_file(skill_id="talking-presenter", path="references/overlay.md")` (picture-in-picture). + +Not for: several characters in scenes (`script-to-video`), or a narrator heard over generated +scenes with no one on screen (`faceless-story-video`). ## Ask first -1. **Who** — a photo (`show_upload` for files on the user's device, `import_media_url` for a web link; images attached to the chat do not reach Frameo, and `create_upload_url` is for clients that send the file themselves) or a description to design from. +1. **Who** — a photo (`show_upload` for files on the user's device, `import_media_url` for a web link; images attached to the chat reach Frameo only through `import_attachments`, in apps that pass them such as ChatGPT, and `create_upload_url` is for clients that send the file themselves) or a description to design from. 2. **Voice** — the user's preference in words (warm, brisk, older, Hindi, British…); pick 3 with `search_voices` and show their names. 3. **Frame** — 9:16 or 16:9, and whether a title card opens the piece. +4. **Script** — the user's own, used as written. When they ask for one to be written, follow the + word budget, hook, lines-to-cut and delivery sections of + `get_skill_file(skill_id="ugc-video", path="references/script-craft.md")`. Say the rough cost (the script's length decides it) in the same turn as the questions; the user's yes comes with the plan (Steps, **The plan first.**). @@ -28,7 +30,8 @@ **Before any paid step.** The project: `list_projects` (or `create_project`) gives the `project_id` and, when the project has several modules, the `module_id`; every call below that takes a project — -`estimate_cost` included — gets that same pair; without it those tools answer `project_needed`. The +`estimate_cost` included — gets that same pair; without the project those tools answer `project_needed`, and without the +module of a project that has several, `module_needed`, which lists its modules. The quote: one `estimate_cost(items=[…])` prices a stage in one call, with the same project, model, size and number of `image_urls` or `reference_image_urls` (`reference_count`) as each generate call, and returns a `quote_id` per item plus the total. Each generate call then passes its own item's `quote_id` and `confirmed_by_user=true`. A quote is single-use and lasts @@ -36,7 +39,7 @@ comes to more than the user approved is asked about again first. Generate calls return `generation_ids`; `wait_task` returns the links, and `show_generations` shows each stage's running and finished work in one card where the chat app displays Frameo cards: all the stage's ids at -once, before its first `wait_task`, and the finished result with `final: true`. +once, before its first `wait_task`; the card updates itself as the work finishes, so the same ids are not shown again. **The plan first.** Before the first paid call, the plan goes to the user in the chat as plain text: what will be made, in order, one line per generation (for a script, the shot list; for a @@ -46,7 +49,7 @@ generated until the user says yes. The user can drop or change lines; a changed line is priced again. -**Canvas rows.** Pass `shot_number` on every `generate_image` and `generate_video` of a shot (1, 2, 3… in story order; the same number for a retake and for that shot's video), so each shot gets its own row on the Frameo canvas. Cast, prop and location references take `placement_kind` (`character`, `prop` or `location`) and the subject's name as `placement_group` instead: they sit on their own board, and the shots built from them do not pile into their row. +**Shot order.** Pass `shot_number` on every `generate_image` and `generate_video` of a shot (1, 2, 3… in story order; the same number for a retake and for that shot's video), so the project keeps each shot apart, in order. Cast, prop and location references take `placement_kind` (`character`, `prop` or `location`) and the subject's name as `placement_group` instead: they are kept with the project's references, apart from the shots built from them. **1. The presenter still (~18 credits).** `generate_image`: a mid-shot of the presenter facing camera, neutral background unless the user wants one, `image_urls=[photo]` when there is a @@ -94,9 +97,10 @@ ## Done -The finished clip, the presenter still, and every clip in the Frameo project (chat and -canvas) for edits in the app. +The finished clip, the presenter still, and every clip in the Frameo project, ready for +edits in the app. ## Files -None. +- `references/overlay.md` — the presenter in a corner of the user's own footage: the green still, + the clips per line, the composite and its check.
Full technical diff · 3 changed fields
changed /description
"One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length."
"One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length. Use for explainers, founder messages, course intros and announcements, or to put the user on screen over footage they already have."
changed /included_files
[
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 372
},
{
"relative_path": "assets/icon.svg",
"size_in_bytes": 405
}
][
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 375
},
{
"relative_path": "assets/icon.svg",
"size_in_bytes": 405
},
{
"relative_path": "references/overlay.md",
"size_in_bytes": 5045
}
]changed /skill_md_contents
"---\nname: talking-presenter\ndescription: \"One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length.\"\n---\n\nNeeds: a script; a photo of the presenter or a description; optionally a brand colour or logo\nCredits: about 1,000–2,100 for a 30–60 second piece (lipsync is the main cost: ~20 credits per second of clip)\nTime: 10–20 minutes\n\n## When\n\nUse for one person speaking to camera: an explainer, a founder message, a course intro, an\nannouncement, a customer-support answer. Any language the voice catalog covers.\n\nNot for: several characters in scenes (`script-to-video`), or narration over other footage\n(`faceless-story-video`).\n\n## Ask first\n\n1. **Who** — a photo (`show_upload` for files on the user's device, `import_media_url` for a web link; images attached to the chat do not reach Frameo, and `create_upload_url` is for clients that send the file themselves) or a description to design from.\n2. **Voice** — the user's preference in words (warm, brisk, older, Hindi, British…); pick 3\n with `search_voices` and show their names.\n3. **Frame** — 9:16 or 16:9, and whether a title card opens the piece.\n\nSay the rough cost (the script's length decides it) in the same turn as the questions; the user's yes comes with the plan (Steps, **The plan first.**).\n\n## Steps\n\n**Before any paid step.** The project: `list_projects` (or `create_project`) gives the `project_id`\nand, when the project has several modules, the `module_id`; every call below that takes a project —\n`estimate_cost` included — gets that same pair; without it those tools answer `project_needed`. The\nquote: one `estimate_cost(items=[…])` prices a stage in one call, with the same project, model,\nsize and number of `image_urls` or `reference_image_urls` (`reference_count`) as each generate call, and returns a `quote_id` per item plus the total. Each generate call\nthen passes its own item's `quote_id` and `confirmed_by_user=true`. A quote is single-use and lasts\n15 minutes, so a long plan is priced stage by stage, right before each stage runs; a stage that\ncomes to more than the user approved is asked about again first. Generate calls return\n`generation_ids`; `wait_task` returns the links, and `show_generations` shows each stage's running\nand finished work in one card where the chat app displays Frameo cards: all the stage's ids at\nonce, before its first `wait_task`, and the finished result with `final: true`.\n\n**The plan first.** Before the first paid call, the plan goes to the user in the chat as plain\ntext: what will be made, in order, one line per generation (for a script, the shot list; for a\nset, each shot), with each line's credits and the total. The credits come from\n`estimate_cost(items=[…])`, up to 10 items a call, so a long plan takes several calls; those\nquotes may expire unused, since each stage is quoted again right before it runs. Nothing is\ngenerated until the user says yes. The user can drop or change lines; a changed line is priced\nagain.\n\n**Canvas rows.** Pass `shot_number` on every `generate_image` and `generate_video` of a shot (1, 2, 3… in story order; the same number for a retake and for that shot's video), so each shot gets its own row on the Frameo canvas. Cast, prop and location references take `placement_kind` (`character`, `prop` or `location`) and the subject's name as `placement_group` instead: they sit on their own board, and the shots built from them do not pile into their row.\n\n**1. The presenter still (~18 credits).** `generate_image`: a mid-shot of the presenter facing\ncamera, neutral background unless the user wants one, `image_urls=[photo]` when there is a\nphoto. `wait_task`, show it; adjust once if asked.\n\n**2. The voice (~1 credit per 50 characters).** `generate_speech(text=script, voice_id)` in one\ncall when the whole script fits one clip (15 s, the lipsync's cap, or the video model's max from\n`list_models(kind=\"video\")` when that is lower); otherwise split at sentence breaks — and at clause breaks (commas, dashes) when one\nsentence alone is still too long — so each file fits one clip. `wait_task` gives the link; play it back to the user before spending on video. The result's\n`duration_seconds`, the file's measured spoken length, is its raw estimate, kept as is for the\nlipsync; a result without one is estimated at 2.8 words per second (2.5 for Hindi) plus one\nsecond of headroom, and that estimate is approximate. When the user picks a presenter\n`list_characters` already has in the project, its first image is the still and its `voice_id` the\nvoice. A new\npresenter is saved with `save_character` under a name not already in the cast (the same name\nreplaces that character's voice), with `image_urls=[presenter still]` and the `voice_id`, so later\nvideos in this project reuse the same face and voice.\n\n**3. The clip (~65 credits per 5 s + ~20 per second of lipsync).** For each speech file:\n`generate_video` from the still (`first_frame_url`) with a prompt like \"presenter speaking\nto camera, subtle natural head movement, steady framing\", `duration` = that file's raw\nestimate rounded up to whole seconds, kept inside the video model's range\n(`list_models(kind=\"video\")`; 4–30 s on the default) and at most 15 s — step 2 sized the files to\nthat, and a file that measures a little longer still goes in whole as `audio_duration`,\n`wait_task`, then `generate_lipsync(video_url, audio_url, duration, audio_duration=the raw\nestimate, aspect_ratio, resolution)` — the raw one, so a clamped clip is still extended to\nthe speech; the size the clip was made at; and `duration` never above 15 s, the lipsync's\nown cap, whatever the video model allows — and\n`wait_task`. Test the first clip\nbefore the rest.\n\n**4. Title card (free).** If wanted: `render_motion_graphics` with `template=\"title_card\"`, the title\n(and a `subtitle`), the piece's `size` and a `duration` of 2 to 3 s; `wait_task` returns the card's clip,\njoined in front in the cut. It counts against the 30 runs per clock hour.\n\n**5. Cut (free).** With a title card, one pass of its own first: the card comes at full HD in its\n`size`, so it is scaled to the clips' size (`scale`, then `setsar=1`) and given a bounded silent\ntrack (`-f lavfi -t <card seconds> -i anullsrc=r=<the clips' sample rate>:cl=stereo`); an\nunbounded `anullsrc` never ends and stalls the join. Then `run_ffmpeg` takes at most 10 inputs and 4 outputs:\nconcatenate the lipsynced clips in\norder, in groups of at most 10 — the card counts as an input, so nine clips per group when\none is joined in front — and repeat until the final call fits (`wait_task` after each pass;\nits outputs are the next pass's inputs). Output `final.mp4`. `wait_task`,\nreturn the link and `open_in_frameo`.\n\n## Done\n\nThe finished clip, the presenter still, and every clip in the Frameo project (chat and\ncanvas) for edits in the app.\n\n## Files\n\nNone.\n"
"---\nname: talking-presenter\ndescription: \"One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length. Use for explainers, founder messages, course intros and announcements, or to put the user on screen over footage they already have.\"\n---\n\n## When\n\nUse for one person speaking to camera: an explainer, a founder message, a course intro, an\nannouncement, a customer-support answer. Any language the voice catalog covers.\n\nTo put the user, from their photo, on screen in a corner of footage they already have, follow\n`get_skill_file(skill_id=\"talking-presenter\", path=\"references/overlay.md\")` (picture-in-picture).\n\nNot for: several characters in scenes (`script-to-video`), or a narrator heard over generated\nscenes with no one on screen (`faceless-story-video`).\n\n## Ask first\n\n1. **Who** — a photo (`show_upload` for files on the user's device, `import_media_url` for a web link; images attached to the chat reach Frameo only through `import_attachments`, in apps that pass them such as ChatGPT, and `create_upload_url` is for clients that send the file themselves) or a description to design from.\n2. **Voice** — the user's preference in words (warm, brisk, older, Hindi, British…); pick 3\n with `search_voices` and show their names.\n3. **Frame** — 9:16 or 16:9, and whether a title card opens the piece.\n4. **Script** — the user's own, used as written. When they ask for one to be written, follow the\n word budget, hook, lines-to-cut and delivery sections of\n `get_skill_file(skill_id=\"ugc-video\", path=\"references/script-craft.md\")`.\n\nSay the rough cost (the script's length decides it) in the same turn as the questions; the user's yes comes with the plan (Steps, **The plan first.**).\n\n## Steps\n\n**Before any paid step.** The project: `list_projects` (or `create_project`) gives the `project_id`\nand, when the project has several modules, the `module_id`; every call below that takes a project —\n`estimate_cost` included — gets that same pair; without the project those tools answer `project_needed`, and without the\nmodule of a project that has several, `module_needed`, which lists its modules. The\nquote: one `estimate_cost(items=[…])` prices a stage in one call, with the same project, model,\nsize and number of `image_urls` or `reference_image_urls` (`reference_count`) as each generate call, and returns a `quote_id` per item plus the total. Each generate call\nthen passes its own item's `quote_id` and `confirmed_by_user=true`. A quote is single-use and lasts\n15 minutes, so a long plan is priced stage by stage, right before each stage runs; a stage that\ncomes to more than the user approved is asked about again first. Generate calls return\n`generation_ids`; `wait_task` returns the links, and `show_generations` shows each stage's running\nand finished work in one card where the chat app displays Frameo cards: all the stage's ids at\nonce, before its first `wait_task`; the card updates itself as the work finishes, so the same ids are not shown again.\n\n**The plan first.** Before the first paid call, the plan goes to the user in the chat as plain\ntext: what will be made, in order, one line per generation (for a script, the shot list; for a\nset, each shot), with each line's credits and the total. The credits come from\n`estimate_cost(items=[…])`, up to 10 items a call, so a long plan takes several calls; those\nquotes may expire unused, since each stage is quoted again right before it runs. Nothing is\ngenerated until the user says yes. The user can drop or change lines; a changed line is priced\nagain.\n\n**Shot order.** Pass `shot_number` on every `generate_image` and `generate_video` of a shot (1, 2, 3… in story order; the same number for a retake and for that shot's video), so the project keeps each shot apart, in order. Cast, prop and location references take `placement_kind` (`character`, `prop` or `location`) and the subject's name as `placement_group` instead: they are kept with the project's references, apart from the shots built from them.\n\n**1. The presenter still (~18 credits).** `generate_image`: a mid-shot of the presenter facing\ncamera, neutral background unless the user wants one, `image_urls=[photo]` when there is a\nphoto. `wait_task`, show it; adjust once if asked.\n\n**2. The voice (~1 credit per 50 characters).** `generate_speech(text=script, voice_id)` in one\ncall when the whole script fits one clip (15 s, the lipsync's cap, or the video model's max from\n`list_models(kind=\"video\")` when that is lower); otherwise split at sentence breaks — and at clause breaks (commas, dashes) when one\nsentence alone is still too long — so each file fits one clip. `wait_task` gives the link; play it back to the user before spending on video. The result's\n`duration_seconds`, the file's measured spoken length, is its raw estimate, kept as is for the\nlipsync; a result without one is estimated at 2.8 words per second (2.5 for Hindi) plus one\nsecond of headroom, and that estimate is approximate. When the user picks a presenter\n`list_characters` already has in the project, its first image is the still and its `voice_id` the\nvoice. A new\npresenter is saved with `save_character` under a name not already in the cast (the same name\nreplaces that character's voice), with `image_urls=[presenter still]` and the `voice_id`, so later\nvideos in this project reuse the same face and voice.\n\n**3. The clip (~65 credits per 5 s + ~20 per second of lipsync).** For each speech file:\n`generate_video` from the still (`first_frame_url`) with a prompt like \"presenter speaking\nto camera, subtle natural head movement, steady framing\", `duration` = that file's raw\nestimate rounded up to whole seconds, kept inside the video model's range\n(`list_models(kind=\"video\")`; 4–30 s on the default) and at most 15 s — step 2 sized the files to\nthat, and a file that measures a little longer still goes in whole as `audio_duration`,\n`wait_task`, then `generate_lipsync(video_url, audio_url, duration, audio_duration=the raw\nestimate, aspect_ratio, resolution)` — the raw one, so a clamped clip is still extended to\nthe speech; the size the clip was made at; and `duration` never above 15 s, the lipsync's\nown cap, whatever the video model allows — and\n`wait_task`. Test the first clip\nbefore the rest.\n\n**4. Title card (free).** If wanted: `render_motion_graphics` with `template=\"title_card\"`, the title\n(and a `subtitle`), the piece's `size` and a `duration` of 2 to 3 s; `wait_task` returns the card's clip,\njoined in front in the cut. It counts against the 30 runs per clock hour.\n\n**5. Cut (free).** With a title card, one pass of its own first: the card comes at full HD in its\n`size`, so it is scaled to the clips' size (`scale`, then `setsar=1`) and given a bounded silent\ntrack (`-f lavfi -t <card seconds> -i anullsrc=r=<the clips' sample rate>:cl=stereo`); an\nunbounded `anullsrc` never ends and stalls the join. Then `run_ffmpeg` takes at most 10 inputs and 4 outputs:\nconcatenate the lipsynced clips in\norder, in groups of at most 10 — the card counts as an input, so nine clips per group when\none is joined in front — and repeat until the final call fits (`wait_task` after each pass;\nits outputs are the next pass's inputs). Output `final.mp4`. `wait_task`,\nreturn the link and `open_in_frameo`.\n\n## Done\n\nThe finished clip, the presenter still, and every clip in the Frameo project, ready for\nedits in the app.\n\n## Files\n\n- `references/overlay.md` — the presenter in a corner of the user's own footage: the green still,\n the clips per line, the composite and its check.\n"
Full snapshot data
{
"description": "One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length. Use for explainers, founder messages, course intros and announcements, or to put the user on screen over footage they already have.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 375
},
{
"relative_path": "assets/icon.svg",
"size_in_bytes": 405
},
{
"relative_path": "references/overlay.md",
"size_in_bytes": 5045
}
],
"name": "talking-presenter",
"skill_md_contents": "---\nname: talking-presenter\ndescription: \"One person on camera delivers a script: a face (photo or designed), a fixed voice, lipsynced delivery, optional title card, cut to length. Use for explainers, founder messages, course intros and announcements, or to put the user on screen over footage they already have.\"\n---\n\n## When\n\nUse for one person speaking to camera: an explainer, a founder message, a course intro, an\nannouncement, a customer-support answer. Any language the voice catalog covers.\n\nTo put the user, from their photo, on screen in a corner of footage they already have, follow\n`get_skill_file(skill_id=\"talking-presenter\", path=\"references/overlay.md\")` (picture-in-picture).\n\nNot for: several characters in scenes (`script-to-video`), or a narrator heard over generated\nscenes with no one on screen (`faceless-story-video`).\n\n## Ask first\n\n1. **Who** — a photo (`show_upload` for files on the user's device, `import_media_url` for a web link; images attached to the chat reach Frameo only through `import_attachments`, in apps that pass them such as ChatGPT, and `create_upload_url` is for clients that send the file themselves) or a description to design from.\n2. **Voice** — the user's preference in words (warm, brisk, older, Hindi, British…); pick 3\n with `search_voices` and show their names.\n3. **Frame** — 9:16 or 16:9, and whether a title card opens the piece.\n4. **Script** — the user's own, used as written. When they ask for one to be written, follow the\n word budget, hook, lines-to-cut and delivery sections of\n `get_skill_file(skill_id=\"ugc-video\", path=\"references/script-craft.md\")`.\n\nSay the rough cost (the script's length decides it) in the same turn as the questions; the user's yes comes with the plan (Steps, **The plan first.**).\n\n## Steps\n\n**Before any paid step.** The project: `list_projects` (or `create_project`) gives the `project_id`\nand, when the project has several modules, the `module_id`; every call below that takes a project —\n`estimate_cost` included — gets that same pair; without the project those tools answer `project_needed`, and without the\nmodule of a project that has several, `module_needed`, which lists its modules. The\nquote: one `estimate_cost(items=[…])` prices a stage in one call, with the same project, model,\nsize and number of `image_urls` or `reference_image_urls` (`reference_count`) as each generate call, and returns a `quote_id` per item plus the total. Each generate call\nthen passes its own item's `quote_id` and `confirmed_by_user=true`. A quote is single-use and lasts\n15 minutes, so a long plan is priced stage by stage, right before each stage runs; a stage that\ncomes to more than the user approved is asked about again first. Generate calls return\n`generation_ids`; `wait_task` returns the links, and `show_generations` shows each stage's running\nand finished work in one card where the chat app displays Frameo cards: all the stage's ids at\nonce, before its first `wait_task`; the card updates itself as the work finishes, so the same ids are not shown again.\n\n**The plan first.** Before the first paid call, the plan goes to the user in the chat as plain\ntext: what will be made, in order, one line per generation (for a script, the shot list; for a\nset, each shot), with each line's credits and the total. The credits come from\n`estimate_cost(items=[…])`, up to 10 items a call, so a long plan takes several calls; those\nquotes may expire unused, since each stage is quoted again right before it runs. Nothing is\ngenerated until the user says yes. The user can drop or change lines; a changed line is priced\nagain.\n\n**Shot order.** Pass `shot_number` on every `generate_image` and `generate_video` of a shot (1, 2, 3… in story order; the same number for a retake and for that shot's video), so the project keeps each shot apart, in order. Cast, prop and location references take `placement_kind` (`character`, `prop` or `location`) and the subject's name as `placement_group` instead: they are kept with the project's references, apart from the shots built from them.\n\n**1. The presenter still (~18 credits).** `generate_image`: a mid-shot of the presenter facing\ncamera, neutral background unless the user wants one, `image_urls=[photo]` when there is a\nphoto. `wait_task`, show it; adjust once if asked.\n\n**2. The voice (~1 credit per 50 characters).** `generate_speech(text=script, voice_id)` in one\ncall when the whole script fits one clip (15 s, the lipsync's cap, or the video model's max from\n`list_models(kind=\"video\")` when that is lower); otherwise split at sentence breaks — and at clause breaks (commas, dashes) when one\nsentence alone is still too long — so each file fits one clip. `wait_task` gives the link; play it back to the user before spending on video. The result's\n`duration_seconds`, the file's measured spoken length, is its raw estimate, kept as is for the\nlipsync; a result without one is estimated at 2.8 words per second (2.5 for Hindi) plus one\nsecond of headroom, and that estimate is approximate. When the user picks a presenter\n`list_characters` already has in the project, its first image is the still and its `voice_id` the\nvoice. A new\npresenter is saved with `save_character` under a name not already in the cast (the same name\nreplaces that character's voice), with `image_urls=[presenter still]` and the `voice_id`, so later\nvideos in this project reuse the same face and voice.\n\n**3. The clip (~65 credits per 5 s + ~20 per second of lipsync).** For each speech file:\n`generate_video` from the still (`first_frame_url`) with a prompt like \"presenter speaking\nto camera, subtle natural head movement, steady framing\", `duration` = that file's raw\nestimate rounded up to whole seconds, kept inside the video model's range\n(`list_models(kind=\"video\")`; 4–30 s on the default) and at most 15 s — step 2 sized the files to\nthat, and a file that measures a little longer still goes in whole as `audio_duration`,\n`wait_task`, then `generate_lipsync(video_url, audio_url, duration, audio_duration=the raw\nestimate, aspect_ratio, resolution)` — the raw one, so a clamped clip is still extended to\nthe speech; the size the clip was made at; and `duration` never above 15 s, the lipsync's\nown cap, whatever the video model allows — and\n`wait_task`. Test the first clip\nbefore the rest.\n\n**4. Title card (free).** If wanted: `render_motion_graphics` with `template=\"title_card\"`, the title\n(and a `subtitle`), the piece's `size` and a `duration` of 2 to 3 s; `wait_task` returns the card's clip,\njoined in front in the cut. It counts against the 30 runs per clock hour.\n\n**5. Cut (free).** With a title card, one pass of its own first: the card comes at full HD in its\n`size`, so it is scaled to the clips' size (`scale`, then `setsar=1`) and given a bounded silent\ntrack (`-f lavfi -t <card seconds> -i anullsrc=r=<the clips' sample rate>:cl=stereo`); an\nunbounded `anullsrc` never ends and stalls the join. Then `run_ffmpeg` takes at most 10 inputs and 4 outputs:\nconcatenate the lipsynced clips in\norder, in groups of at most 10 — the card counts as an input, so nine clips per group when\none is joined in front — and repeat until the final call fits (`wait_task` after each pass;\nits outputs are the next pass's inputs). Output `final.mp4`. `wait_task`,\nreturn the link and `open_in_frameo`.\n\n## Done\n\nThe finished clip, the presenter still, and every clip in the Frameo project, ready for\nedits in the app.\n\n## Files\n\n- `references/overlay.md` — the presenter in a corner of the user's own footage: the green still,\n the clips per line, the composite and its check.\n"
}SHA-256 of public snapshot: 155c3e3ab056bd8f13c90d611f4c7564f29f0db2ae4240295e8ce87d02cd6afb