Kolbo.AIKolbo.AI Docs
Developer API

Video-to-Video

Restyle and transform existing videos using AI with the Kolbo API.

Restyle and transform existing videos using AI. Provide a source video and a text prompt describing the desired transformation, and Kolbo generates a new video with the applied style or changes.

Smart Select (recommended): Omit the model field and Kolbo automatically picks the best model for your prompt. This is the default and recommended approach for most use cases.

Model identifiers are Kolbo-specific. Never hardcode model identifiers — always fetch the current list from GET /api/v1/models?type=video_from_video first. Models may be added, renamed, or retired at any time.

All generation endpoints accept an optional project_id body field that routes the output into a specific project. See Projects.

Endpoint

POST /api/v1/generate/video-from-video

Request Body

Accepts multipart/form-data (for file uploads) or application/json (for URL-based inputs).

FieldTypeRequiredDescription
promptstringNoDescribe the desired transformation or style. Most models require a prompt — only a few specialized models allow omitting it.
video_urlstringNoURL of the input video
filesfile(s)NoVideo file upload (multipart, max 100 MB)
modelstringNoModel identifier from GET /api/v1/models?type=video_from_video (default: auto-select)
aspect_ratiostringNo"16:9", "9:16", "1:1" (default: "16:9")
durationnumberNoOutput duration in seconds
enhance_promptbooleanNoEnhance prompt for better results (default: true)
resolutionstringNoVideo resolution tier (e.g. "720p", "1080p"). Model-dependent — check supported_resolutions on GET /api/v1/models?type=video_from_video. Higher tiers may multiply the credit cost — see Credit Multipliers.
reference_imagesarrayNoReference image URLs for models that take image inputs (e.g. Kling O1/O3 references). Required for motion-control models — see Motion Control.
presetstringNoVEED Subtitles only. Caption style preset (e.g. "glass", "whisper", "fusion", "simple", "vegas"). Ignored by other models.
source_languagestringNoVEED Subtitles only. BCP-47 code of the spoken language to improve transcription accuracy (e.g. "en-US", "es-ES", "he-IL"). Omit to auto-detect.
translation_languagestringNoVEED Subtitles only. BCP-47 code to translate the subtitles into (e.g. "en-US", "fr-FR"). Omit to keep the original spoken language.
srt_contentstringNoVEED Subtitles only. Raw .srt subtitle text to burn in. When set, auto-transcription is skipped.
srt_file_urlstringNoVEED Subtitles only. URL to a .srt file. Alternative to srt_content. When set, auto-transcription is skipped.
vocabularyarrayNoVEED Subtitles only. Brand names / jargon to help transcription, e.g. [{"word":"Kolbo","replaces":["colbo"]}]. Ignored when srt_content / srt_file_url is set.
customizationobjectNoVEED Subtitles only. Style overrides — position (top/center/bottom), shadow (none/min/mid/max), and text_customizations.baseline / .highlighted each with font (Google font name), weight (100-900), color (hex). Any omitted field keeps the preset default; best supported by Basic presets.

You must provide either video_url or a files upload — not both.

Motion Control (character image + driving video)

Motion-control / animate-move models (identifiers containing motion-control, animate-move, or wan-animate) transfer the motion of a reference video onto a character image. For these models the inputs are:

  • reference_images[0] — the character image (the subject that gets animated)
  • video_url — the driving / reference video whose motion is transferred (in the MCP tool this is the source_video argument)

Omitting the character image returns 400 with code MOTION_CONTROL_INPUTS.

curl -X POST https://api.kolbo.ai/api/v1/generate/video-from-video \
  -H "X-API-Key: kolbo_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "your-motion-control-model-identifier",
    "reference_images": ["https://example.com/character.jpg"],
    "video_url": "https://example.com/dance-reference.mp4"
  }'

VEED Subtitles (prompt-less)

The VEED Subtitles model (veed/subtitles) burns styled, auto-transcribed subtitles into a video. It takes no prompt — pass a style preset and optional language settings instead. Billed per minute of input video with a 1-minute minimum.

curl -X POST https://api.kolbo.ai/api/v1/generate/video-from-video \
  -H "X-API-Key: kolbo_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "veed/subtitles",
    "video_url": "https://example.com/talking-clip.mp4",
    "preset": "glass",
    "source_language": "en-US",
    "translation_language": "es-ES"
  }'

Examples

curl -X POST https://api.kolbo.ai/api/v1/generate/video-from-video \
  -H "X-API-Key: kolbo_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Transform into anime style with vibrant colors",
    "video_url": "https://example.com/original-clip.mp4",
    "aspect_ratio": "16:9"
  }'

cURL with File Upload

curl -X POST https://api.kolbo.ai/api/v1/generate/video-from-video \
  -H "X-API-Key: kolbo_live_YOUR_API_KEY" \
  -F "prompt=Transform into anime style with vibrant colors" \
  -F "[email protected]"

With Specific Model

To choose a specific model, first fetch identifiers from GET /api/v1/models?type=video_from_video, then pass the identifier value:

curl -X POST https://api.kolbo.ai/api/v1/generate/video-from-video \
  -H "X-API-Key: kolbo_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Transform into anime style with vibrant colors",
    "video_url": "https://example.com/original-clip.mp4",
    "model": "your-model-identifier"
  }'

Model identifiers come from GET /api/v1/models?type=video_from_video. Always fetch the latest list rather than hardcoding identifiers, as models may change over time.

JavaScript

const API_KEY = "kolbo_live_YOUR_API_KEY";

// Fetch available video-to-video models
async function initModels() {
  const res = await fetch("https://api.kolbo.ai/api/v1/models?type=video_from_video", {
    headers: { "X-API-Key": API_KEY },
  });
  const data = await res.json();
  console.log("Available models:", data.models.map((m) => m.identifier));
}

async function main() {
  await initModels();

  // Using URL (Smart Select)
  const response = await fetch("https://api.kolbo.ai/api/v1/generate/video-from-video", {
    method: "POST",
    headers: {
      "X-API-Key": API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      prompt: "Transform into anime style with vibrant colors",
      video_url: "https://example.com/original-clip.mp4",
      aspect_ratio: "16:9",
    }),
  });

  const data = await response.json();
  console.log("Generation ID:", data.generation_id);
  console.log("Poll URL:", data.poll_url);

  // Poll for completion
  const pollForResult = async (generationId) => {
    while (true) {
      await new Promise((r) => setTimeout(r, data.poll_interval_hint * 1000));
      const status = await fetch(
        `https://api.kolbo.ai/api/v1/generate/${generationId}/status`,
        { headers: { "X-API-Key": API_KEY } }
      ).then((r) => r.json());

      console.log("State:", status.state, "Progress:", status.progress);

      if (status.state === "completed") {
        console.log("Video URL:", status.result.urls[0]);
        return status;
      }
      if (status.state === "failed") {
        console.error("Generation failed:", status.error);
        return status;
      }
    }
  };

  await pollForResult(data.generation_id);
}

main();

Python

import requests
import time

API_KEY = "kolbo_live_YOUR_API_KEY"
BASE_URL = "https://api.kolbo.ai/api"
HEADERS = {"X-API-Key": API_KEY}

# Fetch available video-to-video models
models_res = requests.get(
    f"{BASE_URL}/v1/models",
    headers=HEADERS,
    params={"type": "video_from_video"},
)
print("Available models:", [m["identifier"] for m in models_res.json()["models"]])

# --- Option A: Using URL (Smart Select) ---
response = requests.post(
    f"{BASE_URL}/v1/generate/video-from-video",
    headers={**HEADERS, "Content-Type": "application/json"},
    json={
        "prompt": "Transform into anime style with vibrant colors",
        "video_url": "https://example.com/original-clip.mp4",
        "aspect_ratio": "16:9",
    },
)

data = response.json()
print("Generation ID:", data["generation_id"])

# --- Option B: Using file upload ---
# with open("original-clip.mp4", "rb") as vid:
#     response = requests.post(
#         f"{BASE_URL}/v1/generate/video-from-video",
#         headers=HEADERS,
#         files={"files": vid},
#         data={"prompt": "Transform into anime style with vibrant colors"},
#     )
#     data = response.json()

# Poll for completion
generation_id = data["generation_id"]
poll_interval = data.get("poll_interval_hint", 8)

while True:
    time.sleep(poll_interval)
    status = requests.get(
        f"{BASE_URL}/v1/generate/{generation_id}/status",
        headers=HEADERS,
    ).json()

    print(f"State: {status['state']}  Progress: {status.get('progress', 0)}%")

    if status["state"] == "completed":
        print("Video URL:", status["result"]["urls"][0])
        break
    if status["state"] == "failed":
        print("Error:", status.get("error"))
        break

Response

Generation Started

{
  "success": true,
  "generation_id": "v2v_abc123",
  "type": "video_from_video",
  "model": "auto",
  "credits_charged": 50,
  "poll_url": "/api/v1/generate/v2v_abc123/status",
  "poll_interval_hint": 8
}

Completed Status

{
  "success": true,
  "generation_id": "v2v_abc123",
  "type": "video_from_video",
  "state": "completed",
  "progress": 100,
  "result": {
    "urls": ["https://cdn.kolbo.ai/videos/..."],
    "thumbnail_url": "https://cdn.kolbo.ai/thumbs/...",
    "duration": 5,
    "aspect_ratio": "16:9",
    "prompt_used": "Transform into anime style with vibrant colors",
    "model": "auto",
    "created_at": "2026-04-12T10:00:00.000Z"
  }
}

Tips

  • Use Smart Select (the default). Omit the model field and Kolbo picks the best model for your prompt. This is the simplest and most future-proof approach.
  • Video-to-video generation typically takes 2-5 minutes depending on the model and duration.
  • Be descriptive in your prompt — specify the target style, mood, and any visual changes you want applied.
  • When using file uploads, the total request size limit is 100 MB per file.
  • Credits are charged per second: model.credit x duration.
  • Use poll_interval_hint from the initial response to set your polling interval.
  • Check supported_durations and supported_aspect_ratios on each model via the Models endpoint before requesting specific values.
  • Not all models support all durations or aspect ratios — if unsupported, the API may select the closest match.