快速开始
这个指南会创建一个文生图任务,然后轮询结果。
1. 设置 API Key
export BUBLE_API_KEY="sk_your_api_key"
API Key 只应该在服务端使用,不要暴露在浏览器代码中。
2. 查看可用媒体模型
curl https://img2vid.net/api/v1/media_models \
-H "Authorization: Bearer $BUBLE_API_KEY"
从响应中选择媒体 model,并使用它的 operations[].mode。
3. 创建文生图任务
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": "text_to_image",
"prompt": "A premium product photo of a matte black wireless speaker on a marble table, cinematic studio lighting",
"aspect_ratio": "1:1",
"resolution": "1K",
"output_format": "png"
}'
响应会返回生成任务 id。
4. 轮询任务
curl https://img2vid.net/api/v1/generations/YOUR_GENERATION_ID \
-H "Authorization: Bearer $BUBLE_API_KEY"
持续轮询,直到 data.status 变为 success 或 failed。
5. 需要素材时先上传文件
图生图或图生视频工作流通常需要先上传源文件:
curl https://img2vid.net/api/v1/files \
-H "Authorization: Bearer $BUBLE_API_KEY" \
-F "file=@./reference.png" \
-F "file_type=image" \
-F "model=google/nano-banana-pro" \
-F "mode=image_to_image"
然后把返回的 data.url 传给所选 mode 支持的 image_urls、start_frame 等字段。
6. 使用官方 SDK
SDK 封装的是稳定的公开 API 契约:模型和 app 发现、文件上传、创建异步生成任务、轮询结果,以及 Chat 协议调用。SDK 不会把每个模型的私有细节硬编码进去;模型 key、mode、app 参数和模型专属参数仍应从 API 返回结果中读取。
已发布的 SDK 包名、客户端类名和 BUBLE_API_KEY 环境变量作为兼容标识继续保留;它们仍调用 https://img2vid.net 上的 Img2Vid API。
| 语言 | 安装方式 |
|---|---|
| JavaScript / TypeScript | npm install @buble/sdk |
| Python | pip install buble-ai |
| Go | go get github.com/bublehq/sdks/go |
| Rust | cargo add buble |
| Swift | .package(url: "https://github.com/bublehq/swift-sdk.git", from: "0.1.0") |
| Dart / Flutter | dart pub add buble 或 flutter pub add buble |
| Elixir | {:buble, "~> 0.1.0"} |
| Java | ai.buble:buble-sdk:0.1.0 |
| .NET | dotnet add package Buble.SDK --version 0.1.2 |
| PHP | composer require buble/sdk |
| Ruby | gem install buble |
下面的 SDK 示例在没有显式传入 API key 时都会读取 BUBLE_API_KEY 环境变量。请只在服务端保存和使用这个 key。
JavaScript / TypeScript
import { Buble } from '@buble/sdk';
const buble = new Buble();
const task = await buble.generations.create({
model: 'google/nano-banana',
mode: 'text_to_image',
prompt: 'A cinematic product photo of a matte black espresso cup',
aspect_ratio: '1:1',
output_format: 'png',
});
const result = await buble.generations.wait(task.data.id);
console.log(result.data.result?.images?.[0]?.url);
Python
from buble_ai import Buble
client = Buble()
task = client.generations.create(
model="google/nano-banana",
mode="text_to_image",
prompt="A cinematic product photo of a matte black espresso cup",
aspect_ratio="1:1",
output_format="png",
)
result = client.generations.wait(task["data"]["id"])
print(result["data"]["result"]["images"][0]["url"])
Go
client := buble.NewClient()
task, err := client.Generations.Create(ctx, &buble.CreateGenerationRequest{
Model: "google/nano-banana",
Mode: "text_to_image",
Prompt: "A cinematic product photo of a matte black espresso cup",
Params: map[string]any{
"aspect_ratio": "1:1",
"output_format": "png",
},
})
if err != nil {
return err
}
result, err := client.Generations.Wait(ctx, task.Data.ID)
if err != nil {
return err
}
fmt.Println(result.Data.Result.Images[0].URL)
Rust
use buble::{Client, CreateGenerationRequest, WaitOptions};
let client = Client::from_env()?;
let task = client.generations().create(
CreateGenerationRequest::new("google/nano-banana")
.mode("text_to_image")
.prompt("A cinematic product photo of a matte black espresso cup")
.param("aspect_ratio", "1:1")?
.param("output_format", "png")?,
).await?;
let result = client
.generations()
.wait(&task.data.id, WaitOptions::default())
.await?;
Swift
import Buble
let client = try BubleClient.fromEnvironment()
let task = try await client.generations.create(
try CreateGenerationRequest(model: "google/nano-banana")
.mode("text_to_image")
.prompt("A cinematic product photo of a matte black espresso cup")
.param("aspect_ratio", "1:1")
.param("output_format", "png")
)
let result = try await client.generations.wait(task.data.id)
print(result.data.result?.images?.first?.url.absoluteString ?? "")
Dart / Flutter
import 'package:buble/buble.dart';
final client = BubleClient.fromEnvironment();
final task = await client.generations.create(
CreateGenerationRequest(
model: 'google/nano-banana',
mode: 'text_to_image',
prompt: 'A cinematic product photo of a matte black espresso cup',
).withParam('aspect_ratio', '1:1').withParam('output_format', 'png'),
);
final result = await client.generations.wait(task.data.id);
print(result.data.result?.images.firstOrNull?.url);
Elixir
client = Buble.Client.new!()
{:ok, task} =
Buble.Generations.create(client, %{
model: "google/nano-banana",
mode: "text_to_image",
prompt: "A cinematic product photo of a matte black espresso cup",
aspect_ratio: "1:1",
output_format: "png"
})
{:ok, result} = Buble.Generations.wait(client, task["data"]["id"])
IO.puts(result["data"]["result"]["images"] |> List.first() |> Map.fetch!("url"))
Java
BubleClient client = BubleClient.fromEnv();
Envelope<GenerationTask> task = client.generations().create(
CreateGenerationRequest.builder()
.model("google/nano-banana")
.mode("text_to_image")
.prompt("A cinematic product photo of a matte black espresso cup")
.param("aspect_ratio", "1:1")
.param("output_format", "png")
.build());
Envelope<GenerationTask> result = client.generations().wait(task.getData().getId());
.NET
using var client = BubleClient.FromEnv();
var task = await client.Generations.CreateAsync(new CreateGenerationRequest
{
Model = "google/nano-banana",
Mode = "text_to_image",
Prompt = "A cinematic product photo of a matte black espresso cup"
}.WithParam("aspect_ratio", "1:1").WithParam("output_format", "png"));
var result = await client.Generations.WaitAsync(task!.Data!.Id!);
PHP
use Buble\BubleClient;
use Buble\Generations\CreateGenerationRequest;
$client = BubleClient::fromEnv();
$task = $client->generations()->create(
CreateGenerationRequest::make(
model: 'google/nano-banana',
mode: 'text_to_image',
prompt: 'A cinematic product photo of a matte black espresso cup',
)->withParam('aspect_ratio', '1:1')
->withParam('output_format', 'png')
);
$result = $client->generations()->wait($task['data']['id']);
Ruby
require "buble"
client = Buble::Client.new
task = client.generations.create(
model: "google/nano-banana",
mode: "text_to_image",
prompt: "A cinematic product photo of a matte black espresso cup",
aspect_ratio: "1:1",
output_format: "png"
)
result = client.generations.wait(task.dig("data", "id"))
puts result.dig("data", "result", "images", 0, "url")