Text-to-image generation with GoogleImageGenService and Gemini image models.
Overview
GoogleImageGenService generates images from text prompts with Gemini image models through
the Gemini API. Gemini returns each image inline in the response, and the service decodes it
to RGB pixels for the output transport.
GoogleImageGenService: onegenerateContentrequest per image, with aspect ratio and size settings.
Upstream page
Pipecat's documentation for the same service.
Source
packages/google/src/image.ts and image_decoder.ts.
Gemini image generation docs
Image models, aspect ratios and sizes.
Installation
bun add @pipedog/googleimport { GoogleImageGenService } from "@pipedog/google/image";
import type { ImageDecoder } from "@pipedog/google/image_decoder";Prerequisites
- A Gemini API key from Google AI Studio.
- Pass the key as
apiKey. The examples read it fromGOOGLE_API_KEY. - An image decoder (see below).
GoogleImageGenService
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new GoogleImageGenService.Settings({...}).
| Setting | Type | Default | Description |
|---|---|---|---|
model | string | "gemini-3.1-flash-image" | Gemini image model. |
numberOfImages | number | 1 | Images per prompt. |
aspectRatio | string | null | "1:1" | Aspect ratio, e.g. "16:9". null leaves the model default. |
imageSize | "1K" | "2K" | "4K" | null | null | Resolution. null leaves the model default. Supported sizes vary by model. |
Usage
import { GoogleImageGenService } from "@pipedog/google/image";
import type { ImageDecoder } from "@pipedog/google/image_decoder";
// Your decoder from PNG/JPEG/WebP bytes to RGB pixels (sharp, @jsquash/*, ...).
declare const decodeImage: ImageDecoder;
const imageGen = new GoogleImageGenService({
apiKey: process.env.GOOGLE_API_KEY ?? "",
imageDecoder: decodeImage,
settings: new GoogleImageGenService.Settings({
model: "gemini-3.1-flash-image",
aspectRatio: "16:9",
imageSize: "2K",
}),
});Image decoder
Upstream decodes the returned PNG, JPEG or WebP with Pillow. pipedog has no edge-compatible
decoder yet, so the service takes an imageDecoder: a function from the encoded bytes and MIME
type to { image, size, mode } (raw pixels, [width, height] and a Pillow-style mode such as
"RGB"). Build one on sharp, @jsquash/* or similar.
The default decoder throws "not ported yet". Without an imageDecoder, every generated image
yields an ErrorFrame.
Notes
- The service generates an image for each
TextFrameit receives and emits aURLImageRawFrameper image, withurl: nullsince Gemini returns the image inline. - With
numberOfImagesabove 1, the images are generated one after another, one request each. - A response with no image, or a failed request, yields an
ErrorFrame. - Supports TTFB metrics.
- Pass
clientto use your own GenAI client (anything withmodels.generateContent).
Runtime notes
| Runtime | Works | What it needs |
|---|---|---|
| Bun | ✅ yes | Nothing. |
| Node.js | ✅ yes | Nothing. |
| Deno | ✅ yes | Nothing. |
| Cloudflare Workers | ✅ yes | Nothing. |
Generated from pipecat.runtimes and pipecat.compat in packages/google/package.json: ✅ means the compat smoke test passes on that runtime.
The client is GoogleGenAI from @google/genai, which uses fetch, so the service runs on
Bun, Node, Deno and Cloudflare Workers, as long as your imageDecoder does too.
The deprecated upstream InputParams class, the params option and the negativePrompt
setting are not ported.
pipedog is an unofficial community TypeScript port of Pipecat. It is not affiliated with or endorsed by Daily or the Pipecat project.
Portions adapted from the Pipecat documentation, Copyright (c) 2024–2025 Daily, BSD-2-Clause (see apps/docs/LICENSE-pipecat-docs).