# AwesomeVideo > Browser video editor with styled, animated captions, plus a prepaid API and MCP server for agents. - API docs for agents: https://api.awesomevideoeditor.com/llms.txt (everything in one file: https://api.awesomevideoeditor.com/llms-full.txt or https://awesomevideoeditor.com/llms-full.txt) - OpenAPI: https://api.awesomevideoeditor.com/openapi.json - MCP (Streamable HTTP): https://api.awesomevideoeditor.com/mcp (server card: https://api.awesomevideoeditor.com/.well-known/mcp.json) - MCP with OAuth 2.1 (Claude, ChatGPT, other OAuth clients): https://api.awesomevideoeditor.com/mcp/oauth (discovery: https://api.awesomevideoeditor.com/.well-known/oauth-authorization-server) - Pricing: https://awesomevideoeditor.com/pricing (live JSON: https://api.awesomevideoeditor.com/v1/pricing) - Account and API keys: https://awesomevideoeditor.com/account - Free subtitle converters (in the browser, no upload, no key): https://awesomevideoeditor.com/tools/vtt-to-srt (WebVTT to SRT), https://awesomevideoeditor.com/tools/srt-to-vtt (SRT to WebVTT), https://awesomevideoeditor.com/tools/srt-to-txt (SRT or VTT to a plain-text transcript); index: https://awesomevideoeditor.com/tools Subtitles in one call: MCP `caption_video` (REST POST https://api.awesomevideoeditor.com/v1/captions) takes a public link (`sourceUrl`: direct file, chat attachment, Google Drive, Dropbox) or an uploaded `fileId`, transcribes, optionally translates (`translateTo`), burns, and returns the MP4 plus SRT/VTT. `platform` and `review: true` (link first, burn charged on approval) work here too. 5 credits per minute (7 with translation), the sum of the steps. YouTube links are not downloaded; upload the file instead. `import_url` (free) turns a public link into a `fileId`. Files up to 2048 MB: free resumable multipart upload, MCP `create_multipart_upload` (REST POST https://api.awesomevideoeditor.com/v1/uploads/multipart) returns one PUT url per part; `get_upload_status` lists missing parts after an interruption; `complete_upload` assembles it (walkthrough in llms-full.txt). Every job view has `step`, `progress` (0-100, burn uses real ffmpeg progress), `eta_seconds`, `estimatedCompletionAt`, and `pollAfterSeconds`; a caption_video job that failed after transcribing can be resumed with `resume_job` (REST POST https://api.awesomevideoeditor.com/v1/jobs/{id}/resume), which reuses the transcript and charges only the remaining steps. Platform safe zones: pass `platform` (tiktok, instagram_reels, youtube_shorts, facebook_reels, snapchat_spotlight, linkedin, youtube, x; aliases reels, shorts, instagram...) to burn_captions, shorts, preview, or prepare_client_burn so captions avoid that app's buttons and text. Same price. GET https://api.awesomevideoeditor.com/v1/platforms (free, no key; MCP list_platforms) lists them with margins. Caption autoFit (default on): size, words per caption (4 on 9:16, 5 on 1:1, 7 on 16:9), and a default safe zone (9:16 bottom 35%/top 15%/left 8%/right 15%, clear of TikTok, Reels and Shorts UI; 1:1 bottom 12%; 16:9 bottom 7%) follow the video shape, so a preset reads the same at 720p and 1080p. An explicit `platform` wins. Pass `autoFit: false` to burn_captions, caption_video, preview, shorts, prepare_client_burn, or request_review for the preset's exact fixed pixel sizes. Same price. The web editor applies the identical rule. Caption forms (style fields, web and server identical): `maxWordsPerCaption` 1-8 (1 = one big word at a time) always wins over autoFit's words cap. `activeWordReflow: true` stops a scaled active word from overlapping its neighbours; `wordEntrance` bounce/slide-up/fade animates each word when spoken. `positionMode` cycle (top/middle/bottom by caption) or keyword (`positionKeywords` → `keywordPosition`) moves captions inside the safe zone. `captionLayout: "stacked"` stacks one word per line with a bigger hero word (`posterHeroScale`). `faceAvoid: true` moves captions off detected faces; the burn result returns `faceAvoid.faceLayout` to store as `style.faceLayout`. Dub voices: GET https://api.awesomevideoeditor.com/v1/voices (free, no key; MCP list_voices) lists every voice with a short MP3 sample; pass its id as `voice` to dub or plan. Human review: after transcribe, `request_review` (MCP) or POST /v1/reviews returns a private web-editor link (no login, up to 7 days). The person edits and approves; only then the burn runs and is charged. With `webhookUrl`/`notifyEmail` you get signed `review.approved`, `review.rejected` (with note) and `review.expired` events, once each. Saved glossary (`save_glossary`, /v1/glossary, free) fixes brand names and slang in every transcription. Long video to short clips: MCP `create_clips` (REST POST https://api.awesomevideoeditor.com/v1/clips) transcribes, lets an LLM pick 1-10 self-contained moments (default 3, 15-60 s, snapped to sentence boundaries), and returns each as an MP4 (9:16 crop that follows the speaker by default, `reframe` center or none) with optional burned captions in any preset, plus title, hook, reason and score per clip. Price: 1 credit per source minute (transcription) + 1 per 10 source minutes + 3 per output minute; a 30-minute video with 3 clips is at most 42 credits. Custom presets: agents can design and save their own full caption style (free). MCP `save_custom_preset` (REST POST https://api.awesomevideoeditor.com/v1/custom-presets) takes `style` (the same JSON `list_presets` returns) or `basePreset` + `overrides`, validates it (422 `invalid_style` lists the bad fields; fonts limited to the bundled Inter, Poppins, Oswald, Roboto, Anton, Bebas Neue, Playfair Display, Caveat, IBM Plex Mono), and returns `custom:cp_...` to pass as `preset` to burn_captions, caption_video, preview, shorts, or prepare_client_burn. Up to 50 per key or account. `submit_custom_preset` proposes one for the public community gallery; it appears in `list_presets` only after a human moderator approves it. Built-in caption presets (28; pass as `preset`, e.g. `builtin:beast-glow`): clarity, neon-glow, highlight, hormozi-style, mrbeast-style, sleek-caps, epic-lines, bubble-talk, power-play, sharp-notes, retro-glow, tiktok-vertical, karaoke, pop-words, frosted, editorial, handwritten, terminal, color-burst, iman-lowercase, beast-glow, signature-gold, beast-one-word, hormozi-pop, poster-hero, bounce-chunks, zone-jumper, podcast-karaoke. New: `iman-lowercase` (clean lowercase Inter, the spoken word turns bold), `beast-glow` (white Bebas Neue caps, black outline, green glow, the spoken word in neon green), `signature-gold` (gold Caveat script, centered, the spoken word in pale cream). Caption-form presets: `beast-one-word` (one giant Anton word at a time, bounce entrance, active word yellow), `hormozi-pop` (3 Poppins caps words, the active word grows green and reflows its neighbours), `poster-hero` (stacked Anton poster, the active word is the big orange hero line), `bounce-chunks` (white Inter with black outline, 3 words, each bounces in), `zone-jumper` (Oswald caps chunks alternating center and bottom, active word sky blue), `podcast-karaoke` (left-aligned white Inter in 2-3 full lines, words light up as spoken). Per-call style (no saved preset needed): caption_video, burn_captions, preview, shorts, create_clips, remove_silences (with burnCaptions), translate with burn, batch items, request_review and prepare_client_burn (REST: the same body fields on POST /v1/captions, /v1/captions/burn, /v1/captions/preview, /v1/shorts, /v1/clips, /v1/trim, /v1/translate, /v1/batch, /v1/reviews, /v1/captions/prepare) accept `styleOverrides` (style fields deep-merged onto the preset, null removes a field, validated like custom presets with bundled fonts only; 422 `invalid_style` lists bad fields) and `faceAvoid: true` (shortcut for styleOverrides.faceAvoid: captions move off faces, sampled at 2 fps; the result returns `faceAvoid.faceLayout`). Same price. Example: `{"sourceUrl": "https://example.com/talk.mp4", "preset": "builtin:hormozi-pop", "faceAvoid": true, "styleOverrides": {"fontSize": 72, "maxWordsPerCaption": 2, "wordEntrance": "bounce", "wordStateStyles": {"active": {"color": "#FACC15"}}}}`. Caption-form fields: maxWordsPerCaption (1-N words per caption), activeWordReflow (grown active word pushes neighbours), wordEntrance (bounce, slide-up, fade) + wordEntranceDuration, positionMode (cycle with positionCycle, keyword with positionKeywords + keywordPosition), captionLayout "stacked" + posterHeroScale, faceAvoid. Preview before ordering, free: MCP `style_preview` (REST POST https://api.awesomevideoeditor.com/v1/captions/style-preview) never charges and never transcribes. It takes the same look fields as `caption_video` (sourceUrl/fileId, preset or presets (up to 12; default 6 for the video shape), language, translateTo, brandPresetId, styleOverrides, faceAvoid, highlightWords, highlightColor, platform, autoFit) plus preview-only `text` (sample phrase, max 80 chars), `fullText`, `atSeconds` (one second or up to 3, one sheet row each; default a frame with a face, else the middle) and `transcriptionJobId`/`subtitles` (show the real caption at that second). Each preset is rendered exactly like the burn: same output size, autoFit sizing, words per caption, safe zone, face avoidance and engine, on the real frame. If the text is longer than one caption you see the chunk on screen at that second (`truncated: true`), like the burn; `fullText: true` shows every line but no longer matches a burn. Response: `sheetUrl` (labeled contact sheet), `presets[].frames[]` (url per second) and `presets[].captionVideoArgs`: pass it unchanged to `caption_video` (or POST /v1/captions) to get what you saw. Limits: 30 sheets/hour and 200/day per key (up to 3 seconds = one sheet); 429 `rate_limited` with `retryAfterSeconds`; identical repeats come from cache and do not count. A brand logo is not drawn in the preview. Preview then order (example): 1. `style_preview` {"sourceUrl":"https://example.com/talk.mp4","presets":["hormozi-pop","podcast-karaoke","clarity"],"language":"es","text":"Así se verán tus subtítulos","platform":"youtube","faceAvoid":true,"atSeconds":[5,20]} 2. Show `sheetUrl`; the person picks "podcast-karaoke". 3. `caption_video` with that preset's `captionVideoArgs`: {"sourceUrl":"https://example.com/talk.mp4","preset":"podcast-karaoke","language":"es","platform":"youtube","faceAvoid":true} Audio-only input (podcast, voice note: mp3, m4a, wav, ...): `caption_video` and `burn_captions` (POST https://api.awesomevideoeditor.com/v1/captions, /v1/captions/burn) return an MP4 with one of ten editorial podcast designs plus the captions, drawn on the server by the web editor's own canvas code (same frames as exporting the audio in the editor). Same price as a video: 5 credits/min caption, 4 burn. `style_preview` with `audioVisual` is free. Catalog with names, descriptions, fields, recommended caption presets and preview images: GET https://api.awesomevideoeditor.com/v1/audio-visuals (MCP `list_audio_visuals`), free, no key. Designs (`audioVisual.variant`, default `editorial-cover`): - `swiss-grid` (Swiss grid, light): International-style poster: a huge episode numeral on a six-column grid, one red hairline tracing the last 1.6 s of voice, progress rule and timecode. Fields: showName, episode, speaker. Empty fields: No episode: the numeral becomes the running timecode. No show/speaker: those labels are omitted. - `braun-radio` (Braun radio, light): Dieter Rams-style radio: tuning scale with an orange needle that follows the voice, perforated grille, two knobs (voice level, elapsed time). Fields: showName, episode, speaker. Empty fields: Labels are omitted; the radio itself carries the design. - `riso` (Riso print, light): Two-ink risograph: halftone discs in fluoro pink and blue overprint and breathe with the voice; misregistered type on paper tooth. Fields: showName, episode, speaker. Empty fields: No show name: the big title reads PODCAST. - `editorial-cover` (Editorial cover, light): Magazine cover: serif masthead and issue line; the sentence is set as a pull-quote word by word, with a hairline under the spoken word that thickens with the voice. Fields: showName, episode, speaker. Empty fields: No show name: the masthead reads Podcast. No speaker: the byline is omitted. - `bauhaus` (Bauhaus, light): Circle, square and half-disc on a grid; each answers the voice with its own small delay. Heavy lowercase type. Fields: showName, episode, speaker. Empty fields: The type stack is omitted; the composition stands alone. - `continuous-line` (Continuous line, light): One pen line writes the voice across ruled rows, back and forth so it never lifts; a nib dot marks the tip. Fields: showName, episode, speaker. Empty fields: Labels are omitted. - `vinyl` (Vinyl, dark): Top-down turntable: matte record turning at 33 rpm, cover art on the label, a light sheen that brightens with the voice, tonearm moving with progress. Fields: showName, episode, speaker, coverSrc. Empty fields: No cover: a plain label in the ink colour with the show name (or nothing). - `type-wave` (Type as waveform, dark): The captions are the visual: each word is set at the weight of its own loudness (Inter 200-900), with a live weight scale. Fields: showName, episode, speaker. Empty fields: Labels are omitted. In preset mode the show name (or PODCAST) breathes in weight instead. - `duotone-portrait` (Duotone portrait, light): Cover art or host photo in two inks, framed by a hairline that carries the voice around its edge; heavy caps with a marker block on the spoken word. Fields: showName, episode, speaker, coverSrc. Empty fields: No cover: a two-ink gradient field with the show's initials. - `ma` (Ma, light): Japanese restraint: one sumi ink dot on washi that breathes, slow rings on loud syllables, a vermilion seal and a vertical label. Fields: showName, episode, speaker. Empty fields: No show name: the seal is a plain vermilion square. `audioVisual` fields (all optional): - `showName` (string, max 60), `episode` (string or number, max 12), `speaker` (string, max 60): printed by the design; empty ones are left out. - `coverImageUrl` (public https) or `coverFileId` (from `create_upload`): PNG/JPEG/WebP up to 5 MB, fetched before any charge; used by vinyl (record label) and duotone-portrait (two-ink portrait). Other designs ignore it with a warning. - `background` (paper), `accent`, `ink`: #rgb or #rrggbb. Default: the design's palette. Changing the paper picks a contrasting ink automatically unless `ink` is set. - `captionMode`: `integrated` (default) = the design sets each sentence itself, word by word; the caption preset is not drawn. `preset` = your caption preset draws and the design keeps its caption band clear. - `contrastGuard` (default true, preset mode): a preset whose text colour is too close to the paper (white text on a light design) switches to the design's ink without stroke/shadow. Light designs read best with Editorial, Sharp Notes or Frosted; dark designs (vinyl, type-wave) with Clarity, Iman Lowercase or Podcast Karaoke. - `aspect` 9:16 (default, or from `platform`) | 16:9 | 1:1 | 4:5, or `width`+`height` (128-3840); `enabled` false = paper + captions only; `overlays` up to 8 image/text items. - Retired visualizer ids still work and render their replacement, with a `warnings` entry on the job: bars→swiss-grid, ribbon→continuous-line, rings→ma, spectrogram→riso, skyline→bauhaus, silkline→type-wave, ivory→editorial-cover, halo→vinyl, needle→braun-radio, mono→duotone-portrait. Their `presetId`/`config` fields are ignored (warning), gradient backgrounds fall back to the design's paper. - Errors: unknown variant/field, bad colour, too-long text, unreachable or non-image cover: 422 `invalid_audio_visual`, `charged: false`. curl: curl -X POST https://api.awesomevideoeditor.com/v1/captions -H "Authorization: Bearer $AV_KEY" -H "Content-Type: application/json" -d '{"sourceUrl":"https://example.com/episode.mp3","preset":"clarity","platform":"tiktok","audioVisual":{"variant":"editorial-cover","showName":"Field Notes","episode":"12","speaker":"Alex Doe"}}' MCP: caption_video {"sourceUrl":"https://example.com/episode.mp3","preset":"clarity","audioVisual":{"variant":"vinyl","showName":"Field Notes","coverImageUrl":"https://example.com/cover.jpg"}} Python: requests.post("https://api.awesomevideoeditor.com/v1/captions", headers={"Authorization": f"Bearer {key}"}, json={"fileId": file_id, "preset": "editorial", "audioVisual": {"variant": "riso", "captionMode": "preset", "showName": "Field Notes"}}).json() A brand logo is drawn bottom right. preview, shorts and create_clips on audio return 422 `audio_only_input`, not charged. Long audio renders in 2-minute pieces that a retry or `resume_job` reuses; drawing takes about 0.2-0.4x the audio length on one vCPU; on staging a 50 s episode finished in 1-2.5 minutes end to end, transcription included. Style reference: `get_style_reference` (MCP) / GET https://api.awesomevideoeditor.com/v1/style-reference (free, no key) lists every style field the web editor has, with type, values/range and examples. Word highlights: `wordHighlights: {rules: [{id, enabled, color, backgroundColor?, words?, minLength?}], customLists?: [{id, name, enabled, color, backgroundColor?, words}]}`; rule ids numbers (digits, %), custom (its words list), acronym (ALL CAPS), hashtag (# and @), long (longer than minLength), person/orgloc (web editor NLP only; use custom words for server burns). Keywords in an accent color: `{"rules":[{"id":"custom","enabled":true,"color":"#FACC15","words":["gratis","AwesomeVideo"]}]}` or the shortcut `highlightWords: ["gratis","AwesomeVideo"], highlightColor: "#FACC15"` on any burn tool. Numbers: `{"rules":[{"id":"numbers","enabled":true,"color":"#F59E0B"}]}`. Marker background: `{"rules":[{"id":"custom","enabled":true,"color":"#000000","backgroundColor":"#FACC15","words":["oferta"]}]}`. Smart emphasis: `smartEmphasis: {enabled: true, target: "auto", style: "color"|"pop"|"pill", intensity: "low"|"med"|"high", color: "#A855F7"}` (server burns support target auto; verbs/nouns/numbers/custom are web-only, use wordHighlights instead). Word states: `wordStateStyles: {"active": {"color": "#FACC15", "scaleBy": 1.2}, "upcoming": {"opacity": 0.5}}` with revealMode word-by-word. Color cycle: `segmentColorCycle: {"enabled": true, "segmentSize": 2, "mode": "fixed", "variants": [{"text": "#FFFFFF"}, {"text": "#FACC15"}]}`. Free price checks: `quoteOnly: true` returns {costCents, breakdown, charged:false} without starting a job on create_clips (POST /v1/clips, needs durationSeconds), remove_silences (POST /v1/trim, durationSeconds; upper bound since it bills kept minutes) and generate_metadata (POST /v1/metadata; durationSeconds only when passing media without a transcript). Publishing metadata: MCP `generate_metadata` (REST POST https://api.awesomevideoeditor.com/v1/metadata) writes titles, a description, hashtags and YouTube chapters from what is said. Pass `transcriptionJobId` (any finished transcribe, caption_video, remove_silences or translate job) or `subtitles`, else `fileId`/`mediaUrl` (transcribed first, 1 credit/min). `platforms`: youtube (default), shorts, tiktok, instagram; 1 credit each. Options: language, titleCount 1-10, context (500 chars). `list_presets` returns each style JSON. Agents can start without a human: POST https://api.awesomevideoeditor.com/v1/keys/anonymous returns a key with 0 paid credits (plus 10 free welcome credits for caption_video/transcribe while the trial runs, with a solved GET /v1/keys/challenge proof-of-work); paid calls answer 402 with a $5 checkout link for that key. Before a job, POST /v1/plan (free, no key) prices the whole pipeline and lists any limit violations; paid calls over a limit answer 422 limit_exceeded before charging. ## Credits 1 credit = 1 cent. - `pack_5`: $5 one-time = 500 credits. Never expire. - `pack_20`: $20 one-time = 2,200 credits. Never expire. - `pack_50`: $50 one-time = 6,000 credits. Never expire. - `creator`: $9/month = 1,200 credits/month, or $90/year (10× monthly, 12 grants). - `pro`: $29/month = 4,500 credits/month, or $290/year (10× monthly, 12 grants). Includes the account webhook. - `scale`: $99/month = 18,000 credits/month, or $990/year (10× monthly, 12 grants). Includes the account webhook. Credit policy: pack credits never expire. Monthly plan credits roll over through the end of the following month. `plan`, `quote`, and `list_voices` are free. A paid call over a limit answers 422 before charging (`charged: false`). A server job that fails after charging is refunded automatically to the same balance. Rate limits: 429 `rate_limited` never charges; wait the `Retry-After` header (also `retryAfterSeconds` in the JSON) before retrying.