Image to Video API

Image-to-video workflows use either reference_to_video or frames_to_video, depending on the selected model.

Mode selection

Mode Input field Use when
reference_to_video image_urls The model accepts reference images.
frames_to_video start_frame, optional end_frame The model accepts frame control.

Example: reference image to video

curl https://img2vid.net/api/v1/generations \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/sora-2",
    "mode": "reference_to_video",
    "prompt": "Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion",
    "image_urls": ["https://example.com/reference.png"],
    "duration": "4s",
    "aspect_ratio": "landscape"
  }'

Example: start frame to video

curl https://img2vid.net/api/v1/generations \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling/kling-v3",
    "mode": "frames_to_video",
    "prompt": "The product rotates slowly while the camera glides around it, dramatic highlights and realistic motion",
    "start_frame": "https://example.com/start.png",
    "duration": "5s",
    "resolution": "std",
    "aspect_ratio": "16:9",
    "audio": "false"
  }'

SDK examples

The SDK snippets below use the same public API shape as the HTTP examples: stable fields such as model, mode, prompt, and media URLs are passed directly, and model-specific options stay as flat generation parameters.

These snippets use the reference_to_video Sora example. For the Kling start-frame example, set model to kling/kling-v3, set mode to frames_to_video, replace image_urls with start_frame, and keep duration, resolution, aspect_ratio, and audio as flat parameters.

TypeScript / JavaScript

import { Buble } from '@buble/sdk';

const buble = new Buble();

const task = await buble.generations.create({
  model: 'openai/sora-2',
  mode: 'reference_to_video',
  prompt:
    'Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion',
  image_urls: ['https://example.com/reference.png'],
  duration: '4s',
  aspect_ratio: 'landscape',
});

const result = await buble.generations.wait(task.data.id);
console.log(result.data);

Python

from buble_ai import Buble

client = Buble()

task = client.generations.create(
    model='openai/sora-2',
    mode='reference_to_video',
    prompt='Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion',
    image_urls=['https://example.com/reference.png'],
    duration='4s',
    aspect_ratio='landscape',
)

result = client.generations.wait(task["data"]["id"])
print(result["data"])

Go

package main

import (
    "context"
    "fmt"
    "log"

    buble "github.com/bublehq/sdks/go"
)

func main() {
    ctx := context.Background()
    client := buble.NewClient()

    task, err := client.Generations.Create(ctx, &buble.CreateGenerationRequest{
        Model:  "openai/sora-2",
        Mode:   "reference_to_video",
        Prompt: "Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion",
        ImageURLs: []string{"https://example.com/reference.png"},
        Params: map[string]any{
            "duration": "4s",
            "aspect_ratio": "landscape",
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    result, err := client.Generations.Wait(ctx, task.Data.ID)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%+v\n", result.Data)
}

Rust

use buble::{Client, CreateGenerationRequest, WaitOptions};

#[tokio::main]
async fn main() -> buble::Result<()> {
    let client = Client::from_env();

    let task = client
        .generations()
        .create(
            CreateGenerationRequest::new("openai/sora-2")
                    .mode("reference_to_video")
                    .prompt("Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion")
                    .image_urls(["https://example.com/reference.png"])
                    .param("duration", "4s")?
                    .param("aspect_ratio", "landscape")?,
        )
        .await?;

    let result = client
        .generations()
        .wait(&task.data.id, WaitOptions::default())
        .await?;

    println!("{:?}", result.data);
    Ok(())
}

Swift

import Buble

let client = try BubleClient.fromEnvironment()

let task = try await client.generations.create(
    try CreateGenerationRequest(model: "openai/sora-2")
            .mode("reference_to_video")
            .prompt("Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion")
            .imageURLs(["https://example.com/reference.png"])
            .param("duration", "4s")
            .param("aspect_ratio", "landscape")
)

let result = try await client.generations.wait(task.data.id)
print(result.data)

Dart / Flutter

import 'package:buble/buble.dart';

Future<void> main() async {
  final client = BubleClient.fromEnvironment();

  final task = await client.generations.create(
    CreateGenerationRequest(
      model: 'openai/sora-2',
      mode: 'reference_to_video',
      prompt:
          'Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion',
      imageUrls: ['https://example.com/reference.png'],
    ).withParams({
      'duration': '4s',
      'aspect_ratio': 'landscape',
    }),
  );

  final result = await client.generations.wait(task.data.id);
  print(result.data.raw);
}

Elixir

client = Buble.Client.new!()

{:ok, task} =
  Buble.Generations.create(client, %{
    model: "openai/sora-2",
    mode: "reference_to_video",
    prompt:
      "Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion",
    image_urls: ["https://example.com/reference.png"],
    duration: "4s",
    aspect_ratio: "landscape",
  })

{:ok, result} = Buble.Generations.wait(client, get_in(task, ["data", "id"]))
IO.inspect(result["data"])

Java

import ai.buble.sdk.BubleClient;
import ai.buble.sdk.Envelope;
import ai.buble.sdk.generations.CreateGenerationRequest;
import ai.buble.sdk.generations.GenerationTask;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        BubleClient client = BubleClient.fromEnv();

        Envelope<GenerationTask> task = client.generations().create(
            CreateGenerationRequest.builder()
                    .model("openai/sora-2")
                    .mode("reference_to_video")
                    .prompt("Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion")
                    .imageUrls(List.of("https://example.com/reference.png"))
                    .param("duration", "4s")
                    .param("aspect_ratio", "landscape")
                    .build()
        );

        Envelope<GenerationTask> result = client.generations().wait(task.getData().getId());
        System.out.println(result.getData().getStatus());
    }
}

.NET

using Buble.Sdk;
using Buble.Sdk.Generations;

var client = BubleClient.FromEnv();

var request = new CreateGenerationRequest
{
    Model = "openai/sora-2",
    Mode = "reference_to_video",
    Prompt = "Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion",
    ImageUrls = new[] {"https://example.com/reference.png"},
}
.WithParam("duration", "4s")
.WithParam("aspect_ratio", "landscape");

var task = await client.Generations.CreateAsync(request);
var result = await client.Generations.WaitAsync(task!.Data!.Id!);
Console.WriteLine(result.Data.Status);

PHP

<?php

use Buble\BubleClient;
use Buble\Generations\CreateGenerationRequest;

$client = BubleClient::fromEnv();

$request = new CreateGenerationRequest(
    model: 'openai/sora-2',
    mode: 'reference_to_video',
    prompt: 'Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion',
    imageUrls: ['https://example.com/reference.png'],
);

$task = $client->generations()->create(
    $request
    ->withParam('duration', '4s')
    ->withParam('aspect_ratio', 'landscape')
);

$result = $client->generations()->wait($task['data']['id']);
print_r($result['data']);

Ruby

require 'buble'

client = Buble::Client.new

task = client.generations.create(
  model: 'openai/sora-2',
  mode: 'reference_to_video',
  prompt: 'Animate the reference image into a short cinematic musical scene with expressive performance and smooth camera motion',
  image_urls: ['https://example.com/reference.png'],
  duration: '4s',
  aspect_ratio: 'landscape',
)

result = client.generations.wait(task['data']['id'])
puts result['data']