hermosodocs

Creative generation

Plan, render, and finish image and video ads. Long renders run as jobs you poll.

31 tools. Every name, description and parameter on this page is generated from the running MCP server — see how this reference is built.

planning

plan_ad#

Plan an ad concept

Creative director: turn a brand + product/brief into a finished ad CONCEPT — copy variants (headline/primary/cta) plus an image_concept.prompt OR a video_storyboard, with the resolved recipe + the model ids to render with. Renders nothing; chain its output into generate_image / generate_video. THE USER’S EXPLICIT LENGTH IS SOVEREIGN: when they name a duration ("a 30 second ad", "make it 45s"), pass it as durationSeconds — the board is then AUTHORED to that length (its scenes sum to it) and render_ad renders it as one clip or stitched acts accordingly. Leaving it out lets the planner pick its own default, which is how an explicit ask silently becomes a 15s spot. Spends LLM tokens, 0 ScrapeCreators credits.

ParameterTypeDescription
brandstring | objectbrand name, or a brand profile object {name,domain,category,palette,products,…}. OMIT to use the workspace’s SAVED brand + memory automatically (see get_brand); use draft_brand to onboard a new one
productrequiredstringwhat to advertise + any angle/offer the user specified
format"auto" | "image" | "video"'image', 'video', or 'auto' when unspecified
durationSecondsnumberVIDEO ONLY — the total spot length the user explicitly asked for, in seconds, copied verbatim (30 for "a 30 second ad"). The planner authors the storyboard TO it: the scenes’ seconds sum to it and the script is word-budgeted for it. Supported range 4–180; anything outside is CLAMPED to it (the reply says so). One model clip caps at 15s, so ≤15 renders as a single continuous pass and anything longer is STITCHED from acts filled to 15s with the remainder last (40 → 15+15+10, 17 → 13+4) — never time-compressed. Omit when the user named no length; do NOT pass a guess, an omitted value keeps the recipe-aware default.
hookstringforce the VISUAL scroll-stop mechanic the opening beat is built on — a hook id from list_hooks (e.g. "direct_callout", "mid_problem", "macro_asmr"). Omit to let the planner pick. A hook that cannot be delivered in this brief is DROPPED with the reason rather than rendered wrongly — an on-screen-text hook on an authentic/UGC ad is the one that bites, because that register carries zero on-screen text.
settingstringforce the WHERE — a setting id from list_hooks (e.g. "kitchen", "gym", or a surreal one like "volcano_rim" / "airplane_wing", which are played 100% straight and never acknowledged). Omit for a neutral setting.
recipestringa recipe id from hermoso_capabilities to force an archetype
referencestringa reference ad URL to remix the angle from — Facebook Ad Library, LinkedIn Ad Library or Google Ads Transparency links (the real ad’s copy/advertiser are fetched and fed into the concept)
languagestringoutput language for the ad copy (e.g. Spanish) — default English

image

generate_image#

Generate ad image

Render a finished ad IMAGE and return its served URL. refImages (local paths or URLs) force product-accurate compositing (drops a real product into the scene). MULTI-BRAND CAUTION: useBrand hydration pulls the SAVED workspace brand — when working a brand that is NOT the saved one (a fresh draft_brand), pass that brand's own productImages/logo as refImages (and useBrand:false) or the output composites the WRONG brand's product. model = a catalog id from hermoso_capabilities (omit for the default). Fast (seconds). Spends credits.

ParameterTypeDescription
promptrequiredstringthe full image prompt — subject, composition, lighting, and any on-image ad text
refImagesstring[]local file paths or URLs of product/logo references to composite in
useBrandbooleandefault true: with no refImages, the server hydrates the SAVED brand’s product/logo references so the output lands on-brand; pass false for a pure prompt-only render
aspectRatiostringe.g. '1:1', '9:16', '16:9'
modelstringimage model id from hermoso_capabilities
imageSizestringpixel-size preset for models that support it (e.g. 1K/2K) — omit for the default

YouTube / social thumbnails + video covers

make_thumbnail#

Make video thumbnail

Render a click-driving YOUTUBE / Shorts / Instagram THUMBNAIL or video cover — the full production pipeline (concept framework → casting → scene → render → surgical tweaks → text), not a bare image prompt. Use this for any "thumbnail", "video cover", "video preview" or MrBeast-style packaging ask INSTEAD of generate_image. About 9 credits per variant; the headline overlay is free. CONCEPT — every thumbnail must open an INFORMATION GAP (the image raises a question the title answers) while staying truthful to the video. Brainstorm ≥5 concepts across the 16 frameworks before you pick, and feel free to combine two. Frameworks (pass as `framework`): before_after · social_ui · three_step · screenshot · posed_portrait (the default) · posed_action · specific_day · graphical · landscape · map_aerial · product · adding_text · repetition · size_difference · news_clip · amplified_reality. Call hermoso_capabilities for each one's full 'realize it with' note plus the emotion, overlay-style, font and rim-colour catalogs. THREE GATES, all BEFORE you render: 1. WHO IS IN FRAME — never assume and never silently substitute a stranger. If the framework puts a person in frame and no face photo is attached, the tool refuses (nothing rendered, nothing charged) and tells you to ask the user once: themselves (send a face photo → the identity gets locked), a generated person (`castGenericPerson:true`), or a people-free framework. 2. TEXT — the default is a CLEAN render with the headline TYPESET OVER THE TOP afterwards (free, always legible, correctly spelled). Just pass `headline`. Only set `bakeText:true` if the user explicitly asks for the words painted INTO the image — verified live, that renders the asked-for words correctly but leaks garbled invented text across the rest of the frame. Never infer text intent from the topic or the framework. 3. HOW MANY — ask once whether they want one thumbnail or a SET (offer 4: the same concept at different emotions and/or camera takes). Default is 1; `variants` caps at 16. IDENTITY LOCK is automatic for every attached face photo. `emotion` is the single biggest CTR lever on a face: shock · hype · fear · confusion · determination · smug · charisma · disgust · awe · rage · laugh (or your own phrase). Finished thumbnail needs a fix? Re-call with `tweak` + `sourceImage` for a surgical, pixel-faithful edit (emotion / background / background_color / rim_light) instead of re-rendering — tweaks chain. ALWAYS check the returned postRenderCheck against the image before you present it. PROMPT LANGUAGE — write every DESCRIPTIVE field in ENGLISH (`sceneBrief`, `keyElements`, `location`, `composition`, `background`, `topic`, each person's `describe`, and every `reference` field), translating the user's wording where needed: the image models are trained on English and a non-English scene description renders noticeably worse. Text that gets BAKED OR TYPESET stays verbatim in the user's own language — `headline`, `headlineLines` and `bakedUiText` are never translated.

ParameterTypeDescription
frameworkstringconcept framework id (default 'posed_portrait'); see the list in this description / hermoso_capabilities
frameworkRequestedbooleantrue ONLY when the USER named this framework — it is what authorizes a text-carrying framework (social_ui / news_clip / specific_day / map_aerial) to bake its short UI label
sceneBriefstringwhat the thumbnail depicts — the concept in one dense sentence, rendered exactly
topicstringthe video's topic — used to pick the hero object when you don't name keyElements
headlinestring2–4 word headline. Typeset OVER the finished render by default (free, always legible); newlines split it into stacked lines
headlineLinesstring[]explicit headline lines (up to 3) — overrides splitting `headline` on newlines
bakeTextbooleandefault false. true paints the headline INTO the generation — only on an explicit user ask; it leaks garbled text elsewhere in the frame
bakedUiTextstringshort label for a text-carrying framework (a chat bubble, a DAY N badge, a news lower-third, a map callout) — needs frameworkRequested:true
overlayStylestringheadline style: 'beast' (default, white + heavy black stroke) / 'fire' / 'neon-lime' / 'clean-glass' / 'marker'
fontstringheadline font (default Anton). Alternatives incl. Bebas Neue, Oswald, Archivo Black, Montserrat, Inter, Playfair Display
headlinePlace"bottom" | "top" | "center"where the headline sits — never over the face (default 'bottom')
faceImagesstring[]up to 3 face photos (URLs or local paths) — each becomes a locked CHARACTER identity, in order
peopleobject[]people described in prose instead of by photo (each still gets the chosen expression)
castGenericPersonbooleanpass true only after the user has explicitly chosen a generated stranger over their own face
emotionstringthe expression on the face (default 'shock') — a preset id or your own phrase
emotionsstring[]render one variant per emotion (variants = emotions × takes, max 16)
takesnumbercamera takes per emotion, 1–4: designed framing / low-angle hero / extreme close-up / wide dutch tilt
variantsnumberhow many thumbnails to render (default 1, max 16). Each is its own billed render — offer a set of 4 rather than assuming
aspectRatiostring'16:9' (YouTube, default) / '9:16' (Shorts) / '4:5' (Instagram) / '4:3' / '1:1'
keyElementsstringsignature props / effects that make it pop — oversized, flying toward camera
locationstringplace, time of day, weather, atmosphere
compositionstringoverride the default large-foreground-subject composition
backgroundstringoverride the default bold saturated colour-field background
rimColorstringcolored back+hair light — ONLY when the user names one: 'ice-blue' / 'neon-magenta' / 'toxic-lime' / 'amber-gold' / 'pure-white'
restrainedGradebooleantrue for a calm / premium / muted look instead of the default punchy poster grade
logostringa brand logo URL or path to place into the composition
logo3dbooleanfirst turn the flat logo into a volumetric 3D render (one extra billed image), then composite that
splitobjectsplit/panel LAYOUT — only when the user asks for one ("split", "before/after", "versus screen"). "X vs Y" as a SCENE stays one unified frame
referenceobjectfields YOU extracted by eye from a reference thumbnail. Extract ALL of: brief (one dense sentence on the concept), subject (pose/action generically, NEVER a specific identity), elements, location, composition, background, split (boolean), split_count, person_count (0-3), emotion (one of the 11 presets or 'other'), emotion_detail (one vivid sentence covering eyes, brows, mouth, head angle). emotion + emotion_detail carry the reference's actual facial performance, which is the single biggest CTR lever on a face; split/split_count reproduce its panel structure. The reference image itself is never sent to the model
tweakobjectsurgical pixel-faithful edit of a FINISHED thumbnail — needs sourceImage
sourceImagestringthe finished thumbnail URL a `tweak` edits; tweaks chain, so feed each accepted output into the next
forceGeneratebooleanrender the 'screenshot' framework anyway (it is normally a real video frame, not a generation)

raw playground: voice

generate_voice#

Generate voiceover

RAW text-to-speech from the voice-model catalog: speak a script in a chosen voice and return the served MP3 URL. For a standalone voiceover / narration clip — NOT for adding audio to a video (render_ad and generate_video voice their own spots; change_voice re-voices a finished clip). engine picks the voice model (default 'seed-audio'; also 'eleven-v3', 'minimax-speech', 'kokoro'); voice is a preset name from that engine (see hermoso_capabilities → voice engines). Paid (a couple of credits by length; ≤900 characters).

ParameterTypeDescription
textrequiredstringthe script to speak (≤900 characters)
enginestringvoice-engine id: 'seed-audio' (default), 'eleven-v3', 'minimax-speech', or 'kokoro' — listed in hermoso_capabilities
voicestringa voice preset from the chosen engine (e.g. 'Aria'/'George' on eleven-v3, 'stokie_en' on seed-audio) — omit for the engine default

generate_text#

Generate text

RAW text generation against the writing-model catalog (Claude, Gemini, GPT, Llama, DeepSeek…) — ad copy, hooks, scripts, rewrites, brainstorms. Prompt-only, no ad assembly (for a finished on-brand creative use plan_ad → render_ad). model = a writing-model id from hermoso_capabilities (omit for the default Claude orchestrator). Paid (a credit or two by length).

ParameterTypeDescription
promptrequiredstringthe writing task / question
modelstringa writing-model id from hermoso_capabilities (a Claude / Gemini / GPT / Llama / DeepSeek id) — omit for the default

video / avatar / stitch

render_ad#

Render ad video

RECOMMENDED for finished video ADS: render a plan_ad concept through the SAME quality pipeline as the Hermoso web Studio — timed shot list, exact/clean speech (no garbled words), text composited in post (never model-painted), brand end card, licensed music bed, real product references. Pass plan_ad’s full structured output as `creative`. Honors the plan’s render_plan structure/duration: a ≤15s storyboard renders as ONE single-pass clip; a longer plan automatically renders as STITCHED ACTS (fewest balanced ≤15s clips) — never time-compressed into one clip. CAST A SAVED CREATOR with `creator` so the SAME person stars in this ad as in the last one (list_creators is the roster) — otherwise every render invents a new face. Renders take 1–3 min; keep polling get_job if it returns still-rendering. Spends credits.

ParameterTypeDescription
creativerequiredobjectthe FULL structured output of plan_ad (must contain video_storyboard)
creatorstringCAST A SAVED CREATOR in this ad — their id from list_creators, or the name you know them by (“Sarah”). Their saved portrait becomes the on-camera identity for the whole spot, so the same face carries across every act and across every ad you render for this brand — and because we already have their picture, the character portrait this pipeline would otherwise generate is skipped, so casting somebody costs LESS than not casting them. Omit to let the ad cast a fresh person. Refused for free, with nothing rendered, if the name matches nobody or more than one creator, if the plan has nobody on camera, or if they are a REAL person with no likeness consent on file.
modelstringvideo model id from hermoso_capabilities (default: the plan’s pick). Naming one is a DELIBERATE pick — the server asks before ever swapping it (no silent fallback)
durationSecondsnumbertotal ad length in seconds (supported range 4–180; outside that it is clamped). Omit to honor the plan’s own duration — that is almost always right. This only RE-TIMES an already-authored board (its scenes are scaled to fit), it does NOT re-write it, so to change the length of the ad the user asked for, re-run plan_ad with durationSeconds instead. ≤15s renders as one clip; longer is stitched from acts filled to 15s with the remainder last — use dryRun:true to see the exact act split for free before spending.
aspectRatiostringoutput aspect ratio, e.g. 9:16 (default) / 1:1 / 16:9
resolution"480p" | "720p" | "1080p" | "4k"'720p' default; '480p' = cheap fast draft pass, '1080p'/'4k' = premium final delivery (more credits)
captionsbooleancomposited caption pills on/off (default: the recipe decides)
endCardbooleanbranded end card on/off (default: on, except organic recipes)
musicbooleanlicensed music bed on/off (default on)
lockupbooleanpersistent brand-logo lockup overlay on/off
ttsVoicestringvoiceover voice name (e.g. Rachel / George) when the plan voices over
dryRunbooleanreturn the routing decision (single pass vs stitched acts, resolved model + act lengths) WITHOUT submitting a render — free, nothing charged
allowGenericProductbooleanproceed even though this brand has NO product photo on file and the ad features a product — the packaging will be INVENTED. Only pass true after telling the user that and hearing they are fine with a generic stand-in

make_template_ad#

Make template ad

Render a NATIVE-STYLE TEMPLATE ad from pure HTML — no AI video/image model in the loop, renders in ~30 seconds for a couple of credits. Perfect for native-feel social ads at volume. YOU author the content (short, casual, believable — never marketing-speak). Templates (pass as config.template): 'imessage-chat' (VIDEO ~15s: a real-looking iMessage thread where a friend reveals the product as a rich-link card; config: { thread: { contactName, messages: [{from:'them'|'me', text?, product?:{image,title,domain}}] }, theme?:'dark'|'light', endCard:{headline,cta,domain,logo?,color} } — 4-6 short lowercase bubbles, product card mid-thread from 'me', 1-2 excited replies after); 'chatgpt-chat' (VIDEO: a ChatGPT answer streams the punchline; config: { question, answer (may **bold** the brand), productImage?, endCard }); 'apple-notes' (VIDEO: an iPhone note types itself out; config: { title, lines: string[], theme?, endCard }); 'value-prop' (VIDEO ~17s kinetic typography: config: { hook (≤40 chars), claims: string[] (3-5 COMPLETE phrases, ≤6 words / ≤34 chars each — a finished thought, NEVER a clipped clause like 'Looks good on any'), productImages: string[] (2-3 DISTINCT photos — one rotates per card), palette: string[], endCard }); 'static-mockup' (IMAGE: config: { style:'imessage'|'notes'|'card', size?:{w,h}, ...style fields }); 'airdrop-carousel' (VIDEO ~10s: an iOS AirDrop share card springs up and cycles 3-16 REAL product photos to a full-lineup payoff; config: { brandName, products: [{image, title?}], contactLine?, endCard }); 'app-ui-tour' (VIDEO ~12-16s for APP brands: floating-iPhone mockup walks through REAL app screenshots with kinetic captions; config: { hook?, appName, iconImage?, beats: [{screenImage, caption}] (2-6), palette?, fontStack?, endCard }); 'imessage-cascade' (VIDEO ~12s: iOS notification banners spring in and stack over a blurred backdrop; config: { notifications: [{sender, text}] (4-8), backgroundImage?, endCard }); 'photo-grid' (VIDEO ~8s: collage assembles real photos one at a time; config: { title?, photos: [{image, label?}] (4-9), palette?, fontStack?, endCard }); 'vignette' (VIDEO ~12s: cinematic Ken-Burns hero film; config: { hook, lines: [2-4 ≤40ch], heroImage, palette?, fontStack?, endCard }); 'kinetic-type' (VIDEO ~9-15s typographic motion design with NO VOICEOVER — it is NOT a silent asset: it always carries its own synthesised SFX (whoosh/tick/chime) and, once a curated track is on file, the family's loudest music bed at -16 LUFS; config.music:'off' silences the bed but never the SFX: 3-6 short phrases each land word by word on a full-bleed brand card (product beats caption the phrase over the photo instead), the longest word picked out in the brand accent, and a skewed accent slab wipes every cut; supply productImages and every OTHER beat becomes a full-bleed product shot with its phrase captioned over it — with none it renders as pure typography, so it needs NO photos; config: { phrases: string[] (3-6, ≤34 chars each — punchy, declarative, ONE idea per phrase, a finished thought never a clipped clause), productImages?: string[] (up to 4 DISTINCT photos), palette?: string[], fontStack?, endCard }); 'myth-vs-fact' (VIDEO ~15-26s VO-FIRST kinetic explainer with a real VOICEOVER — the family's ONE paid-audio format: a calm-authority read busts 2-4 myths, each MYTH line slamming in with a red per-line strike then the counter FACT line landing bold+affirmative, word-level KARAOKE lighting each word as the VO speaks it; config: { pairs: [{ myth (≤50ch, the common wrong belief), fact (≤60ch, the corrective truth — wrap its payoff phrase in [brackets] to accent it) }] (2-4), palette?, fontStack?, endCard }. Real product truths only — NEVER invent stats. Costs the flat template credits PLUS a small voiceover charge); 'carousel' (MULTI-IMAGE: 5-10 branded 1080×1080 PNG slides for Meta/LinkedIn/IG carousels — returns an images[] array, one PNG per slide; config: { cover: { hook?, title }, slides: [{ headline (≤8 words), support? (≤16 words), stat?: { value, label } }] (3-8; a stat slide is a REAL user-supplied number like '94%' or '40k+' + a label, never invented), cta: { headline, cta?, domain? }, productImage?, logo?, palette?, fontStack?, endCardColor? }). Every VIDEO format except myth-vs-fact (VO-first, deliberately dry) also gets a mood-matched MUSIC BED when a curated track is on file (the library ships empty — no track means no bed, never a paid generation) under its own SFX, from the curated library — free, no model, no extra credits; set config.music:'off' for a silent cut or a mood name (upbeat/calm/warm/epic/tense/playful/elegant/hype/chill/dramatic) to re-mood it. Image URLs may be any public URL — the server localizes them. Spends a couple of credits.

ParameterTypeDescription
configrequiredobjectthe template config — MUST include config.template (one of the template ids above) plus that template's fields

finish_video#

Finish video

Post-process an EXISTING rendered video (its served mp4 URL) with the proven direct-response 'reviewer' finish and/or a film-grain pass — no AI model, ~30s, a couple of credits. pills=true composites a header pill (e.g. '10/10 would buy again'), a brand-accent sub-pill, and 3-4 green-check proof pills cascading in on the beat (YOU author the copy: header ≤40 chars, sub ≤34, each point ≤44 — concrete real benefits, never fabricated stats). grain=true applies a subtle camera-grain finish that makes photoreal AI renders look phone-shot ('less AI') — works alone or with pills. Returns a NEW video; the original is untouched.

ParameterTypeDescription
videoUrlrequiredstringthe served URL of the video to finish (from a previous render/job)
headerstringheader pill copy, ≤40 chars (required when pills is on)
substringaccent sub-pill copy, ≤34 chars (usually the product/brand)
pointsstring[]3-4 proof points, ≤44 chars each
accentstringbrand accent hex for the sub-pill
pillsbooleandefault true — set false for a grain-only pass
grainbooleandefault false — anti-AI film-grain finish

post_edit#

Post-production edit

MECHANICAL post-production on an EXISTING rendered video (its served mp4 URL) — an ordered plan of whitelisted primitives executed by ffmpeg (+ Chrome for typeset cards) in seconds for ~2 credits flat, NO AI model, the original untouched (returns a NEW video). The lane for: append a branded end card ('add an end card with our logo and website' — ADDS its seconds, never re-renders), trim, speed (0.5-2x), mute (whole or a window), audio_gain (-20..+6 dB), fade_out, corner logo watermark, anti-AI film grain. Up to 6 ops per plan, applied in order. Brand assets (name/domain/logo/accent) load from the workspace brand automatically; override per-call if needed. NEVER use generate_video/render_ad for these mechanical asks.

ParameterTypeDescription
videoUrlrequiredstringthe served URL of the video to edit
opsrequiredobject[]the ordered edit plan (max 6 ops)
brandNamestringoverride the workspace brand name
domainstringoverride the brand website
accentstringoverride the brand accent hex

fix_beat#

Fix a video beat

Surgically re-render ONE time window (1.5-8s) of an existing rendered video and splice it back on the VIDEO TRACK ONLY — the rest of the video and ALL audio stay byte-identical. Use when one beat/shot is broken ('the shot at 8 seconds glitches') and a full re-render would waste the parts that worked; bills only the replacement clip's seconds (~1/3 of a full render). Do NOT pick a window covering spoken dialogue (a video-only splice under speech breaks lip-sync) — pass speechWindows to enforce this.

ParameterTypeDescription
videoUrlrequiredstringthe served URL of the master video to fix
startSecondsrequirednumberwindow start in seconds
endSecondsrequirednumberwindow end in seconds (window 1.5-8s)
promptrequiredstringwhat the replacement footage should show — describe the shot, matching the master's style
refImagestringoptional product/style anchor image URL
speechWindowsnumber[][][[start,end],...] windows with spoken lines — the fix window must not overlap these

THREE BUILT LANES

clip_video#

Clip a long video

Cut ONE long video into several RANKED, ready-to-post short clips (podcast, webinar, interview, conference talk, long ad cut → Reels/Shorts/TikTok). Transcribes the source with timestamps, picks the strongest SELF-CONTAINED moments, then cuts + reframes each with ffmpeg — no video model renders anything, which is why it's fast and cheap. ACCEPTS: (a) a YouTube link (or Vimeo / Loom / Dailymotion / Streamable / Rumble / Wistia / Twitch / TED) — the server pulls the video down itself; (b) a direct https .mp4/.mov/.webm; (c) a Hermoso /generated/ URL (upload_file turns a local file into one). NOT supported: TikTok / Instagram / Facebook links, and anything age-restricted, private, members-only, geo-blocked or still LIVE — those fail fast with the real reason and are fully refunded, so ask for a direct file or an upload rather than retrying. Source must be at least ~15s and under ~600MB; only the first ~40 minutes is analysed (the result reports truncated:true when it hits that). Cost: a ~7-credit hold, settled to the exact transcription + encode cost, plus the clip-selection model's tokens billed as their own small event. RETURNS clips[] — each with its OWN served mp4 URL, title, hook, ready-to-post caption, 0-100 score and source timecode — not a single video.

ParameterTypeDescription
videorequiredstringthe long video to clip — a YouTube/Vimeo/Loom/Dailymotion/Streamable/Rumble/Wistia/Twitch/TED watch URL, a direct https .mp4/.mov/.webm, or a Hermoso /generated/ URL
countnumberhow many clips to cut, 1-8 (default 4)
aspectRatio"9:16" | "1:1" | "16:9" | "keep"clip shape — '9:16' (default) vertical for Reels/Shorts/TikTok; 'keep' leaves the source framing untouched

make_explainer#

Make an explainer video

Turn a TOPIC into a finished narrated explainer video. Writes a sectioned script, paints a BURST of pictures per section (about one every 1.5s — most of them one-detail edits of the frame before, so it reads as movement rather than a slideshow), narrates each section with TTS, holds each picture PERFECTLY STILL for its own slice of the narration (the motion is the CUT RATE, exactly as Higgsfield's stills pipeline does it — a slow move on a still shimmers), then composites the end card (and any on-screen text you asked for) with the Chrome+ffmpeg engine the ads use (text is never model-painted, so it never garbles). BURNED ON-SCREEN TEXT IS OFF BY DEFAULT — the narration carries the point and the pictures carry the story, so the film ships clean unless the user asks otherwise; `captions:true` adds held key points and `subtitles:true` adds narration-timed CAPS (see both). It is an image film WITH motion, not N video-model renders — that's what keeps it affordable. `style` picks the visual family: the default 'cinematic' is photoreal editorial; every other id is a STYLED, strictly non-photoreal look (illustrated / collage / clay / pixel …) that first renders ONE style-key image and then locks every scene to it, so the whole film holds one look. Cost at the default frame density: a ~130-credit hold for a 60s explainer on the default style, ~100 styled; `frameDensity:'lean'` roughly halves it and `'minimal'` (one picture per section) is ~30. All settle to the exact per-frame image + narration spend (a longer target = more sections = more). Takes SEVERAL minutes — one image render per frame; independent frames are painted concurrently, so it is far faster than the frame count suggests. Needs the writing model and a narration voice engine connected. NOT the tool for a short product ad — use render_ad or generate_video for those, and make_template_ad for the deterministic native formats.

ParameterTypeDescription
topicrequiredstringwhat the explainer should teach or explain — a topic or a short brief
durationSecondsnumbertarget length 20-120s (default 60); drives the section count — ~10s of narration each, 3-8 sections
frameDensity"standard" | "lean" | "minimal"how many pictures per second of narration, and therefore what it costs. 'standard' (default) is a frame about every 1.5s — the density Higgsfield's own stills pipeline enforces; 'lean' is one about every 2.5s (the longest hold that still reads as a film, ~40% of the frames and ~40% of the cost); 'minimal' is ONE picture per narration section, which is cheapest and is frankly a slideshow. Only drop below the default if the user asked for something cheaper.
aspectRatio"9:16" | "16:9" | "1:1" | "4:5" | "3:4"'9:16' default
style"cinematic" | "editorial_collage" | "flat_vector" | "stickman" | "whiteboard" | "ink_marker" | "silhouette" | "storybook" | "paper_diorama" | "isometric" | "claymation" | "pixel_art" | "watercolor" | "fluffy_toy" | "low_poly" | "stylized_3d" | "studio_3d" | "mannequin"visual style. 'cinematic' (default) is photoreal; the rest are non-photoreal styled looks — editorial_collage (halftone cutouts + marker accents), flat_vector, stickman, whiteboard, ink_marker, silhouette, storybook (gouache), paper_diorama, isometric, claymation, pixel_art, watercolor, fluffy_toy (felted plush), low_poly, stylized_3d (matte clay render), studio_3d (preschool toy 3D on a white sweep — the Kids default), mannequin (clay-render reenactment figures — a History alternate). Ask the user which they want rather than picking silently; a styled pick costs more (see the cost note).
channel"explainer" | "history" | "kids" | "fairytale"the CHANNEL TYPE — it sets the pacing, the narration register and the default look, and is orthogonal to `style` (a named style always wins): explainer (casual second-person, fast cuts), history (witty chronological retelling / documentary), kids (fastest, question-first, warm teacher), fairytale (slow, atmospheric myth or folklore). Default 'explainer'.
voicestringnarration voice name — omit for the default warm read
captionsbooleanturn ON-SCREEN TEXT on. DEFAULT FALSE, and leave it false unless the user asks — the narration already says the point and the pictures carry it, so the clean film is the better default. `captions:true` on its own burns SUBTITLES (see below), because that is what a caption is for: showing what is being said when the phone is on mute. Slim white CAPS, thin black outline, bottom safe band, no plate, no box.
subtitlesbooleanwhich on-screen text, once `captions` is on. LEAVE IT UNSET (or true) for SUBTITLES — every spoken word, in order, timed to the narration; free, no extra render, no extra credits, and there is NO cue limit, so the whole film is subtitled however long it runs (at most 5 words / 32 characters a line). Set it FALSE only if the user explicitly wants section HEADINGS instead: one short summary label held over each ~7-15s section. That is NOT what is being said — it is a label about it — so it is the wrong answer to "add captions" and to anyone watching on mute. `subtitles:true` also implies `captions:true`. TIMING: each cue is anchored to that section’s REAL measured narration length and distributed inside the section by character count — exact at every section boundary, approximate to a few tenths of a second within one. It is not a word-level speech clock, so never promise frame-accurate sync.
musicstringmusic bed under the narration, measured to sit about 14 dB under the voice and sidechain-ducked beneath it. Omit and the KIDS and FAIRYTALE channels get their recommended bed COMPOSED for this film — those two are the only channels a bed is due on unasked, and it costs a small flat fee; every other channel ships dry. 'off' forces silence. 'library' takes a free curated track only, and ships dry when none is on file. NAME A MOOD — upbeat / calm / warm / epic / tense / playful / elegant / hype / chill / dramatic — to compose one on ANY channel, at the same fee. hermoso_capabilities reports the exact figure as explainerMusicCredits; quote it before you turn a bed on or pick a mood.
upscalenumberoptional FINAL upscale — 2 doubles each side, 4 quadruples. Captions and the end card are burned BEFORE it so they upscale with the frame. It is priced BY LENGTH and it is the expensive part — several times the cost of rendering the film itself. hermoso_capabilities reports the exact figures per length as explainerUpscaleCredits. Never turn it on unasked: quote the number and let the user choose.
endCardbooleanappend the branded end card (default true)
brandNamestringbrand name for the end card — omit to leave it unbranded

product_sizzle#

Product sizzle (music-led)

Render an 18-30s music-led PRODUCT SIZZLE: ONE 15s Seedance 2.0 hero clip of the product, diced into fast cuts and intercut with typeset spec/CTA cards on a brand-coloured grain background, mixed to a music bed. Faceless by design — no people, no voiceover, no spoken lines; the cards carry every word, so nothing is left to a video model's spelling. Pass a real packshot as refImage or the label will not be yours. EXPENSIVE — the hero clip is the only paid leg and it is a full 15s Seedance render: ≈1,040 credits at the DEFAULT 1080p, ≈470 at 720p, ≈220 at 480p, ≈4,130 at 4k (call hermoso_capabilities for the live seedance-2 per-duration numbers; the dicing and the cards are free, and the music bed is already included in the quoted figure). Confirm the spend with the user before calling. For a talking/UGC ad use render_ad or generate_avatar; for a cheap deterministic format use make_template_ad.

ParameterTypeDescription
promptrequiredstringwhat the sizzle should show — the product, the setting, the look
secondsnumberfinished length, clamped to 18-30s (default 25). The PAID hero render is always 15s regardless — this only changes how the cuts and cards are packed
refImagestringproduct packshot URL that anchors the real label — strongly recommended
aspectRatiostring'9:16' default; anything the seedance-2 catalog entry does not list falls back to 9:16
resolution"480p" | "720p" | "1080p" | "4k"hero-clip resolution and therefore the whole cost — DEFAULT '1080p' (≈1,040 credits); '720p' ≈470, '480p' ≈220, '4k' ≈4,130
specsstring[]up to 4 spec lines for the typeset cards, ≤26 chars each
ctastringclosing CTA line, ≤30 chars
brandNamestringbrand name on the cards — defaults to the workspace brand
musicMoodstringmusic-bed mood, e.g. driving / cinematic / upbeat

generate_video#

Generate video

Render a RAW video clip from your own prompt and return its served mp4 URL. For finished brand ADS prefer render_ad (it runs the Studio quality pipeline — composited text, clean speech, end card, music); use this for raw/experimental clips or precise manual control. ONE generation = one continuous clip up to the model’s longest listed duration (seedance-2 goes to 15s single-pass with a full multi-beat arc — never assume a generic 8–10s cap); durationSeconds must be one of the model’s durations from hermoso_capabilities. Renders take 1–3 min. refImage anchors the opening frame; ttsScript adds a voiceover. AUDIO IS NOT FREE AND NOT OPTIONAL BY DEFAULT: a clip delivered with no audio of its own gets a music bed composed and CHARGED on top of the render (see musicMood and audio) — on a cheap short draft the bed can cost as much as the clip. Pass refVideo (a clip URL) to EDIT an existing video instead of generating from scratch — the omni engine transforms that clip per your prompt, inheriting the source clip’s canvas + length (aspectRatio/durationSeconds are ignored for an edit). Spends credits (Starter plan is video-blocked server-side).

ParameterTypeDescription
promptrequiredstringthe video prompt / shot description (for a refVideo edit, this is the transformation instruction)
refImagestringlocal path or URL to anchor the first frame
refVideostringURL of an existing video to EDIT rather than generate from scratch — the omni engine accepts a raw clip and transforms it per your prompt, inheriting the SOURCE clip’s canvas (aspect ratio) and length (aspectRatio/durationSeconds are ignored for an edit). Omit to generate a fresh clip.
durationSecondsnumberlength of THIS ONE clip in seconds — pick one of the chosen model’s listed durations from hermoso_capabilities (seedance-2/kling-3: 5/10/15). This is a single continuous generation, so it CANNOT exceed the model’s longest clip: a longer ask is REFUSED with nothing rendered and nothing charged (it is never quietly truncated). For a spot longer than one clip, use plan_ad with durationSeconds then render_ad, which stitches ≤15s acts (40s = 15+15+10).
aspectRatiostringdefault '9:16'
modelstringvideo model id from hermoso_capabilities. Naming one is a DELIBERATE pick — the server asks before ever swapping it (no silent fallback); omit it to let the router pick
resolution"480p" | "720p" | "1080p" | "4k"'720p' default; '480p' = cheap fast draft pass, '1080p'/'4k' = premium final delivery (more credits)
ttsScriptstringvoiceover script to speak
ttsVoicestringvoice name, e.g. Rachel / George
musicMoodstringWHICH mood the music bed is composed in (upbeat / calm / warm / epic / tense / playful / elegant / hype / chill / dramatic). It does NOT decide WHETHER there is one: a clip that comes back with no audio track — every model hermoso_capabilities lists as "silent", plus any audio model that returned mute — gets a bed composed and CHARGED automatically, at the flat per-track fee hermoso_capabilities reports as explainerMusicCredits, and omitting this field only means the mood defaults to "warm". Pass audio:false for a genuinely silent clip with no bed and no bed charge.
audiobooleandefault true. false = render SILENT: no native model audio, no music bed, and no bed charge held or billed. This is the ONLY way to decline the automatic bed (see musicMood) — leave it alone for anything that should have sound, and do not combine it with ttsScript.

generate_avatar#

Generate talking avatar

Render a TALKING-AVATAR / creator lip-sync clip from a portrait image + a script. Blocks until done (1–3 min). Requires the avatar capability (canAvatar in hermoso_capabilities). Spends credits.

ParameterTypeDescription
imagerequiredstringlocal path or URL of the presenter portrait
scriptrequiredstringthe words the avatar speaks
voicestringvoice name (Rachel/Sarah/George/Adam)
resolutionstring'720p' (default) or '480p' draft

stitch_video#

Stitch multi-scene video

Render a multi-scene STITCHED video (≥2 scenes) — ONLY for spots LONGER than one model clip (>15s). A ≤15s multi-beat ad renders better and cheaper as ONE single-pass generate_video/render_ad on seedance-2 (it handles the full hook→demo→payoff arc in one take) — never stitch those. Blocks until done. Spends credits.

ParameterTypeDescription
scenesrequiredobject[]array of scene objects (visual + optional voiceover/seconds)
aspectRatiostringoutput aspect ratio, e.g. 9:16 (default) / 1:1 / 16:9
voiceoverstringfull voiceover script spoken across the scenes
voicestringvoiceover voice name, e.g. Rachel / George
resolutionstring720p (default), 480p draft, or 1080p final
modelstringvideo model id from hermoso_capabilities — omit to let the router pick
durationSecondsnumbertotal spot length in seconds (defaults to the sum of the scenes’ seconds)

get_job#

Get render job read-only

Poll a render job by id. Returns status (queued|running|done|error), progress, and on done the served media URL. Renders take 1–3 minutes: keep calling this until done/error without asking the user — several calls is normal, not a stall.

ParameterTypeDescription
idrequiredstringthe job id, e.g. job_xxx

assets

list_library#

List library read-only

Browse this workspace's Library — every image/video generated in the Studio, newest first (the same Library the web app shows). Returns served URLs you can open directly or hand to fetch_asset for a download link, plus each asset's kind, model, and age. Free, read-only.

ParameterTypeDescription
kind"image" | "video" | "all"filter by asset kind (default 'all')
limitnumbermax assets to return (default 20, max 60)

fetch_asset#

Fetch asset read-only

Resolve a generated asset reference (a /generated/… path or any URL) to a clickable absolute URL + a direct download URL.

ParameterTypeDescription
urlrequiredstringthe asset url or /generated/ path
namestringoptional filename for the download

post-production & analysis

analyze_video#

Analyze video read-only

Break a video ad down into its structure: the verbatim transcript (voiceover + on-screen text) with a beat list, plus duration and sampled frame timestamps. Use to study a reference/competitor ad before remixing its structure. Costs ~a transcription call; no ScrapeCreators credits.

ParameterTypeDescription
urlrequiredstringthe video URL (a served /generated/ path or a public http(s) video)

score_ad#

Score ad read-only

Virality/performance prediction for a finished ad (image or video URL): overall score, per-dimension breakdown (scroll-stop, hook, clarity, brand/product, CTA, retention, goal fit), strengths, and the single biggest fix. Use BEFORE spending on distribution, or to rank variants.

ParameterTypeDescription
urlrequiredstringthe ad asset URL (a /generated/ path or public URL)
kind"image" | "video"'image' (default) or 'video'
intentstringwhat the ad is trying to achieve, for goal-fit scoring

reframe_video#

Reframe video

Reframe a video to a different aspect ratio (e.g. 16:9 master → 9:16 vertical) with smart subject tracking. Paid render; returns the served URL of the reframed video.

ParameterTypeDescription
videorequiredstringthe source video URL
aspectRatiorequired"9:16" | "1:1" | "16:9" | "4:3" | "3:4" | "21:9" | "9:21"the target aspect ratio

upscale_video#

Upscale video

Upscale a video to higher resolution (2x) for final delivery. Paid render; returns the served URL.

ParameterTypeDescription
videorequiredstringthe source video URL

edit_video#

Edit a video clip

EDIT/transform an existing video clip with a natural-language instruction (video-to-video) — KEEPS the original motion, timing and edit, changes the subject/setting/style. Use for 'change the background to a city', 'make it nighttime', 'restyle it as claymation', 'swap the product'. Best on 3–10s clips. NOT for mechanical cuts, trims, end cards or watermarks (use post_edit — seconds, ~2 credits, no AI model), NOT for making a new video (generate_video / render_ad), NOT for translating the spoken track (dub_video) and NOT for putting a saved creator's face on the motion (recast_motion). Paid render; returns the served URL of the edited clip.

ParameterTypeDescription
videorequiredstringthe source video URL (from a previous render, a job result, or list_library)
instructionrequiredstringthe exact transformation to apply, in the user’s own words
keepAudiobooleandefault true — keep the source clip’s audio track. Set false to return the edit silent
elementsobject[]OPTIONAL identity/product grounding (≤4): a creator portrait or the real product photo, so the edit restores the REAL thing instead of re-inventing it. Describe each one in the instruction. Leave out for a plain restyle

dub_video#

Dub video

Localize a finished video into another language WITHOUT re-rendering it: the spoken track is transcribed, translated, re-voiced and lip-synced back onto the SAME footage, so the visuals, timing and edit are untouched. Just pass the video and the language — the script is read off the source automatically (pass `script` only to override what it heard). Paid; returns the served URL of the localized video.

ParameterTypeDescription
videorequiredstringthe source video URL
languagerequiredstringtarget language, e.g. 'Spanish', 'de', 'French (Canada)'
scriptstringOPTIONAL override for the original spoken words. Leave this out — the source video is transcribed automatically. Only pass it when you already know the exact script and the auto-transcript got it wrong.
voicestringoptional target voice preset, e.g. 'Aria' (warm female) or 'George' (confident male). Defaults to a voice matching the source speaker's register.

change_voice#

Change narrator voice

Swap the narration of a finished video into a different voice — keeps the performance, lip-sync, and background sound. Use when the user likes the video but wants a different narrator voice; use dub_video only for language translation. Paid; returns the served URL.

ParameterTypeDescription
videorequiredstringthe source video URL
voicestringtarget narrator voice preset name, e.g. 'Aria', 'George', 'Rachel', 'Sarah', 'Brian', 'Charlotte' (defaults to a warm female read)

recast_motion#

Recast motion

Motion transfer: re-perform a reference video's motion with a different person/character (supply their image). The reference clip drives the movement; the image supplies the identity. Paid render.

ParameterTypeDescription
imagerequiredstringthe actor/character image URL (who should appear)
videorequiredstringthe reference video whose motion to re-perform
promptstringoptional scene/style guidance
orientation"video" | "image"which aspect to keep: the video's (default) or the image's

plan_variations#

Plan ad variations

Fan a brief into N DISTINCT ad angles (different hooks/mechanics/audiences), each with its own headline + visual brief — then render each with generate_image and rank with score_ad. LLM planning only; renders nothing itself.

ParameterTypeDescription
brandstring | objectbrand name or profile object; OMIT to use the workspace’s saved brand
productrequiredstringwhat to advertise
countintegerhow many distinct variants (default 6)
languagestringoutput language for the variant copy (e.g. Spanish) — default English

product-photo tools

list_product_photos#

List product photos read-only

List the product photos ALREADY saved in your workspace — the brand's product library plus any app-store screens (also surfaces photos locked in your OTHER creations, since a set product lands in the shared library). FREE — returns each photo's url + label. Call it before set_product_image to see the existing photos you can reuse. Reads YOUR saved brand (pass brandId to target a specific brand — that switches this key's active brand like use_brand).

ParameterTypeDescription
brandIdstringa brand id/name from list_brands whose product library to list; omit to use the active brand

set_product_image#

Set product photo

Lock an image as the ad's real PRODUCT photo so every render grounds on the true packaging. Pass `imageUrl` = a product shot's URL — an image from a prior research result (an organic Instagram/TikTok post, a scraped page image), a workspace / list_product_photos url, or any public product photo. The server downloads it and runs a product+safety check: a lifestyle/scene shot with no clear product, or an off-category / unsafe image, is REJECTED and NOTHING is locked (the summary says why). On PASS it persists the photo to a DURABLE url and returns it — pass that url as a reference to generate_image / render_ad. Bills one vision check. Reads YOUR saved brand for the category match (pass brandId to target a specific brand — switches this key's active brand like use_brand).

ParameterTypeDescription
imageUrlrequiredstringthe image URL to lock as the product (from a research result, a workspace / list_product_photos url, or any public product photo)
source_notestringa short note on where it came from, e.g. "from their IG post"
brandIdstringa brand id/name from list_brands to lock the product for; omit to use the active brand

fetch_app_screens#

Fetch App Store screens

Pull an APP brand's REAL App Store screenshots into the workspace brand, so a screen-hungry native format can use them. Use when the brand has 0–1 app screens on file and you want make_template_ad(template:'app-ui-tour'), or the user asks to 'pull my app's screenshots'. Pass appName (defaults to the saved brand's name). FREE — a keyless App Store lookup. It needs a CONFIDENT match: an ambiguous or unknown app returns 0 screens and saves nothing, which you should relay plainly rather than retrying with guesses. On success the screens are saved to the brand (durable URLs) and are immediately usable.

ParameterTypeDescription
appNamestringthe app's name to look up on the App Store — defaults to the saved brand's name
brandIdstringa brand id/name from list_brands to save the screens onto; omit to use the active brand