Skip to content

Commit 2db5b9d

Browse files
GuinersGuinersgemini-code-assist[bot]holtskinner
authored
feat(genai): Adding videogen samples (#4197)
* adding videogen samples and tests * Update genai/test/videogen-with-img.test.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * adding videogen samples and tests * code review fix * fixing failed tests * fixing samples * Update genai/video-generation/videogen-with-txt.js Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com> * Update model ID to use veo 3.1 fast * Move video-generation tests to dedicated directory --------- Co-authored-by: Guiners <rkoza@softserveinc.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
1 parent b2c188e commit 2db5b9d

File tree

6 files changed

+272
-0
lines changed

6 files changed

+272
-0
lines changed

genai/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
"test": "c8 mocha -p -j 2 --timeout 2400000 test/*.test.js test/**/*.test.js"
1414
},
1515
"dependencies": {
16+
"@google-cloud/storage": "^7.17.3",
1617
"@google/genai": "1.30.0",
1718
"axios": "^1.6.2",
1819
"canvas": "^3.2.0",
1920
"google-auth-library": "^10.3.0",
2021
"luxon": "^3.7.1",
22+
"node-fetch": "^3.3.2",
2123
"openai": "^5.19.1",
2224
"proxyquire": "^2.1.3",
2325
"supertest": "^7.0.0"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "nodejs-genai-video-generation-samples",
3+
"version": "0.0.1",
4+
"private": true,
5+
"license": "Apache-2.0",
6+
"author": "Google LLC",
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
10+
},
11+
"engines": {
12+
"node": ">=16.0.0"
13+
},
14+
"files": [
15+
"*.js"
16+
],
17+
"scripts": {
18+
"test": "c8 mocha -p -j 2 --timeout 2400000 test/*.test.js test/**/*.test.js"
19+
},
20+
"dependencies": {
21+
"@google-cloud/storage": "^7.17.3",
22+
"@google/genai": "1.30.0"
23+
},
24+
"devDependencies": {
25+
"c8": "^10.0.0",
26+
"chai": "^4.5.0",
27+
"mocha": "^10.0.0"
28+
}
29+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
const {assert} = require('chai');
18+
const {describe, it} = require('mocha');
19+
const {Storage} = require('@google-cloud/storage');
20+
21+
const location = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
const projectId = process.env.CAIP_PROJECT_ID;
23+
const sample = require('../videogen-with-img.js');
24+
const {delay} = require('../../test/util');
25+
26+
const storage = new Storage();
27+
28+
const GCS_OUTPUT_BUCKET = 'nodejs-docs-samples-tests';
29+
30+
async function gcs_output_uri() {
31+
const dt = new Date();
32+
const prefix = `video_output/${dt.toISOString()}`;
33+
const fullUri = `gs://${GCS_OUTPUT_BUCKET}/${prefix}`;
34+
35+
return {
36+
uri: fullUri,
37+
async cleanup() {
38+
const [files] = await storage.bucket(GCS_OUTPUT_BUCKET).getFiles({
39+
prefix,
40+
});
41+
for (const file of files) {
42+
await file.delete();
43+
}
44+
},
45+
};
46+
}
47+
48+
describe('videogen-with-img', async () => {
49+
it('should generate video content from an image', async function () {
50+
this.timeout(180000);
51+
this.retries(4);
52+
await delay(this.test);
53+
const gscOutput = gcs_output_uri();
54+
const gscUri = (await gscOutput).uri;
55+
const output = await sample.generateVideo(gscUri, projectId, location);
56+
console.log('output', output);
57+
assert(output);
58+
});
59+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
const {assert} = require('chai');
18+
const {describe, it} = require('mocha');
19+
const {Storage} = require('@google-cloud/storage');
20+
21+
const location = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
const projectId = process.env.CAIP_PROJECT_ID;
23+
const sample = require('../videogen-with-txt.js');
24+
const {delay} = require('../../test/util');
25+
26+
const storage = new Storage();
27+
28+
const GCS_OUTPUT_BUCKET = 'nodejs-docs-samples-tests';
29+
30+
async function gcs_output_uri() {
31+
const dt = new Date();
32+
const prefix = `text_output/${dt.toISOString()}`;
33+
const fullUri = `gs://${GCS_OUTPUT_BUCKET}/${prefix}`;
34+
35+
return {
36+
uri: fullUri,
37+
async cleanup() {
38+
const [files] = await storage.bucket(GCS_OUTPUT_BUCKET).getFiles({
39+
prefix,
40+
});
41+
for (const file of files) {
42+
await file.delete();
43+
}
44+
},
45+
};
46+
}
47+
48+
describe('videogen-with-txt', async () => {
49+
it('should generate video content from a text prompt', async function () {
50+
this.timeout(180000);
51+
this.retries(4);
52+
await delay(this.test);
53+
const gscOutput = gcs_output_uri();
54+
const gscUri = (await gscOutput).uri;
55+
const output = await sample.generateVideo(gscUri, projectId, location);
56+
console.log('output', output);
57+
assert(output);
58+
});
59+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// [START googlegenaisdk_videogen_with_img]
18+
const {GoogleGenAI} = require('@google/genai');
19+
20+
const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
21+
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
23+
async function generateVideo(
24+
outputGcsUri,
25+
projectId = GOOGLE_CLOUD_PROJECT,
26+
location = GOOGLE_CLOUD_LOCATION
27+
) {
28+
const client = new GoogleGenAI({
29+
vertexai: true,
30+
project: projectId,
31+
location: location,
32+
});
33+
34+
let operation = await client.models.generateVideos({
35+
model: 'veo-3.1-fast-generate-001',
36+
prompt:
37+
'Extreme close-up of a cluster of vibrant wildflowers swaying gently in a sun-drenched meadow',
38+
image: {
39+
gcsUri: 'gs://cloud-samples-data/generative-ai/image/flowers.png',
40+
mimeType: 'image/png',
41+
},
42+
config: {
43+
aspectRatio: '16:9',
44+
outputGcsUri: outputGcsUri,
45+
},
46+
});
47+
48+
while (!operation.done) {
49+
await new Promise(resolve => setTimeout(resolve, 15000));
50+
operation = await client.operations.get({operation: operation});
51+
console.log(operation);
52+
}
53+
54+
if (operation.response) {
55+
console.log(operation.response.generatedVideos[0].video.uri);
56+
}
57+
return operation;
58+
}
59+
60+
// [END googlegenaisdk_videogen_with_img]
61+
62+
module.exports = {
63+
generateVideo,
64+
};
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// [START googlegenaisdk_videogen_with_txt]
18+
const {GoogleGenAI} = require('@google/genai');
19+
20+
const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
21+
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
23+
async function generateVideo(
24+
outputGcsUri,
25+
projectId = GOOGLE_CLOUD_PROJECT,
26+
location = GOOGLE_CLOUD_LOCATION
27+
) {
28+
const client = new GoogleGenAI({
29+
vertexai: true,
30+
project: projectId,
31+
location: location,
32+
});
33+
34+
let operation = await client.models.generateVideos({
35+
model: 'veo-3.1-fast-generate-001',
36+
prompt: 'a cat reading a book',
37+
config: {
38+
aspectRatio: '16:9',
39+
outputGcsUri: outputGcsUri,
40+
},
41+
});
42+
43+
while (!operation.done) {
44+
await new Promise(resolve => setTimeout(resolve, 15000));
45+
operation = await client.operations.get({operation: operation});
46+
console.log(operation);
47+
}
48+
49+
if (operation.response) {
50+
console.log(operation.response.generatedVideos[0].video.uri);
51+
}
52+
return operation;
53+
}
54+
55+
// [END googlegenaisdk_videogen_with_txt]
56+
57+
module.exports = {
58+
generateVideo,
59+
};

0 commit comments

Comments
 (0)