extract_vertical_clip
ActiveTool of Weftly
Cut a 9:16 vertical clip from any prior video job (find_clips, summarize, or video transcribe), suitable for direct upload to TikTok, Instagram Reels, or YouTube Shorts. Default output is 1080×1920 H.264 / AAC `.mp4` with center-cropped framing; audio loudness-normalized to -14 LUFS / -1.5 dBTP for short-form social. Single-segment only; clip duration must be between 1 and 90 seconds (Instagram Reels max). Operates on a parent job — possessing the parent `source_job_id` is the capability, no upload step. Two-call flow: (1) call with `source_job_id` + `start` + `end` (in source seconds) to receive {job_id, payment_challenge}; (2) pay via MPP and call with `job_id` + `payment_credential` to start processing. Poll get_job_status(job_id) for completion; output is role `clip-vertical-video` (the `.mp4`). Flat price: $0.50 per clip. Payment: pay by credit card via the Stripe Checkout link (open the returned `payment_url` in any browser) or Tempo USDC via mppx. Optional `profile` parameter selects the encoding profile (default `tiktok-primary`). Allowed values: `tiktok-primary` (1080×1920, fast preset, CRF 22), `tiktok-primary-720p` (720×1280, CBR 3 Mbps — half-resolution mobile-optimized, ~40% faster wall time), `instagram-reels` (1080×1920, slow preset, CBR 4 Mbps), `instagram-stories` (same encode shape as instagram-reels). All four profiles loudness-normalize identically. Optional `subject` parameter controls reframing (default `center`, preserves today's behavior): `auto` locks onto the longest-tracked face from the parent's subjects-sidecar (or runs inline detection if the parent has none); `subject_id` (with `subject_id` param naming a face_N from the sidecar) locks onto a specific subject; `follow` switches crop between active speakers across the clip using the sidecar's active_speaker_timeline; `manual` accepts caller-supplied framing via `subject_box: {x, y, w, h}` (source pixels) or `subject_x_offset` (direct crop x). Sidecar shape at /.well-known/weftly-subjects-v1.schema.json. auto/subject_id/follow fall back to center if detection or sidecar resolution fails — the paid job always delivers a clip. Source must be a horizontal video (wider than 9:16) — already-vertical or square sources are rejected. Source must still be in storage (72h TTL for find_clips parents, 24h elsewhere — check `expires_at` from get_job_status on the parent). Pair with `find_clips` ($2.00/video) to pick a moment first, then call this to get a download-ready vertical mp4 in under 5 minutes. Multiple extract_vertical_clip calls against one parent are independent paid jobs. Failed jobs auto-refund.
Parameters schema
{
"type": "object",
"properties": {
"end": {
"type": "number",
"minimum": 0,
"description": "Source-relative end time in seconds (must be > start, and end - start ∈ [1, 90]). Required on the first call."
},
"start": {
"type": "number",
"minimum": 0,
"description": "Source-relative start time in seconds. Required on the first call."
},
"t_ref": {
"type": "number",
"minimum": 0,
"description": "For subject=\"manual\" with subject_box — source-seconds timestamp the box applies to. Informational in v1."
},
"title": {
"type": "string",
"maxLength": 200,
"description": "Optional title for the assembled clip. Surfaces in get_job_status and download filenames; doesn't affect the cut itself."
},
"job_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Job ID returned from a previous extract_vertical_clip call. Include along with payment_credential to confirm payment and trigger processing. Also include alone to recover the current state."
},
"profile": {
"enum": [
"tiktok-primary",
"tiktok-primary-720p",
"instagram-reels",
"instagram-stories"
],
"type": "string",
"description": "Optional encoding profile. Default: tiktok-primary (1080×1920 H.264 fast preset, CRF 22, 6 Mbps cap). tiktok-primary-720p: 720×1280, CBR 3 Mbps — half-resolution mobile-optimized, ~40% faster wall time. instagram-reels: 1080×1920 H.264 slow preset, CBR 4 Mbps. instagram-stories: same encode shape as instagram-reels. All four apply loudness normalization to -14 LUFS / -1.5 dBTP."
},
"subject": {
"enum": [
"center",
"manual",
"auto",
"subject_id",
"follow"
],
"type": "string",
"description": "Optional reframing strategy. Default: \"center\" (hardcoded center crop, today's behavior). \"auto\": lock onto the longest-tracked face from the parent find_clips job's subjects-sidecar (or run inline detection if no sidecar). \"subject_id\": lock onto a specific face named in the sidecar (pass subject_id). \"follow\": switch crop between active speakers across the clip using the sidecar's active_speaker_timeline (per-segment encode + concat). \"manual\": caller specifies the subject (pass subject_box or subject_x_offset). See /.well-known/weftly-subjects-v1.schema.json. auto/subject_id/follow fall back to center if detection fails — the paid job always delivers a clip."
},
"subject_id": {
"type": "string",
"maxLength": 64,
"description": "Required when subject=\"subject_id\". Subject id from the parent's subjects-sidecar (e.g. \"face_0\")."
},
"subject_box": {
"type": "object",
"required": [
"x",
"y",
"w",
"h"
],
"properties": {
"h": {
"type": "number",
"exclusiveMinimum": 0
},
"w": {
"type": "number",
"exclusiveMinimum": 0
},
"x": {
"type": "number",
"minimum": 0
},
"y": {
"type": "number",
"minimum": 0
}
},
"description": "For subject=\"manual\" — bounding box of the subject in source pixels. Crop centers on the box center.",
"additionalProperties": false
},
"source_job_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Job ID of any prior video job (find_clips, summarize, or video transcribe). Possessing this id is the capability — extract_vertical_clip is not session-bound, so a user can come back from a different session within the parent's TTL and still extract. Required on the first call."
},
"subject_x_offset": {
"type": "number",
"minimum": 0,
"description": "For subject=\"manual\" — direct crop x-offset in source pixels (alternative to subject_box)."
},
"payment_credential": {
"type": "string",
"description": "MPP payment credential (full Authorization header value, e.g. \"Payment eyJ...\"). extract_vertical_clip accepts Tempo USDC and Stripe SPT — see the challenge's WWW-Authenticate header or /.well-known/mpp.json for the supported methods. Include with job_id after paying the challenge to start processing."
}
},
"additionalProperties": false
}No endpoints wrapped at confidence ≥ 0.70.
Parent server
Weftly
https://github.com/woven-record-media/weftly-monorepo
1/7 registries