diff --git a/genai/snippets/src/main/java/genai/videogeneration/VideoGenWithImg.java b/genai/snippets/src/main/java/genai/videogeneration/VideoGenWithImg.java new file mode 100644 index 00000000000..8708791c52d --- /dev/null +++ b/genai/snippets/src/main/java/genai/videogeneration/VideoGenWithImg.java @@ -0,0 +1,85 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.videogeneration; + +// [START googlegenaisdk_videogen_with_img] + +import com.google.genai.Client; +import com.google.genai.types.GenerateVideosConfig; +import com.google.genai.types.GenerateVideosOperation; +import com.google.genai.types.GenerateVideosResponse; +import com.google.genai.types.GeneratedVideo; +import com.google.genai.types.GetOperationConfig; +import com.google.genai.types.Image; +import com.google.genai.types.Video; +import java.util.concurrent.TimeUnit; + +public class VideoGenWithImg { + + public static void main(String[] args) throws InterruptedException { + // TODO(developer): Replace these variables before running the sample. + String modelId = "veo-3.0-generate-preview"; + String outputGcsUri = "gs://your-bucket/your-prefix"; + generateContent(modelId, outputGcsUri); + } + + // Generates a video with an image and a text prompt. + public static String generateContent(String modelId, String outputGcsUri) + throws InterruptedException { + // Client Initialization. Once created, it can be reused for multiple requests. + try (Client client = Client.builder().location("global").vertexAI(true).build()) { + + GenerateVideosOperation operation = + client.models.generateVideos( + modelId, + "Extreme close-up of a cluster of vibrant wildflowers" + + " swaying gently in a sun-drenched meadow.", + Image.builder() + .gcsUri("gs://cloud-samples-data/generative-ai/image/flowers.png") + .mimeType("image/png") + .build(), + GenerateVideosConfig.builder() + .aspectRatio("16:9") + .outputGcsUri(outputGcsUri) + .build()); + + while (!operation.done().orElse(false)) { + TimeUnit.SECONDS.sleep(15); + operation = + client.operations.getVideosOperation(operation, GetOperationConfig.builder().build()); + } + + String generatedVideoUri = + operation + .response() + .flatMap(GenerateVideosResponse::generatedVideos) + .flatMap(videos -> videos.stream().findFirst()) + .flatMap(GeneratedVideo::video) + .flatMap(Video::uri) + .orElseThrow( + () -> + new IllegalStateException( + "Could not get the URI from the generated video")); + + System.out.println("Generated video URI: " + generatedVideoUri); + // Example response: + // Generated video URI: gs://your-bucket/your-prefix/generated-video-123.mp4 + return generatedVideoUri; + } + } +} +// [END googlegenaisdk_videogen_with_img] diff --git a/genai/snippets/src/main/java/genai/videogeneration/VideoGenWithTxt.java b/genai/snippets/src/main/java/genai/videogeneration/VideoGenWithTxt.java new file mode 100644 index 00000000000..d29a40b1ea0 --- /dev/null +++ b/genai/snippets/src/main/java/genai/videogeneration/VideoGenWithTxt.java @@ -0,0 +1,80 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.videogeneration; + +// [START googlegenaisdk_videogen_with_txt] + +import com.google.genai.Client; +import com.google.genai.types.GenerateVideosConfig; +import com.google.genai.types.GenerateVideosOperation; +import com.google.genai.types.GenerateVideosResponse; +import com.google.genai.types.GenerateVideosSource; +import com.google.genai.types.GeneratedVideo; +import com.google.genai.types.GetOperationConfig; +import com.google.genai.types.Video; +import java.util.concurrent.TimeUnit; + +public class VideoGenWithTxt { + + public static void main(String[] args) throws InterruptedException { + // TODO(developer): Replace these variables before running the sample. + String modelId = "veo-3.0-generate-001"; + String outputGcsUri = "gs://your-bucket/your-prefix"; + generateContent(modelId, outputGcsUri); + } + + // Generates a video with a text prompt. + public static String generateContent(String modelId, String outputGcsUri) + throws InterruptedException { + // Client Initialization. Once created, it can be reused for multiple requests. + try (Client client = Client.builder().location("global").vertexAI(true).build()) { + + GenerateVideosOperation operation = + client.models.generateVideos( + modelId, + GenerateVideosSource.builder().prompt("a cat reading a book").build(), + GenerateVideosConfig.builder() + .aspectRatio("16:9") + .outputGcsUri(outputGcsUri) + .build()); + + while (!operation.done().orElse(false)) { + TimeUnit.SECONDS.sleep(15); + operation = + client.operations.getVideosOperation(operation, GetOperationConfig.builder().build()); + } + + String generatedVideoUri = + operation + .response() + .flatMap(GenerateVideosResponse::generatedVideos) + .flatMap(videos -> videos.stream().findFirst()) + .flatMap(GeneratedVideo::video) + .flatMap(Video::uri) + .orElseThrow( + () -> + new IllegalStateException( + "Could not get the URI from the generated video")); + + System.out.println("Generated video URI: " + generatedVideoUri); + // Example response: + // Generated video URI: gs://your-bucket/your-prefix/generated-video-123.mp4 + return generatedVideoUri; + } + } +} +// [END googlegenaisdk_videogen_with_txt] diff --git a/genai/snippets/src/test/java/genai/videogeneration/VideoGenerationIT.java b/genai/snippets/src/test/java/genai/videogeneration/VideoGenerationIT.java new file mode 100644 index 00000000000..412bc22f7af --- /dev/null +++ b/genai/snippets/src/test/java/genai/videogeneration/VideoGenerationIT.java @@ -0,0 +1,96 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.videogeneration; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.api.gax.paging.Page; +import com.google.cloud.storage.Blob; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.UUID; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class VideoGenerationIT { + + private static final String VIDEO_GEN_MODEL = "veo-3.0-generate-001"; + private static final String VIDEO_GEN_PREVIEW_MODEL = "veo-3.0-generate-preview"; + private static final String BUCKET_NAME = "java-docs-samples-testing"; + private static final String PREFIX = "genai-video-generation-" + UUID.randomUUID(); + private static final String OUTPUT_GCS_URI = String.format("gs://%s/%s", BUCKET_NAME, PREFIX); + private ByteArrayOutputStream bout; + private PrintStream out; + + // Check if the required environment variables are set. + public static void requireEnvVar(String envVarName) { + assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) + .that(System.getenv(envVarName)) + .isNotEmpty(); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @AfterClass + public static void cleanup() { + Storage storage = StorageOptions.getDefaultInstance().getService(); + Page blobs = storage.list(BUCKET_NAME, Storage.BlobListOption.prefix(PREFIX)); + + for (Blob blob : blobs.iterateAll()) { + storage.delete(blob.getBlobId()); + } + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + bout.reset(); + } + + @Test + public void testVideoGenWithImg() throws InterruptedException { + String response = VideoGenWithImg.generateContent(VIDEO_GEN_PREVIEW_MODEL, OUTPUT_GCS_URI); + assertThat(response).isNotEmpty(); + assertThat(bout.toString()).contains(OUTPUT_GCS_URI); + } + + @Test + public void testVideoGenWithTxt() throws InterruptedException { + String response = VideoGenWithTxt.generateContent(VIDEO_GEN_MODEL, OUTPUT_GCS_URI); + assertThat(response).isNotEmpty(); + assertThat(bout.toString()).contains(OUTPUT_GCS_URI); + } +}