Image to Video

Image-to-Video

Transform static images into dynamic, high-quality videos with smooth, natural motion guided by optional text prompts.


Create an Image-to-Video Task

Animate a static image into a video. The model analyzes the source image and generates fluid motion based on the visual content and optional text guidance.

Request URL

Copy
POST https://api-gen-na.bach.art/api/vdr/videos/image2video

Request Headers

HeaderValue
AuthorizationBearer <your_api_token>
Content-Typeapplication/json

Request Body

json
Copy
{
  "model_name": "bach-1.0-preview",
  "image_url": "https://example.com/images/scene.jpg",
  "prompt": "The scene comes alive with gentle movement",
  "negative_prompt": "blurry, distorted, unnatural",
  "resolution": "720p",
  "duration": 6,
  "cfg_scale": 5.0,
  "enhance_prompt": true,
  "generate_audio": false,
  "audio_prompt": "gentle movement, ambient sounds",
  "callback_url": "https://your-domain.com/callback",
  "seed": 12345,
  "enable_moderation": true
}

Request Parameters

ParameterTypeRequiredDefaultDescription
model_namestringYesModel identifier. Currently only bach-1.0-preview is supported
image_urlstringYesPublicly accessible HTTP/HTTPS URL of the source image
promptstringNoText description to guide the animation (max 10,000 characters)
negative_promptstringNoElements to exclude from the generated video (max 10,000 characters)
resolutionstringYesOutput resolution: 720p or 1080p (case-sensitive)
durationintegerYesVideo duration in seconds. (range:1~6)
fpsintegerNo30Frame rate:30 or 24. Currently default at 30
cfg_scalefloatNo5.0Classifier-free guidance scale. Higher values increase prompt adherence (range: 1.015.0)
enhance_promptbooleanNotrueAutomatically enhance the prompt for improved visual quality
generate_audiobooleanNofalseGenerate a synchronized audio track
audio_promptstringNoText description for audio generation (max 200 characters). Only effective when generate_audio is true
callback_urlstringNoWebhook URL for task completion notifications (max 500 characters)
seedintegerNoRandomRandom seed for reproducible generation (range: 010,000,000)
enable_moderationbooleanNotrueEnable content moderation for text, image, and audio inputs

Image Requirements

RequirementSpecification
Supported FormatsJPEG, PNG, WebP, GIF, BMP, TIFF
Maximum File Size10 MB
Minimum Resolution300 × 300 pixels
Recommended Resolution720p or higher for best results
URL AccessibilityMust be publicly accessible via HTTP/HTTPS

Response

Success (HTTP 200):

json
Copy
{
  "code": 200,
  "message": "Success",
  "data": {
    "task_id": "770e8400-e29b-41d4-a716-446655440002",
    "create_at": 1709251200
  }
}
FieldTypeDescription
codeintegerBusiness response code
messagestringResponse message
data.task_idstringUnique task identifier (UUID)
data.create_atlongTask creation timestamp (Unix epoch, seconds)

Error Examples:

ScenarioHTTP StatusCodeMessage
Missing prompt4001000Please provide a prompt.
Invalid duration4001000Duration must be between 1 and 5 seconds.
Insufficient credits4031302Insufficient credit package.

For a complete list of error codes, see Response Codes.


Query an Image-to-Video Task

Retrieve the status and result of a previously submitted image-to-video task.

Request URL

Copy
GET https://api-gen-na.bach.art/api/vdr/videos/image2video/{task_id}

Request Headers

HeaderValue
AuthorizationBearer <your_api_token>

Path Parameters

ParameterTypeRequiredDescription
task_idstringYesTask identifier returned by the creation endpoint

Request Example

bash
Copy
curl -X GET "https://api-gen-na.bach.art/api/vdr/videos/image2video/770e8400-e29b-41d4-a716-446655440002" \
  -H "Authorization: Bearer <your_api_token>"

Response

Success (HTTP 200):

json
Copy
{
  "code": 200,
  "message": "Success",
  "data": {
    "task_id": "770e8400-e29b-41d4-a716-446655440002",
    "status": "TASK_SUCCEEDED",
    "message": "Video generation completed successfully",
    "video_url": "https://cdn.bach.art/videos/770e8400-e29b-41d4-a716-446655440002.mp4"
  }
}
FieldTypeDescription
data.task_idstringUnique task identifier
data.statusstringCurrent task status. See Task Status
data.messagestringHuman-readable status message
data.video_urlstringDownload URL for the generated video. Present only when status is TASK_SUCCEEDED

Task Status Values

StatusDescription
TASK_PENDINGTask is queued, awaiting processing
TASK_PROCESSINGVideo generation is in progress
TASK_SUCCEEDEDGeneration completed; video_url is available
TASK_FAILEDGeneration failed; check message for details

Webhook Callback

If you provide a callback_url when creating a task, the API sends an HTTP POST request to that URL upon task completion.

Callback Payload:

json
Copy
{
  "task_id": "770e8400-e29b-41d4-a716-446655440002",
  "status": "TASK_SUCCEEDED",
  "video_url": "https://cdn.bach.art/videos/770e8400-e29b-41d4-a716-446655440002.mp4",
  "created_at": 1709251200,
  "completed_at": 1709251280
}

Note: Your callback endpoint must return HTTP 200 within 5 seconds. Failed callbacks are retried up to 3 times with exponential backoff.


Code Examples

Python

python
Copy
import requests
import time

API_BASE = "https://api-gen-na.bach.art/api/vdr"
API_TOKEN = "<your_api_token>"

headers = {
    "Authorization": f"Bearer {API_TOKEN}",
    "Content-Type": "application/json"
}

# Step 1: Create an image-to-video task
payload = {
    "model_name": "bach-1.0-preview",
    "image_url": "https://example.com/images/landscape.jpg",
    "prompt": "Clouds drift slowly across the sky, trees sway gently in the breeze",
    "negative_prompt": "static, frozen, jerky motion",
    "resolution": "1080p",
    "duration": 5,
    "cfg_scale": 5.0,
    "enhance_prompt": True
}

response = requests.post(
    f"{API_BASE}/videos/image2video",
    headers=headers,
    json=payload
)

task_id = response.json()["data"]["task_id"]
print(f"Task submitted: {task_id}")

# Step 2: Poll for completion
while True:
    status_response = requests.get(
        f"{API_BASE}/videos/image2video/{task_id}",
        headers=headers
    )

    result = status_response.json()["data"]
    status = result["status"]

    if status  "TASK_SUCCEEDED":
        print(f"Video ready: {result['video_url']}")
        break
    elif status  "TASK_FAILED":
        print(f"Generation failed: {result['message']}")
        break
    else:
        print(f"Status: {status}, waiting...")
        time.sleep(10)

cURL

bash
Copy
# Create task
curl -X POST "https://api-gen-na.bach.art/api/vdr/videos/image2video" \
  -H "Authorization: Bearer <your_api_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "bach-1.0-preview",
    "image_url": "https://example.com/images/landscape.jpg",
    "prompt": "Clouds drift slowly across the sky, trees sway gently in the breeze",
    "resolution": "1080p",
    "duration": 5
  }'

# Query task status
curl -X GET "https://api-gen-na.bach.art/api/vdr/videos/image2video/{task_id}" \
  -H "Authorization: Bearer <your_api_token>"

Node.js

javascript
Copy
const axios = require('axios');

const API_BASE = 'https://api-gen-na.bach.art/api/vdr';
const API_TOKEN = '<your_api_token>';

const headers = {
  'Authorization': `Bearer ${API_TOKEN}`,
  'Content-Type': 'application/json'
};

async function animateImage() {
  // Step 1: Create task
  const submitResponse = await axios.post(
    `${API_BASE}/videos/image2video`,
    {
      model_name: 'bach-1.0-preview',
      image_url: 'https://example.com/images/landscape.jpg',
      prompt: 'Clouds drift slowly across the sky, trees sway gently in the breeze',
      resolution: '1080p',
      duration: 5,
      enhance_prompt: true
    },
    { headers }
  );

  const taskId = submitResponse.data.data.task_id;
  console.log(`Task submitted: ${taskId}`);

  // Step 2: Poll for completion
  while (true) {
    const statusResponse = await axios.get(
      `${API_BASE}/videos/image2video/${taskId}`,
      { headers }
    );

    const { status, video_url, message } = statusResponse.data.data;

    if (status = 'TASK_SUCCEEDED') {
      console.log(`Video ready: ${video_url}`);
      return video_url;
    } else if (status = 'TASK_FAILED') {
      throw new Error(`Generation failed: ${message}`);
    }

    console.log(`Status: ${status}, waiting...`);
    await new Promise(resolve => setTimeout(resolve, 10000));
  }
}

animateImage().catch(console.error);

Best Practices

Image Selection

  • Use high-resolution sources: Images at 720p or higher produce the best output quality.
  • Ensure clear subjects: Well-defined subjects with good lighting generate more coherent animations.
  • Avoid excessive clutter: Overly busy scenes may result in less natural motion.

Prompt Writing

  • Describe the desired motion: Focus on the type, speed, and direction of movement (e.g., "gentle swaying," "flowing water," "walking forward").
  • Be specific: Include details about camera movement, environmental effects, and character actions.
  • Leverage negative prompts: Specify unwanted effects such as "jerky motion," "morphing," or "distortion."

Duration Selection

DurationRecommended Use Case
1–2 sQuick animations, subtle effects, loops
3–4 sStandard product showcases, social media content
5-6 sComplex scenes, cinematic storytelling
Previous
Text to Video
Next
Text to Subject
On this page