Skip to main content
Glama
hermoso-ai

Hermoso

Official

Post-production edit

post_edit

Edit an existing video mechanically with ffmpeg operations (trim, speed, mute, audio, music, voiceover, text, watermark, join) to produce a new video.

Instructions

MECHANICAL post-production on an EXISTING video (URL): ordered primitives run by ffmpeg in seconds, ~2 credits flat, NO AI model, as a NEW video. Ops: a branded end card (adds its seconds), trim, speed (0.5-2x), mute (whole or a window), audio_gain (-20..+6 dB), fade_out, music (a bed UNDER the clip, its own sound kept and ducked under: omit track = a free library track picked by mood, no attribution; or track = an audio link: an upload_file URL, a find_sound link, a video post's sound; track 'generate' composes it, paid, ONLY when the user asks; start/end, db, replace), voiceover (text spoken OVER it, its sound ducked; ~2.5 words/s; voice female|male; +~1 credit), watermark (brand logo), grain (anti-AI), text (timed words in a native look: style 'tiktok-classic' default / 'clean-minimal' / 'note-style' or a textStyle; start/end), join (this video FOLLOWED BY clips[]: Library URLs, direct files or public post links, as one 1080x1920 video, loudness matched). Presets are shortcuts: text/watermark take any x/y, grain any amount, join any ffmpeg transition, a bridge any sound link. 'A viral hook, then our clip' = videoUrl: the hook's post link + [{op:'join', clips:[{url: ours}], bridge}], and it ALWAYS gets a bridge unless the user asks for a bare cut: {kind:'impact'} cuts the hook just before its payoff (found from the footage; cutAt overrides) and lands our clip on a punch-in and flash, with the payoff sound FROM THE HOOK ITSELF: its own audio carries across the cut, else one generated from its frames (up to 8 credits), else a neutral impact. {kind:'text', text, then?} only when the user asks for words over the cut. No voiceover bridge: have our clip's host say the connecting line. matchCut = where our clip starts. ANY OTHER EDIT, op or bridge (whip, zoom, freeze, wipe, split screen, generated shot) is edit_timeline: free keyframes, any size. NEVER generate_video/render_ad for these.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
opsYesthe ordered edit plan (max 6 ops)
accentNooverride the brand accent hex
domainNooverride the brand website
dryRunNotrue = return the exact credits this edit reserves and run nothing
videoUrlYesthe video to edit: a render / Library URL, a direct file, or a public post link
brandNameNooverride the workspace brand name

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.1.374
    • addedInput schema / properties / ops / items / properties / keepSound
      Added value: +{
      +  "type": "boolean"
      +}
    • changedInput schema / properties / ops / items / properties / op / enum
      Previous value: -[
      -  "trim",
      -  "speed",
      -  "mute",
      -  "audio_gain",
      -  "fade_out",
      -  "music",
      -  "append_card",
      -  "watermark",
      -  "grain",
      -  "text",
      -  "join"
      -]New value: +[
      +  "trim",
      +  "speed",
      +  "mute",
      +  "audio_gain",
      +  "fade_out",
      +  "music",
      +  "voiceover",
      +  "append_card",
      +  "watermark",
      +  "grain",
      +  "text",
      +  "join"
      +]
    • changedInput schema / properties / ops / items / properties / text / description
      Previous value: -"text: the words, verbatim"New value: +"text/voiceover: the words, verbatim"
    • addedInput schema / properties / ops / items / properties / voice
      Added value: +{
      +  "type": "string"
      +}
  2. Changed8 schema fields changedv0.1.366
    • changedInput schema / properties / ops / items / properties / db / description
      Previous value: -"audio_gain -20..+6 dB"New value: +"audio_gain -20..+6 dB / music: trim on its automatic level, -20..+12"
    • addedInput schema / properties / ops / items / properties / duck
      Added value: +{
      +  "anyOf": [
      +    {
      +      "const": "auto",
      +      "type": "string"
      +    },
      +    {
      +      "type": "boolean"
      +    }
      +  ],
      +  "description": "music: 'auto' default = dips while the clip's own sound plays"
      +}
    • addedInput schema / properties / ops / items / properties / fadeOut
      Added value: +{
      +  "description": "music: fade-out seconds 0-5",
      +  "type": "number"
      +}
    • addedInput schema / properties / ops / items / properties / from
      Added value: +{
      +  "description": "music: the second of the track to start from",
      +  "type": "number"
      +}
    • addedInput schema / properties / ops / items / properties / mood
      Added value: +{
      +  "description": "music: mood words for the library pick, or the brief for generated music",
      +  "type": "string"
      +}
    • changedInput schema / properties / ops / items / properties / op / enum
      Previous value: -[
      -  "trim",
      -  "speed",
      -  "mute",
      -  "audio_gain",
      -  "fade_out",
      -  "append_card",
      -  "watermark",
      -  "grain",
      -  "text",
      -  "join"
      -]New value: +[
      +  "trim",
      +  "speed",
      +  "mute",
      +  "audio_gain",
      +  "fade_out",
      +  "music",
      +  "append_card",
      +  "watermark",
      +  "grain",
      +  "text",
      +  "join"
      +]
    • addedInput schema / properties / ops / items / properties / replace
      Added value: +{
      +  "description": "music: true = replaces the clip's own sound",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / ops / items / properties / track
      Added value: +{
      +  "description": "music: omit = a library track by mood; a library track name; an audio link; 'generate' (paid, only on the user's ask)",
      +  "type": "string"
      +}
  3. Changed22 schema fields changedv0.1.320
    • addedInput schema / properties / dryRun
      Added value: +{
      +  "description": "true = return the exact credits this edit reserves and run nothing",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / ops / items / properties / background / description
      Previous value: -"append_card: card background — hex or a color name ('red', 'navy'…); the user's stated color always wins over the brand palette"New value: +"append_card: hex or a colour name; the user's colour beats the brand palette"
    • addedInput schema / properties / ops / items / properties / bridge / properties / sound / description
      Added value: +"'auto' default, 'own', 'impact', 'whoosh', 'none', or an audio URL (find_sound)"
    • removedInput schema / properties / ops / items / properties / bridge / properties / sound / enum
      Removed value: -[
      -  "auto",
      -  "own",
      -  "impact",
      -  "whoosh",
      -  "none"
      -]
    • changedInput schema / properties / ops / items / properties / card_html / description
      Previous value: -"append_card: your OWN full-frame card design as inline-styled HTML ({{logo}} inserts the real brand logo) — use when the standard layout cannot honor the request"New value: +"append_card: your OWN full-frame card as inline-styled HTML ({{logo}} = the brand logo)"
    • addedInput schema / properties / ops / items / properties / clips / items / properties / match
      Added value: +{}
    • addedInput schema / properties / ops / items / properties / clips / items / properties / reframe
      Added value: +{}
    • changedInput schema / properties / ops / items / properties / corner / description
      Previous value: -"watermark corner (default br)"New value: +"watermark corner (default br), or x/y"
    • changedInput schema / properties / ops / items / properties / headline / description
      Previous value: -"append_card: big line (defaults to the brand name)"New value: +"append_card: big line (default: brand name)"
    • addedInput schema / properties / ops / items / properties / intensity / anyOf
      Added value: +[
      +  {
      +    "enum": [
      +      "default",
      +      "strong"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "number"
      +  }
      +]
    • changedInput schema / properties / ops / items / properties / intensity / description
      Previous value: -"grain look"New value: +"grain: or 0-1 (default 0.25)"
    • removedInput schema / properties / ops / items / properties / intensity / enum
      Removed value: -[
      -  "default",
      -  "strong"
      -]
    • removedInput schema / properties / ops / items / properties / intensity / type
      Removed value: -"string"
    • addedInput schema / properties / ops / items / properties / match
      Added value: +{
      +  "description": "join: seam match, 'auto' default | 'off' | {grade,level,grain,blur,strength}"
      +}
    • changedInput schema / properties / ops / items / properties / position / description
      Previous value: -"text: where"New value: +"text: where, or x/y"
    • addedInput schema / properties / ops / items / properties / reframe
      Added value: +{
      +  "description": "join: shot change at a same-framing stitch, 'auto' | 'off' | step 1.1-1.5"
      +}
    • changedInput schema / properties / ops / items / properties / seconds / description
      Previous value: -"fade_out 0.3-3s / append_card 2-5s / crossfade 0.2-1.5s"New value: +"fade_out 0.3-3s / append_card 2-5s / transition 0.2-1.5s"
    • changedInput schema / properties / ops / items / properties / sub / description
      Previous value: -"append_card: the pill line (defaults to the website) / text: a smaller second line"New value: +"append_card: pill line (default: website) / text: a second, smaller line"
    • changedInput schema / properties / ops / items / properties / transition / description
      Previous value: -"join"New value: +"join: 'cut' default, 'crossfade', or any ffmpeg xfade name (wipeleft…)"
    • removedInput schema / properties / ops / items / properties / transition / enum
      Removed value: -[
      -  "cut",
      -  "crossfade"
      -]
    • addedInput schema / properties / ops / items / properties / x
      Added value: +{
      +  "description": "text/watermark centre: 0-1 of frame, or px",
      +  "type": "number"
      +}
    • addedInput schema / properties / ops / items / properties / y
      Added value: +{
      +  "type": "number"
      +}
  4. Changed2 schema fields changedv0.1.285
    • addedInput schema / properties / ops / items / properties / bridge
      Added value: +{
      +  "description": "join: connects the hook to the first clip",
      +  "properties": {
      +    "cutAt": {
      +      "description": "omit: found from the footage",
      +      "type": "number"
      +    },
      +    "flash": {
      +      "type": "boolean"
      +    },
      +    "kind": {
      +      "enum": [
      +        "impact",
      +        "text"
      +      ],
      +      "type": "string"
      +    },
      +    "matchCut": {
      +      "type": "number"
      +    },
      +    "shake": {
      +      "type": "boolean"
      +    },
      +    "sound": {
      +      "enum": [
      +        "auto",
      +        "own",
      +        "impact",
      +        "whoosh",
      +        "none"
      +      ],
      +      "type": "string"
      +    },
      +    "text": {
      +      "type": "string"
      +    },
      +    "then": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "kind"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / ops / items / properties / textStyle
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "additionalProperties": {},
      +      "properties": {},
      +      "type": "object"
      +    }
      +  ]
      +}
  5. Changed11 schema fields changedv0.1.281
    • addedInput schema / properties / ops / items / properties / clips
      Added value: +{
      +  "description": "join: the clips after this video",
      +  "items": {
      +    "properties": {
      +      "end": {
      +        "type": "number"
      +      },
      +      "start": {
      +        "type": "number"
      +      },
      +      "url": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "url"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / properties / ops / items / properties / end / description
      Previous value: -"trim/mute window end (s)"New value: +"trim/mute/text window end (s)"
    • changedInput schema / properties / ops / items / properties / op / enum
      Previous value: -[
      -  "trim",
      -  "speed",
      -  "mute",
      -  "audio_gain",
      -  "fade_out",
      -  "append_card",
      -  "watermark",
      -  "grain"
      -]New value: +[
      +  "trim",
      +  "speed",
      +  "mute",
      +  "audio_gain",
      +  "fade_out",
      +  "append_card",
      +  "watermark",
      +  "grain",
      +  "text",
      +  "join"
      +]
    • addedInput schema / properties / ops / items / properties / position
      Added value: +{
      +  "description": "text: where",
      +  "enum": [
      +    "top",
      +    "center",
      +    "lower",
      +    "bottom"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / ops / items / properties / seconds / description
      Previous value: -"fade_out 0.3-3s / append_card 2-5s"New value: +"fade_out 0.3-3s / append_card 2-5s / crossfade 0.2-1.5s"
    • changedInput schema / properties / ops / items / properties / start / description
      Previous value: -"trim/mute window start (s)"New value: +"trim/mute/text window start (s)"
    • addedInput schema / properties / ops / items / properties / style
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "additionalProperties": {},
      +      "properties": {},
      +      "type": "object"
      +    }
      +  ],
      +  "description": "text: a look name or a textStyle"
      +}
    • changedInput schema / properties / ops / items / properties / sub / description
      Previous value: -"append_card: the pill line (defaults to the brand website)"New value: +"append_card: the pill line (defaults to the website) / text: a smaller second line"
    • addedInput schema / properties / ops / items / properties / text
      Added value: +{
      +  "description": "text: the words, verbatim",
      +  "type": "string"
      +}
    • addedInput schema / properties / ops / items / properties / transition
      Added value: +{
      +  "description": "join",
      +  "enum": [
      +    "cut",
      +    "crossfade"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / videoUrl / description
      Previous value: -"the served URL of the video to edit"New value: +"the video to edit: a render / Library URL, a direct file, or a public post link"
  6. Changed1 schema field changedv0.1.161
    • changedOutput schema / (root)
      Previous value: -{
      -  "$schema": "http://json-schema.org/draft-07/schema#",
      -  "additionalProperties": false,
      -  "properties": {
      -    "jobId": {
      -      "description": "the render job id — poll get_job with this id to resume or inspect",
      -      "type": "string"
      -    },
      -    "model": {
      -      "anyOf": [
      -        {
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "description": "the product-facing label of the model that rendered it"
      -    },
      -    "raw": {
      -      "description": "the raw job result payload (e.g. images[] for carousel template ads)"
      -    },
      -    "stillRendering": {
      -      "description": "true when the render is still in progress — keep polling get_job with jobId",
      -      "type": "boolean"
      -    },
      -    "url": {
      -      "anyOf": [
      -        {
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "description": "the served URL of the finished media (absent/null while still rendering)"
      -    }
      -  },
      -  "type": "object"
      -}New value: +null
  7. Addedv0.1.15

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations (which only say non-readonly, non-destructive, open-world): it discloses that output is a NEW video, that cost is ~2 credits flat with specific surcharges (voiceover +~1, generated impact sound up to 8), that music ducks under the clip's own audio, and the full bridge/cut semantics. This is exactly the kind of context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, cost, and op list before the complex bridge rules, and for a 12-op tool with nested bridge/clip objects most sentences carry genuine routing information. However, the heavy ALL-CAPS and comma-spliced clauses make it dense and hard to parse, costing some readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers cost, safety behavior, alternatives, and brand overrides thoroughly, which is strong for a complex tool. With no output schema, however, it never describes the return value or job/status shape an agent would receive, leaving that one gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real semantic value the schema lacks — the 'join' hook pattern, bridge auto-insertion rules, matchCut meaning, and preset shortcuts ('text/watermark take any x/y, grain any amount'). It clarifies how ops interact rather than merely restating field names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource — 'MECHANICAL post-production on an EXISTING video (URL)' — and explicitly distinguishes itself from edit_timeline, generate_video, and render_ad by name. An agent can route between these siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use and when-not: 'ANY OTHER EDIT, op or bridge (whip, zoom, freeze...) is edit_timeline' and 'NEVER generate_video/render_ad for these.' It also gates sub-features by user intent (track 'generate' only when the user asks; text bridge only when words are requested).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools