Topaz Labs

Learn how to use the Topaz Labs provider for the AI SDK.

The Topaz Labs provider contains support for Topaz Labs' image and video enhancement models.

Topaz models enhance media you supply. They upscale, denoise, sharpen and restore an existing image or video. They do not generate media from a text prompt, so the input file is the required part of the request and a text prompt is ignored.

Setup

The Topaz Labs provider is available in the @ai-sdk/topaz module. You can install it with

$ pnpm add @ai-sdk/topaz

Provider Instance

You can import the default provider instance topaz from @ai-sdk/topaz:

import { topaz } from '@ai-sdk/topaz';

If you need a customized setup, you can import createTopaz and create a provider instance with your settings:

import { createTopaz } from '@ai-sdk/topaz';

const topaz = createTopaz({
  apiKey: process.env.TOPAZ_API_KEY,
});

You can use the following optional settings to customize the Topaz Labs provider instance:

  • apiKey string

    API key that is being sent as the X-API-Key header. It defaults to the TOPAZ_API_KEY environment variable.

  • baseURL string

    Use a different URL prefix for API calls, e.g. to use proxy servers. The default prefix is https://api.topazlabs.com.

  • headers Record<string, string>

    Custom headers to include in the requests.

  • fetch (input: RequestInfo, init?: RequestInit) => Promise<Response>

    Custom fetch implementation.

Image Models

You can create Topaz image models using topaz.image():

import { topaz } from '@ai-sdk/topaz';
import { generateImage } from 'ai';

const { images } = await generateImage({
  model: topaz.image('wonder-3.5'),
  prompt: {
    images: ['https://example.com/photo.jpg'],
  },
});

The image to enhance (JPEG, PNG or TIFF) is passed through the prompt's images. The Topaz image API is asynchronous: the provider submits the job, polls until it finishes, and downloads the result, so generateImage resolves with the enhanced image.

Model Capabilities

ModelTopaz modelDescription
wonder-3.5Wonder 3.5Generative upscaling and detail recovery

Passing a raw Topaz model name (for example Wonder 3.5) also works, and unknown ids are forwarded to the API unchanged.

Image Provider Options

import { topaz, type TopazImageModelOptions } from '@ai-sdk/topaz';
import { generateImage } from 'ai';

const { images } = await generateImage({
  model: topaz.image('wonder-3.5'),
  prompt: {
    images: ['https://example.com/photo.jpg'],
  },
  size: '4096x4096',
  providerOptions: {
    topaz: {
      enhancementStrength: 'high',
      grain: true,
      grainDensity: 0.3,
      outputFormat: 'png',
    } satisfies TopazImageModelOptions,
  },
});
  • enhancementStrength 'low' | 'medium' | 'high': how aggressively to enhance. Defaults to high.
  • grain boolean: add grain to the output. Defaults to false.
  • grainDensity number: grain intensity, 0 to 1. Defaults to 0.5.
  • grainModel 'silver' | 'gaussian' | 'grey': grain model. Defaults to silver.
  • grainSize number: grain particle size, 1 to 5. Defaults to 1.
  • grainStrength number: grain effect strength, 0 to 1. Defaults to 0.5.
  • inputWidth / inputHeight number: input dimensions in pixels. Topaz infers these from the upload when omitted.
  • outputWidth / outputHeight number: output dimensions in pixels, 1 to 32000. These take precedence over the dimensions derived from size.
  • outputFormat 'jpeg' | 'jpg' | 'png' | 'tiff' | 'tif': output format. Topaz defaults to jpeg.
  • cropToFill boolean: crop the output to fill the requested dimensions. Defaults to false.
  • webhookUrl string: URL to receive job-status webhooks.
  • pollIntervalMillis number: status poll interval. Defaults to 2000.
  • pollTimeoutMillis number: maximum time to wait for the job. Defaults to 600000. The provider cancels the Topaz job when this runs out or the call is aborted, since Topaz charges on completion.

aspectRatio, seed, mask and n greater than 1 are not supported and produce warnings.

Image Provider Metadata

providerMetadata.topaz.images[] on the result contains, for each image:

  • processId string: the Topaz job id.
  • credits number: the credits Topaz charged for the job.
  • width / height number: the output dimensions.
  • format string: the output format.

Video Models

You can create Topaz video models using topaz.video():

import { topaz } from '@ai-sdk/topaz';
import { experimental_generateVideo as generateVideo } from 'ai';

const { videos } = await generateVideo({
  model: topaz.video('proteus'),
  prompt: '',
  inputReferences: ['https://example.com/clip.mp4'],
  resolution: '3840x2160',
});

The video to enhance is passed through inputReferences, and resolution sets the output resolution. Starlight models also need source metadata. generateVideo requires a prompt, so pass an empty string: Topaz ignores text, and a non-empty prompt produces a warning.

Model Capabilities

ModelTopaz modelDescription
proteusprob-4Detail-preserving upscaling with fine control
starlight-precise-2.6slp-2.6Generative upscaling with high fidelity

Passing a raw Topaz filter model name (for example slp-2.5) also works, and unknown ids are forwarded to the API unchanged.

Input Video

A URL input is handed to Topaz, which fetches it itself. A file input is uploaded to Topaz. Either way processing starts once Topaz has the video, and the only required setting is the output resolution (from resolution or output.width / output.height).

Source Metadata

The source provider option describes the input video. The AI SDK does not inspect media files, so the values come from your side:

  • Starlight models require it. Topaz rejects Starlight requests without it and prices them from these values, so they must describe the real video.
  • For other models it is optional. When it is set, Topaz returns a cost estimate as soon as the request is created.

Setting any of width, height, duration or frameRate requires all four. The output resolution and frame rate default to the source values.

FieldWhere it comes from
resolutionsource.width and source.height.
durationsource.duration.
frameRatesource.frameRate.
frameCountsource.frameCount, or duration * frameRate when it is omitted.
containersource.container, or the input's media type or URL extension.
sizeThe input bytes (file inputs only).
const { videos } = await generateVideo({
  model: topaz.video('starlight-precise-2.6'),
  prompt: '',
  inputReferences: ['https://example.com/clip.mp4'],
  resolution: '3840x2160',
  providerOptions: {
    topaz: {
      source: {
        width: 1920,
        height: 1080,
        duration: 10,
        frameRate: 30,
        frameCount: 300,
      },
    },
  },
});

Set source.frameCount explicitly for variable-frame-rate input, where duration * frameRate is not exact.

Video Provider Options

Structural options:

  • source object: input video metadata, width, height, duration, frameRate, frameCount and container. See Source Metadata.
  • output object: output settings.
    • width / height: output dimensions. These take precedence over resolution.
    • frameRate: output frame rate, taking precedence over fps. Topaz only changes the frame rate when a frame-interpolation filter is present.
    • audioTransfer ('Copy' | 'Convert' | 'None', default Copy), audioCodec ('AAC' | 'AC3' | 'PCM', default AAC), audioBitrate.
    • videoEncoder ('AV1' | 'H264' | 'H265' | 'ProRes' | 'VP9', Topaz defaults to H265), videoProfile, videoBitrate, dynamicCompressionLevel ('Low' | 'Mid' | 'High').
    • container ('mp4' | 'mov' | 'mkv' | 'avi' | 'webm'): defaults to the input container when it is mov or mkv, otherwise mp4. ProRes always produces mov, AV1 and VP9 always produce mp4.
    • cropToFit: center-crop to the output dimensions.
  • additionalFilters Array<Record<string, unknown>>: extra filters[] entries, e.g. a frame-interpolation filter. Each entry must include a model key.
  • filter Record<string, unknown>: escape hatch merged into the model's filter entry, overriding the typed options below.

Proteus filter settings: videoType, auto, fieldOrder, focusFixLevel, compression, details, prenoise, noise, halo, preblur, blur, grain, grainSigma, grainSize, grainType, recoverOriginalDetailValue.

Starlight Precise filter settings: sharpness, videoBitDepth, videoCodec, videoProfile, watermark.

See the Proteus and Starlight Precise 2.6 references for the accepted ranges, and Create Video Request for the accepted encoder and profile combinations.

A non-empty prompt, aspectRatio, seed, duration, generateAudio, frameImages and n greater than 1 are not supported and produce warnings.

Long-Running Operations

Video enhancement takes minutes, so Topaz video models implement the AI SDK's async operation protocol. generateVideo polls to completion, and long clips can exceed its default 10 minute timeout, so raise poll.timeoutMs when needed. Use experimental_startVideo when you would rather persist the operation and check its status later:

import { topaz } from '@ai-sdk/topaz';
import { experimental_startVideo as startVideo } from 'ai';

const operation = await startVideo({
  model: topaz.video('proteus'),
  prompt: '',
  inputReferences: ['https://example.com/clip.mp4'],
  resolution: '3840x2160',
});

If the upload fails after the request is created, the provider cancels the Topaz request so any reserved credits are refunded.

Video Provider Metadata

Topaz estimates the cost of a video request in credits as a [lowerBound, upperBound] range and bills the lower bound.

The start result's providerMetadata.topaz contains the requestId and, when Topaz could estimate the cost at request time, estimatedCredits. Topaz can do that when source metadata is set. It is informational only: the completed status carries the billed value.

The completed status's providerMetadata.topaz contains:

  • requestId string: the Topaz request id.
  • credits number: the credits Topaz bills for the request (the lower bound of its final estimate).
  • estimatedCredits [number, number]: the final cost range.
  • outputSize string: the size of the enhanced video.
  • expiresAt number: when the download URL expires, in milliseconds since the Unix epoch.

A failed request reports Topaz's errorCode (for example CREDIT_DIFFERENCE when Topaz's estimate after reading the video diverged from the first one, in which case it refunds the credits) in both the error message and providerMetadata.topaz.errorCode.