diff --git a/genai/package.json b/genai/package.json index 2c370bd447..6a8760a274 100644 --- a/genai/package.json +++ b/genai/package.json @@ -13,13 +13,14 @@ "test": "c8 mocha -p -j 2 --timeout 2400000 test/*.test.js test/**/*.test.js" }, "dependencies": { + "@google-cloud/storage": "^7.17.3", "@google/genai": "1.20.0", "axios": "^1.6.2", "google-auth-library": "^10.3.0", "luxon": "^3.7.1", - "proxyquire": "^2.1.3", "node-fetch": "^3.3.2", "openai": "^5.19.1", + "proxyquire": "^2.1.3", "supertest": "^7.0.0" }, "devDependencies": { diff --git a/genai/test/videogen-with-img.test.js b/genai/test/videogen-with-img.test.js new file mode 100644 index 0000000000..5999464380 --- /dev/null +++ b/genai/test/videogen-with-img.test.js @@ -0,0 +1,59 @@ +// 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 +// +// https://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. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const {Storage} = require('@google-cloud/storage'); + +const location = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const projectId = process.env.CAIP_PROJECT_ID; +const sample = require('../video-generation/videogen-with-img.js'); +const {delay} = require('./util'); + +const storage = new Storage(); + +const GCS_OUTPUT_BUCKET = 'nodejs-docs-samples-tests'; + +async function gcs_output_uri() { + const dt = new Date(); + const prefix = `video_output/${dt.toISOString()}`; + const fullUri = `gs://${GCS_OUTPUT_BUCKET}/${prefix}`; + + return { + uri: fullUri, + async cleanup() { + const [files] = await storage.bucket(GCS_OUTPUT_BUCKET).getFiles({ + prefix, + }); + for (const file of files) { + await file.delete(); + } + }, + }; +} + +describe('videogen-with-img', async () => { + it('should generate video content from an image', async function () { + this.timeout(180000); + this.retries(4); + await delay(this.test); + const gscOutput = gcs_output_uri(); + const gscUri = (await gscOutput).uri; + const output = await sample.generateVideo(gscUri, projectId, location); + console.log('output', output); + assert(output); + }); +}); diff --git a/genai/test/videogen-with-txt.test.js b/genai/test/videogen-with-txt.test.js new file mode 100644 index 0000000000..adb3995fc9 --- /dev/null +++ b/genai/test/videogen-with-txt.test.js @@ -0,0 +1,59 @@ +// 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 +// +// https://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. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const {Storage} = require('@google-cloud/storage'); + +const location = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const projectId = process.env.CAIP_PROJECT_ID; +const sample = require('../video-generation/videogen-with-txt.js'); +const {delay} = require('./util'); + +const storage = new Storage(); + +const GCS_OUTPUT_BUCKET = 'nodejs-docs-samples-tests'; + +async function gcs_output_uri() { + const dt = new Date(); + const prefix = `text_output/${dt.toISOString()}`; + const fullUri = `gs://${GCS_OUTPUT_BUCKET}/${prefix}`; + + return { + uri: fullUri, + async cleanup() { + const [files] = await storage.bucket(GCS_OUTPUT_BUCKET).getFiles({ + prefix, + }); + for (const file of files) { + await file.delete(); + } + }, + }; +} + +describe('videogen-with-txt', async () => { + it('should generate video content from a text prompt', async function () { + this.timeout(180000); + this.retries(4); + await delay(this.test); + const gscOutput = gcs_output_uri(); + const gscUri = (await gscOutput).uri; + const output = await sample.generateVideo(gscUri, projectId, location); + console.log('output', output); + assert(output); + }); +}); diff --git a/genai/video-generation/videogen-with-img.js b/genai/video-generation/videogen-with-img.js new file mode 100644 index 0000000000..fa8ae023fe --- /dev/null +++ b/genai/video-generation/videogen-with-img.js @@ -0,0 +1,64 @@ +// 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 +// +// https://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. + +'use strict'; + +// [START googlegenaisdk_videogen_with_img] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; +const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global'; + +async function generateVideo( + outputGcsUri, + projectId = GOOGLE_CLOUD_PROJECT, + location = GOOGLE_CLOUD_LOCATION +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + location: location, + }); + + let operation = await client.models.generateVideos({ + model: 'veo-3.0-generate-preview', + prompt: + 'Extreme close-up of a cluster of vibrant wildflowers swaying gently in a sun-drenched meadow', + image: { + gcsUri: 'gs://cloud-samples-data/generative-ai/image/flowers.png', + mimeType: 'image/png', + }, + config: { + aspectRatio: '16:9', + outputGcsUri: outputGcsUri, + }, + }); + + while (!operation.done) { + await new Promise(resolve => setTimeout(resolve, 15000)); + operation = await client.operations.get({operation: operation}); + console.log(operation); + } + + if (operation.response) { + console.log(operation.response.generatedVideos[0].video.uri); + } + return operation.response.generatedVideos[0].video.uri; +} + +// [END googlegenaisdk_videogen_with_img] + +module.exports = { + generateVideo, +}; diff --git a/genai/video-generation/videogen-with-txt.js b/genai/video-generation/videogen-with-txt.js new file mode 100644 index 0000000000..2fa7db0400 --- /dev/null +++ b/genai/video-generation/videogen-with-txt.js @@ -0,0 +1,59 @@ +// 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 +// +// https://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. + +'use strict'; + +// [START googlegenaisdk_videogen_with_txt] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; +const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global'; + +async function generateVideo( + outputGcsUri, + projectId = GOOGLE_CLOUD_PROJECT, + location = GOOGLE_CLOUD_LOCATION +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + location: location, + }); + + let operation = await client.models.generateVideos({ + model: 'veo-3.0-generate-001', + prompt: 'a cat reading a book', + config: { + aspectRatio: '16:9', + outputGcsUri: outputGcsUri, + }, + }); + + while (!operation.done) { + await new Promise(resolve => setTimeout(resolve, 15000)); + operation = await client.operations.get({operation: operation}); + console.log(operation); + } + + if (operation.response) { + console.log(operation.response.generatedVideos[0].video.uri); + } + return operation.response.generatedVideos[0].video.uri; +} + +// [END googlegenaisdk_videogen_with_txt] + +module.exports = { + generateVideo, +};