Skip to content

Video Generation

Gunpal Jain edited this page Nov 15, 2026 · 2 revisions

Video Generation

VideoGenerationModel generates videos with Google's Veo models on Vertex AI. Generation is a long-running operation: you start it, then poll until the video is ready.

Veo on the Gemini API is retired. On the Gemini API, VideoGenerationModel.GenerateVideosAsync throws NotSupportedException straight away instead of sending a request the API would reject. To generate video on the Gemini API, use a Gemini Omni model (GoogleAIModels.Video.GeminiOmni12Flash, or InteractionModels.GeminiOmni12Flash in the Interactions API) through the Interactions API.

NuGet packages

dotnet add package Google_GenerativeAI
dotnet add package Google_GenerativeAI.Auth   # service account / OAuth authenticators for Vertex AI

Video generation is billed per second of output and can be expensive; start with short durations and one video.

Models (Vertex AI)

Constant (VertexAIModels.Video) Model ID
Veo31GeneratePreview veo-3.1-generate-preview
Veo31FastGeneratePreview veo-3.1-fast-generate-preview
Veo3Generate001 veo-3.0-generate-001
Veo3FastGenerate001 veo-3.0-fast-generate-001
Veo3GeneratePreview veo-3.0-generate-preview
Veo3FastGeneratePreview veo-3.0-fast-generate-preview
Veo2Generate001 veo-2.0-generate-001 (default for CreateVideoGenerationModel())

The GoogleAIModels.Video.Veo* constants are marked [Obsolete] because those models are shut down on the Gemini API. Check the Vertex AI documentation for which Veo versions are currently available in your region.

Generating a video

using GenerativeAI;
using GenerativeAI.Authenticators;
using GenerativeAI.Types;

var vertexAi = new VertexAI(
    projectId: "your-project-id",
    region: "us-central1",
    authenticator: new GoogleServiceAccountAuthenticator("service-account.json"));

var videoModel = vertexAi.CreateVideoGenerationModel(VertexAIModels.Video.Veo31FastGenerate001);

var operation = await videoModel.GenerateVideosAsync(
    "A dog catching a ball in a sunny park",
    config: new GenerateVideosConfig
    {
        AspectRatio = VideoAspectRatio.LANDSCAPE_16_9,
        DurationSeconds = 5,
        NumberOfVideos = 1,
        Resolution = VideoResolution.HD_720P,
        PersonGeneration = VideoPersonGeneration.AllowAdult,
        EnhancePrompt = true
    });

var result = await videoModel.AwaitForLongRunningOperation(operation!.Name!);

if (result?.Done == true && result.Result?.GeneratedVideos is { Count: > 0 } videos)
{
    var video = videos[0];
    if (video.VideoBytes != null)
        await File.WriteAllBytesAsync("dog.mp4", video.VideoBytes);
    else
        Console.WriteLine($"Video stored at {video.Uri}"); // when OutputGcsUri is set
}

You can also construct the model directly: new VideoGenerationModel(platformAdapter, VertexAIModels.Video.Veo31FastGenerate001), where platformAdapter must be a VertextPlatformAdapter.

API

Member Description
GenerateVideosAsync(GenerateVideosRequest request, CancellationToken) Starts generation (predictLongRunning). Returns a GenerateVideosOperation.
GenerateVideosAsync(string prompt, ImageSample? referenceImage = null, GenerateVideosConfig? config = null, CancellationToken) Same, from a prompt and optional starting image.
AwaitForLongRunningOperation(string operationId, int? timeOut = null, CancellationToken) Polls every second until the operation is done (for up to 10 minutes). Throws VertexAIException if the operation finished with an error.
GetVideoGenerationStatusAsync(string operationId, int? timeOut = null, CancellationToken) Checks the operation once. Use it to poll on your own schedule.
ModelName The model in use.

GenerateVideosOperation has Name, Done, Error and, when done, Result (GenerateVideosResponse):

  • GeneratedVideos: a List<Video>; each Video has VideoBytes (also exposed as BytesBase64Encoded), Uri and MimeType.
  • RaiMediaFilteredCount and RaiMediaFilteredReasons: videos removed by safety filters.

Image-to-video

Pass a starting frame as an ImageSample (bytes or a Cloud Storage URI):

var firstFrame = new ImageSample
{
    ImageBytes = await File.ReadAllBytesAsync("first-frame.png"),
    MimeType = "image/png"
    // or: GcsUri = "gs://bucket/first-frame.png"
};

var operation = await videoModel.GenerateVideosAsync(
    "The camera slowly pulls back to reveal the whole city",
    referenceImage: firstFrame,
    config: new GenerateVideosConfig { DurationSeconds = 5 });

GenerateVideosConfig

These settings are sent to Vertex AI by VideoGenerationModel:

Property Type Description
NumberOfVideos int? Number of videos to generate
DurationSeconds int? Length of each video
AspectRatio VideoAspectRatio? LANDSCAPE_16_9 or PORTRAIT_9_16
Resolution VideoResolution? HD_720P or FullHD_1080P
Fps int? Frames per second
Seed int? Seed for more repeatable results
NegativePrompt string? What to avoid
EnhancePrompt bool? Let the service rewrite the prompt
PersonGeneration VideoPersonGeneration? DontAllow or AllowAdult
OutputGcsUri string? Cloud Storage location for the output (then Video.Uri is set instead of bytes)
PubsubTopic string? Pub/Sub topic for completion notifications

GenerateVideosConfig also defines GenerateAudio, LastFrame, ReferenceImages (VideoGenerationReferenceImage with VideoGenerationReferenceType.STYLE/ASSET), Mask (VideoGenerationMask with VideoGenerationMaskMode) and CompressionQuality (VideoCompressionQuality.OPTIMIZED/LOSSLESS). VideoGenerationModel does not currently forward these to the Vertex AI request.

Related pages

Clone this wiki locally