上传并生成
这个端到端示例会先上传一张源图片,然后用它创建图生图任务。
1. 上传源图片
curl https://img2vid.net/api/v1/files \
-H "Authorization: Bearer $BUBLE_API_KEY" \
-F "file=@./room.png" \
-F "file_type=image" \
-F "model=google/nano-banana-pro" \
-F "mode=image_to_image"
保存返回的 data.url。
2. 创建生成任务
curl https://img2vid.net/api/v1/generations \
-H "Authorization: Bearer $BUBLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-pro",
"mode": "image_to_image",
"prompt": "Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling",
"image_urls": ["https://example.com/uploaded-room.png"],
"aspect_ratio": "16:9",
"resolution": "1K",
"output_format": "png"
}'
3. 轮询结果
curl https://img2vid.net/api/v1/generations/YOUR_GENERATION_ID \
-H "Authorization: Bearer $BUBLE_API_KEY"
Node.js 版本
import fs from 'node:fs';
const fileForm = new FormData();
fileForm.append(
'file',
new Blob([fs.readFileSync('./room.png')], { type: 'image/png' }),
'room.png'
);
fileForm.append('file_type', 'image');
fileForm.append('model', 'google/nano-banana-pro');
fileForm.append('mode', 'image_to_image');
const upload = await fetch('https://img2vid.net/api/v1/files', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.BUBLE_API_KEY}` },
body: fileForm,
});
const { data: uploaded, error: uploadError } = await upload.json();
if (uploadError) throw new Error(uploadError.message);
const generation = await fetch('https://img2vid.net/api/v1/generations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BUBLE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'google/nano-banana-pro',
mode: 'image_to_image',
prompt:
'Redesign this room as a premium modern Japanese-inspired interior.',
image_urls: [uploaded.url],
aspect_ratio: '16:9',
resolution: '1K',
output_format: 'png',
}),
});
const { data: task, error } = await generation.json();
if (error) throw new Error(error.message);
console.log(task.id);
SDK 示例
这些 SDK 示例会上传 ./room.png,把返回的 data.url 作为 image_urls[0] 创建生成任务,并等待任务完成。
TypeScript / JavaScript
import { Buble } from '@buble/sdk';
const buble = new Buble();
const uploaded = await buble.files.upload('./room.png', {
file_type: 'image',
model: 'google/nano-banana-pro',
mode: 'image_to_image',
});
const task = await buble.generations.create({
model: 'google/nano-banana-pro',
mode: 'image_to_image',
prompt:
'Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling',
image_urls: [uploaded.data.url],
aspect_ratio: '16:9',
resolution: '1K',
output_format: 'png',
});
const result = await buble.generations.wait(task.data.id);
console.log(result.data);
Python
from buble_ai import Buble
client = Buble()
uploaded = client.files.upload(
'./room.png',
file_type='image',
model='google/nano-banana-pro',
mode='image_to_image',
)
task = client.generations.create(
model='google/nano-banana-pro',
mode='image_to_image',
prompt='Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling',
image_urls=[uploaded['data']['url']],
aspect_ratio='16:9',
resolution='1K',
output_format='png',
)
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()
uploaded, err := client.Files.Upload(
ctx,
buble.FileFromPath("./room.png"),
buble.WithFileType("image"),
buble.WithUploadModel("google/nano-banana-pro"),
buble.WithUploadMode("image_to_image"),
)
if err != nil {
log.Fatal(err)
}
task, err := client.Generations.Create(ctx, &buble.CreateGenerationRequest{
Model: "google/nano-banana-pro",
Mode: "image_to_image",
Prompt: "Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling",
ImageURLs: []string{uploaded.Data.URL},
Params: map[string]any{
"aspect_ratio": "16:9",
"resolution": "1K",
"output_format": "png",
},
})
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, FileUpload, UploadOptions, WaitOptions};
#[tokio::main]
async fn main() -> buble::Result<()> {
let client = Client::from_env();
let uploaded = client
.files()
.upload(
FileUpload::from_path("./room.png"),
UploadOptions::new()
.file_type("image")
.model("google/nano-banana-pro")
.mode("image_to_image"),
)
.await?;
let task = client
.generations()
.create(
CreateGenerationRequest::new("google/nano-banana-pro")
.mode("image_to_image")
.prompt("Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling")
.image_urls([uploaded.data.url])
.param("aspect_ratio", "16:9")?
.param("resolution", "1K")?
.param("output_format", "png")?,
)
.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 uploaded = try await client.files.upload(
.fromFileURL(URL(fileURLWithPath: "./room.png"), contentType: "image/png"),
options: UploadOptions(
fileType: "image",
model: "google/nano-banana-pro",
mode: "image_to_image"
)
)
let task = try await client.generations.create(
try CreateGenerationRequest(model: "google/nano-banana-pro")
.mode("image_to_image")
.prompt("Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling")
.imageURLs([uploaded.data.url.absoluteString])
.param("aspect_ratio", "16:9")
.param("resolution", "1K")
.param("output_format", "png")
)
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 uploaded = await client.files.upload(
FileUpload.fromPath('./room.png', contentType: 'image/png'),
options: const UploadOptions(
fileType: 'image',
model: 'google/nano-banana-pro',
mode: 'image_to_image',
),
);
final task = await client.generations.create(
CreateGenerationRequest(
model: 'google/nano-banana-pro',
mode: 'image_to_image',
prompt:
'Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling',
imageUrls: [uploaded.data.url.toString()],
).withParams({
'aspect_ratio': '16:9',
'resolution': '1K',
'output_format': 'png',
}),
);
final result = await client.generations.wait(task.data.id);
print(result.data.raw);
}
Elixir
client = Buble.Client.new!()
{:ok, uploaded} =
Buble.Files.upload(client, "./room.png", %{
file_type: "image",
model: "google/nano-banana-pro",
mode: "image_to_image"
})
{:ok, task} =
Buble.Generations.create(client, %{
model: "google/nano-banana-pro",
mode: "image_to_image",
prompt:
"Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling",
image_urls: [get_in(uploaded, ["data", "url"])],
aspect_ratio: "16:9",
resolution: "1K",
output_format: "png"
})
{: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.files.FileUpload;
import ai.buble.sdk.files.UploadOptions;
import ai.buble.sdk.files.UploadedFile;
import ai.buble.sdk.generations.CreateGenerationRequest;
import ai.buble.sdk.generations.GenerationTask;
import java.nio.file.Path;
import java.util.List;
public class Example {
public static void main(String[] args) {
BubleClient client = BubleClient.fromEnv();
Envelope<UploadedFile> uploaded = client.files().upload(
FileUpload.fromPath(Path.of("./room.png")),
UploadOptions.builder()
.fileType("image")
.model("google/nano-banana-pro")
.mode("image_to_image")
.build()
);
Envelope<GenerationTask> task = client.generations().create(
CreateGenerationRequest.builder()
.model("google/nano-banana-pro")
.mode("image_to_image")
.prompt("Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling")
.imageUrls(List.of(uploaded.getData().getUrl()))
.param("aspect_ratio", "16:9")
.param("resolution", "1K")
.param("output_format", "png")
.build()
);
Envelope<GenerationTask> result = client.generations().wait(task.getData().getId());
System.out.println(result.getData().getStatus());
}
}
.NET
using Buble.Sdk;
using Buble.Sdk.Files;
using Buble.Sdk.Generations;
var client = BubleClient.FromEnv();
var uploaded = await client.Files.UploadAsync(
FileUpload.FromPath("./room.png", contentType: "image/png"),
new UploadOptions
{
FileType = "image",
Model = "google/nano-banana-pro",
Mode = "image_to_image",
}
);
var request = new CreateGenerationRequest
{
Model = "google/nano-banana-pro",
Mode = "image_to_image",
Prompt = "Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling",
ImageUrls = new[] { uploaded!.Data!.Url! },
}
.WithParam("aspect_ratio", "16:9")
.WithParam("resolution", "1K")
.WithParam("output_format", "png");
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\Files\FileUpload;
use Buble\Files\UploadOptions;
use Buble\Generations\CreateGenerationRequest;
$client = BubleClient::fromEnv();
$uploaded = $client->files()->upload(
FileUpload::fromPath('./room.png', 'image/png'),
new UploadOptions(
fileType: 'image',
model: 'google/nano-banana-pro',
mode: 'image_to_image',
),
);
$request = new CreateGenerationRequest(
model: 'google/nano-banana-pro',
mode: 'image_to_image',
prompt: 'Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling',
imageUrls: [$uploaded['data']['url']],
);
$task = $client->generations()->create(
$request
->withParam('aspect_ratio', '16:9')
->withParam('resolution', '1K')
->withParam('output_format', 'png')
);
$result = $client->generations()->wait($task['data']['id']);
print_r($result['data']);
Ruby
require 'buble'
client = Buble::Client.new
uploaded = client.files.upload(
'./room.png',
file_type: 'image',
model: 'google/nano-banana-pro',
mode: 'image_to_image'
)
task = client.generations.create(
model: 'google/nano-banana-pro',
mode: 'image_to_image',
prompt: 'Redesign this room as a premium modern Japanese-inspired interior with warm oak, paper lantern lighting, low furniture, and calm editorial styling',
image_urls: [uploaded['data']['url']],
aspect_ratio: '16:9',
resolution: '1K',
output_format: 'png'
)
result = client.generations.wait(task['data']['id'])
puts result['data']