Skip to main content

Remix

One long video in, a set of shorts and drafted copy out. Remix watches the whole thing, finds the moments worth cutting, and writes the blog post and social posts to go with them. For webinars, it finds clips of the real speaker and builds a recap video.

Create​

POST /v1/remixes

Two sources. A video already in the workspace:

curl -X POST https://api.vidocu.ai/v1/remixes \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"videoId": "vid_abc123"}'

Or an external URL, which needs the duration since nothing has inspected the file yet:

-d '{"videoUrl": "https://example.com/talk.mp4", "durationSec": 2400, "title": "Q3 keynote"}'

Exactly one of videoId or videoUrl. Creating a remix analyzes nothing - it just sets it up.

402 if the workspace hasn't the balance for a video that long. The check happens here; the charge happens when analysis completes.

Webinar remixes​

Add a plan to make clips of the real speaker, in their own voice, instead of scripted shorts. Remix transcribes who said what, maps the chapters, and scores the moments that stand on their own.

curl -X POST https://api.vidocu.ai/v1/remixes \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"videoId": "vid_abc123",
"plan": {
"outputs": {
"clips": { "count": "auto", "length": "30to60", "tone": "marketing" },
"recap": { "targetSec": 120 },
"text": { "blog": true, "linkedin": true, "x": false, "quotes": true }
},
"focus": "the pricing Q&A",
"range": { "start": 180, "end": 3480 },
"cleanup": { "voice": true, "fillers": true, "longPauses": true }
}
}'
FieldValues
outputs.clipsVertical 9:16 clips. count: "auto" or 1-15. length: auto, lt30, 30to60, 60to90. tone: marketing or educational
outputs.recapA 16:9 highlights video. targetSec: 60, 120, 180 or 300
outputs.textWhich posts to draft
focusOptional topic to favour. Other standout moments are still picked
rangeOptional seconds of the source to use. At least a minute, at most 90 minutes
languageOptional spoken language code. Detected when left out
cleanupVoice cleanup, filler-word cuts and long-pause trims, applied on export

Choose at least one output. The source can be any length if range picks 90 minutes or less of it, and only the range is billed. The response carries "pipelineVersion": 2.

Analysis costs 3 credits per minute of the range.

Analyze​

POST /v1/remixes/:id/analyze

{ "status": "analyzing", "remixId": "...", "jobId": "..." }

Returns 202. This is the slow part - poll GET /v1/remixes/:id until status is ready.

A workspace runs one analysis at a time. If another is already running you get:

{ "status": "queued", "remixId": "..." }

That is not an error and needs no retry. The queued remix starts on its own when the running one finishes, oldest first.

Billed per minute of source video, when the analysis completes.

Read the result​

GET /v1/remixes/:id returns the full analysis once ready: the shorts it found with their timings, chapters, and drafted blog, LinkedIn and X copy.

GET /v1/remixes lists them, cursor-paginated and filterable by status and projectId. The list omits analysis - it is far too large to return per row.

Statuses: pending (created, not analyzed), queued, analyzing, ready, failed. When a remix fails, error says why and analysis can be run again.

While a webinar remix analyzes, analysisProgress reports where it is:

{ "message": "Finding the best moments", "percentage": 52, "at": "2026-10-18T19:47:58.000Z" }

Review moments​

A ready webinar remix holds analysis.speakers, analysis.chapters and analysis.moments. Each moment is a range of the source:

{
"id": "m4",
"start": 136.44,
"end": 161.62,
"title": "The REINS Act targets Washington bureaucracy",
"kind": "insight",
"speakerIds": ["spk_1"],
"score": { "total": 85, "hook": 82, "standalone": 85, "value": 88, "clarity": 86 },
"cuts": [{ "start": 150.2, "end": 150.6 }],
"status": "proposed",
"use": { "clip": true, "recap": true },
"origin": "ai"
}

cuts are the filler words and long pauses that are skipped when it plays. Times are seconds in the source video.

Update a moment​

PATCH /v1/remixes/:id/moments/:momentId

-d '{"status": "kept", "title": "Why the REINS Act matters", "end": 168}'

Any of status (proposed, kept, dropped), title, start, end, use, kind, cuts and hookText (the headline over the clip's first seconds; an empty string goes back to the title). A new start or end snaps to the nearest transcript line. Cuts already in the clip stay, and the newly covered part gets its own filler and pause cuts. Returns { "moment": ... }.

add and remove take a span of transcript in source seconds, { "start": 412.3, "end": 431 }:

  • add brings that text into the clip, from anywhere in the webinar. Text outside the clip widens it and skips what sits in between, so a clip can join two separate sections, such as the question that gives an answer its context. The clip can span at most 10 minutes from its first word to its last, skipped parts included.
  • remove takes that text out of the clip. At the start or end, the clip starts or ends at the next word it keeps.
-d '{"add": {"start": 412.3, "end": 431}}'

framing frames a clip by hand instead of automatically. Boxes are { x, y, w, h }, 0 to 1 of the source frame, and are fitted to the clip's shape around their centre:

framingThe clip shows
{"mode": "speaker", "box": {...}}That part of the frame, all the way through
{"mode": "screen", "screen": {...}, "camera": {...}}That part of a shared screen, with the camera box as a small card. Leave out camera for no card
{"mode": "stack", "top": {...}, "bottom": {...}}Two parts of the frame, one over the other, each filling half the clip. The speaker over the screen, or two people
{"mode": "whole"}The whole frame, with bars
{"mode": "auto"} or nullBack to automatic

A made clip's export row has shots: how it was framed automatically, in the same boxes, so you can start from there. Changing framing marks a made clip as changed.

Add a moment​

POST /v1/remixes/:id/moments with {"start": 612.4, "end": 655, "title": "Optional"}

Use analysis.subtitles to find the times. The range snaps to the transcript like a trim, and the new moment starts as kept. Returns 201 with { "moment": ... }.

Set the recap order​

PUT /v1/remixes/:id/recap

{
"items": [
{ "type": "title_card", "id": "t1", "text": "Where AI policy goes next", "durationSec": 2.5 },
{ "type": "moment", "momentId": "m7" },
{ "type": "moment", "momentId": "m10" }
]
}

Replaces the whole list. Title cards show for 1-6 seconds. Until you set it, recap is null and analysis.recapOrder holds the suggested order. Changing a moment's use.recap doesn't reorder the recap, so send the list you want.

These three return 409 on a remix made without a plan, or one that hasn't finished analyzing.

Style​

Send clipStyle or recapStyle with PATCH /v1/remixes/:id. Both are partial: what you send merges over what's saved.

{
"clipStyle": {
"ratio": "9:16",
"captions": { "enabled": true, "preset": "bold", "position": "bottom", "highlightColor": "#FACC15" },
"hook": { "enabled": true },
"endCard": { "enabled": true, "text": "Watch the full webinar" },
"logo": true
},
"recapStyle": { "captions": true, "logo": true }
}
FieldValues
clipStyle.ratio9:16, 4:5, 1:1 or 16:9. A 16:9 clip shows the whole webinar frame unless you set its framing
clipStyle.captions.presetbold, clean or boxed
clipStyle.captions.positionbottom (lower third) or middle
clipStyle.captions.highlightColorHex colour of the word being spoken
clipStyle.hook.enabledEach clip's hookText (or title) over its first seconds
clipStyle.endCardA closing line on screen for 2.5 seconds
logoYour Brand Kit logo. Free plans always show the Vidocu mark

The defaults are what's shown above, with the end card off. Clips already made keep their look until you make them again.

Update and delete​

PATCH /v1/remixes/:id changes the title, moves the remix to a project folder, or sets its style. Status, analysis and exports belong to the pipeline and can't be set - writing them by hand would desynchronise a running job.

DELETE /v1/remixes/:id is refused with 409 while analysis is running. Videos already exported from the remix are separate objects and are untouched.

Export​

POST /v1/remixes/:id/export

Text outputs come back immediately:

curl -X POST https://api.vidocu.ai/v1/remixes/rmx_123/export \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"outputType": "blog"}'
{ "exportId": "...", "status": "completed", "content": "# How we cut onboarding in half\n\n..." }

Video outputs start a render and return 202 with a job:

{ "exportId": "...", "jobId": "...", "status": "processing" }
outputTypeKindNotes
blogtextReturns Markdown
linkedintextvariantIndex picks which draft; defaults to the first
xtextThe thread, joined
clipsvideoWebinar remixes. Every kept clip, or the ones in momentIds
recapvideoWebinar remixes. The 16:9 recap in its order
shortvideoEarlier remixes. Needs shortId from the analysis
yt-trimvideoEarlier remixes. The trimmed cut

Each short or yt-trim export counts as one against the plan's export allowance regardless of length; 402 when that's exhausted. Poll GET /v1/remixes/:id/exports for a video export's URL.

Clips and the recap​

curl -X POST https://api.vidocu.ai/v1/remixes/rmx_123/export \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"outputType": "clips", "momentIds": ["m4", "m7"]}'
{
"status": "processing",
"started": [{ "exportId": "...", "momentId": "m4" }],
"unchanged": ["m7"],
"estimatedCredits": 18
}

Each clip is its own export row (outputType: "clip", outputId = the moment id); the recap is outputType: "recap". Rows carry progress (0-100) while they're made. Clips follow the speaker and come with the voice cleaned up when the plan asked for it.

When the speaker shares their screen or slides with their camera on, a clip splits in two, the way Reels and TikTok do: the speaker fills the top half and the screen the bottom half, with captions on the line between them. A small camera gets a shorter top part (down to 30% of the clip) so the speaker isn't blown up into a blur, and a tiny one shows as a small card over the screen. A shared screen zooms in on where things happen; a slide shows whole, so no word is cut off. Without a camera, the clip shows the busy part of the screen with captions below it. Two people on a call stack one over the other; with three, the one talking goes on top and the other two sit side by side below. With more, the clip follows whoever is talking. The recap shows shared screens as they were.

A clip already made from the same trims, cuts and style, or still being made, isn't made again. It's listed in unchanged and costs nothing. When nothing is left to make, the call returns 200 with "status": "completed".

Credits are checked before anything starts (402 when the balance is short) and charged when each video is ready, on what was made: 10 credits per output minute, plus 25 per minute of voice cleanup. Cleanup for a range is paid once, so a recap reusing a made clip doesn't pay for it again. A failed video costs nothing. The final charge is on each row as creditsCharged.

Regenerate the copy​

POST /v1/remixes/:id/regenerate with {"outputType": "blog" | "linkedin" | "x"}

Rewrites that output from the analyzed transcript and returns the updated analysis. It replaces the current draft, so don't call it on copy someone has edited.

1 credit per run. It doesn't count as an export.

Exports list​

GET /v1/remixes/:id/exports lists what has been produced - each with its output type, status and URL. Webinar clips and the recap also carry progress, durationSec and creditsCharged.

Errors​

StatusCodeCause
400validation_errorBoth or neither of videoId/videoUrl, or videoUrl without durationSec
402limit_exceededNot enough balance for a video that long
404not_foundNo such remix in this workspace
400validation_errorA plan with no outputs, or a range under a minute or over 90 minutes
404not_foundNo such moment in this remix
409conflictAlready analyzing, or deleting while analysis runs. Moment and recap edits on a remix without a plan, or before analysis finishes