Skip to main content
The Queue API is the primary way to generate videos with the JavaScript SDK. Submit jobs that are processed asynchronously in the background, then poll for status and retrieve results when complete.
All video generation (text-to-video, image-to-video, video-to-video, motion control) uses the Queue API. For image generation, use the Process API.

Overview

The Queue API provides four main methods:
  • submit() - Submit a job and get a job ID immediately
  • status() - Check the status of a submitted job
  • result() - Retrieve the completed video
  • submitAndPoll() - Submit and automatically poll until completion

Submit a Job

Submit a video generation job and receive a job ID immediately:
const job = await client.queue.submit({
  model: models.video("lucy-pro-t2v"),
  prompt: "A serene lake at sunset with mountains in the background",
  resolution: "720p",
});

console.log(`Job ID: ${job.job_id}`);
console.log(`Status: ${job.status}`); // "pending"
Returns:
  • job_id - Unique identifier for the job
  • status - Initial status ("pending")

Check Job Status

Poll the status of a submitted job:
const status = await client.queue.status(job.job_id);

console.log(`Status: ${status.status}`); // "pending", "processing", "completed", or "failed"
Status Values:
StatusDescription
pendingJob is queued, waiting to be processed
processingJob is currently being processed
completedJob finished successfully
failedJob failed or timed out (timeout after 10 minutes)

Get Job Result

Retrieve the video once the job is completed:
import { writeFileSync } from "fs";

// First check status
const status = await client.queue.status(job.job_id);

if (status.status === "completed") {
  const result = await client.queue.result(job.job_id);

  if (result.status === "completed") {
    // result.data is a Blob
    const buffer = Buffer.from(await result.data.arrayBuffer());
    writeFileSync("output.mp4", buffer);
    console.log("Video saved!");
  } else {
    console.error(`Error: ${result.error}`);
  }
}
Returns:
  • status - Either "completed" or "failed"
  • data - Video Blob (when completed)
  • error - Error message (when failed)

Submit and Poll

The easiest way to use the Queue API - submit a job and automatically poll until completion:
import { writeFileSync } from "fs";

const result = await client.queue.submitAndPoll({
  model: models.video("lucy-pro-t2v"),
  prompt: "A serene lake at sunset with mountains in the background",
  resolution: "720p",
  onStatusChange: (job) => {
    console.log(`Status: ${job.status}`);
  },
});

if (result.status === "completed") {
  const buffer = Buffer.from(await result.data.arrayBuffer());
  writeFileSync("output.mp4", buffer);
  console.log("Video saved!");
} else {
  console.error(`Generation failed: ${result.error}`);
}
Parameters:
  • All standard model parameters (prompt, resolution, etc.)
  • onStatusChange (optional) - Callback function called on each status change

TypeScript Types

import type {
  JobStatus,
  JobSubmitResponse,
  JobStatusResponse,
  QueueJobResult,
} from "@decartai/sdk";

// Job status values
type JobStatus = "pending" | "processing" | "completed" | "failed";

// Submit response
interface JobSubmitResponse {
  job_id: string;
  status: JobStatus;
}

// Status response
interface JobStatusResponse {
  job_id: string;
  status: JobStatus;
}

// Result (discriminated union)
type QueueJobResult =
  | { status: "completed"; data: Blob }
  | { status: "failed"; error: string };

Complete Example

Node.js

import { createDecartClient, models } from "@decartai/sdk";
import { writeFileSync } from "fs";

const client = createDecartClient({ apiKey: "your-api-key" });

async function generateVideo() {
  console.log("Submitting video generation job...");

  const result = await client.queue.submitAndPoll({
    model: models.video("lucy-pro-t2v"),
    prompt: "A futuristic cityscape with flying cars",
    resolution: "720p",
    onStatusChange: (job) => {
      console.log(`  Status: ${job.status}`);
    },
  });

  if (result.status === "completed") {
    const buffer = Buffer.from(await result.data.arrayBuffer());
    writeFileSync("cityscape.mp4", buffer);
    console.log("Video saved to cityscape.mp4");
  } else {
    console.error(`Generation failed: ${result.error}`);
  }
}

generateVideo();

Image Animation with Queue

Animate images using the queue for better control:
import { readFileSync, writeFileSync } from "fs";

const imageBuffer = readFileSync("input-image.jpg");
const imageBlob = new Blob([imageBuffer], { type: "image/jpeg" });

const result = await client.queue.submitAndPoll({
  model: models.video("lucy-pro-i2v"),
  prompt: "Animate with gentle motion and wind",
  data: imageBlob,
  resolution: "720p",
  onStatusChange: (job) => {
    console.log(`Status: ${job.status}`);
  },
});

if (result.status === "completed") {
  const buffer = Buffer.from(await result.data.arrayBuffer());
  writeFileSync("animated.mp4", buffer);
}

Video Editing with Queue

Transform videos with style transfer:
import { readFileSync, writeFileSync } from "fs";

const videoBuffer = readFileSync("input-video.mp4");
const videoBlob = new Blob([videoBuffer], { type: "video/mp4" });

const result = await client.queue.submitAndPoll({
  model: models.video("lucy-pro-v2v"),
  prompt: "Convert to anime style with vibrant colors",
  data: videoBlob,
  onStatusChange: (job) => {
    console.log(`Status: ${job.status}`);
  },
});

if (result.status === "completed") {
  const buffer = Buffer.from(await result.data.arrayBuffer());
  writeFileSync("styled-video.mp4", buffer);
}

Cancellation with AbortSignal

Cancel queue operations using AbortController:
const controller = new AbortController();

// Start generation
const resultPromise = client.queue.submitAndPoll({
  model: models.video("lucy-pro-t2v"),
  prompt: "A beautiful sunset",
  signal: controller.signal,
  onStatusChange: (job) => {
    console.log(`Status: ${job.status}`);
  },
});

// Cancel after 30 seconds (example)
setTimeout(() => {
  controller.abort();
  console.log("Cancellation requested");
}, 30000);

try {
  const result = await resultPromise;
  // Handle result...
} catch (error) {
  if (error.name === "AbortError") {
    console.log("Generation cancelled");
  }
}

Manual Polling

For custom polling logic, you can manually poll for status:
import { writeFileSync } from "fs";

// Submit job
const job = await client.queue.submit({
  model: models.video("lucy-pro-t2v"),
  prompt: "A serene lake at sunset",
});

console.log(`Job submitted: ${job.job_id}`);

// Manual polling loop
while (true) {
  const status = await client.queue.status(job.job_id);
  console.log(`Status: ${status.status}`);

  if (status.status === "completed") {
    const result = await client.queue.result(job.job_id);
    if (result.status === "completed") {
      const buffer = Buffer.from(await result.data.arrayBuffer());
      writeFileSync("output.mp4", buffer);
      console.log("Video saved!");
    }
    break;
  } else if (status.status === "failed") {
    console.error("Generation failed");
    break;
  }

  // Wait before next poll
  await new Promise((r) => setTimeout(r, 2000));
}

Error Handling

import {
  createDecartClient,
  models,
  QueueSubmitError,
  QueueStatusError,
  QueueResultError,
  DecartSDKError,
} from "@decartai/sdk";

try {
  const result = await client.queue.submitAndPoll({
    model: models.video("lucy-pro-t2v"),
    prompt: "A beautiful sunset",
  });
} catch (error) {
  if (error instanceof QueueSubmitError) {
    console.error(`Failed to submit job: ${error.message}`);
  } else if (error instanceof QueueStatusError) {
    console.error(`Failed to check status: ${error.message}`);
  } else if (error instanceof QueueResultError) {
    console.error(`Failed to get result: ${error.message}`);
  } else if (error instanceof DecartSDKError) {
    console.error(`SDK error: ${error.message}`);
  }
}

Supported Models

All non-realtime video models support queue processing:
ModelTypeDescription
lucy-pro-t2vText-to-VideoGenerate videos from text prompts
lucy-pro-i2vImage-to-VideoAnimate images
lucy-dev-i2vImage-to-VideoDevelopment model for animation
lucy-pro-v2vVideo-to-VideoTransform video style
lucy-fast-v2vVideo-to-VideoFast video transformation

API Reference

client.queue.submit(options)

Submit a job for processing. Parameters:
  • options: QueueSubmitOptions - Model and input parameters
    • model - Model from models.video()
    • signal?: AbortSignal - Optional abort signal
    • Additional model-specific parameters
Returns: Promise<JobSubmitResponse>
  • job_id: string - Unique job identifier
  • status: JobStatus - Initial status (“pending”)

client.queue.status(jobId)

Check the status of a job. Parameters:
  • jobId: string - The job identifier
Returns: Promise<JobStatusResponse>
  • job_id: string - Job identifier
  • status: JobStatus - Current status

client.queue.result(jobId)

Get the result of a completed job. Parameters:
  • jobId: string - The job identifier
Returns: Promise<QueueJobResult>
  • When completed: { status: "completed", data: Blob }
  • When failed: { status: "failed", error: string }

client.queue.submitAndPoll(options)

Submit a job and poll until completion. Parameters:
  • options: QueueSubmitAndPollOptions - Model and input parameters
    • onStatusChange?: (job: JobStatusResponse) => void - Status change callback
    • signal?: AbortSignal - Optional abort signal
    • Additional model-specific parameters
Returns: Promise<QueueJobResult>

Next Steps