Skip to content
This repository was archived by the owner on Jul 20, 2023. It is now read-only.

Commit 7508d64

Browse files
authored
feat: add spritesheet samples and tests. Remove unneeded list jobs ca… (#43)
1 parent 19a8e6c commit 7508d64

File tree

3 files changed

+340
-14
lines changed

3 files changed

+340
-14
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* Copyright 2021, Google, Inc.
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+
* http://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+
16+
'use strict';
17+
18+
function main(projectId, location, inputUri, outputUri) {
19+
// [START transcoder_create_job_with_periodic_images_spritesheet]
20+
/**
21+
* TODO(developer): Uncomment these variables before running the sample.
22+
*/
23+
// projectId = 'my-project-id';
24+
// location = 'us-central1';
25+
// inputUri = 'gs://my-bucket/my-video-file';
26+
// outputUri = 'gs://my-bucket/my-output-folder/';
27+
28+
// Imports the Transcoder library
29+
const {TranscoderServiceClient} = require('@google-cloud/video-transcoder');
30+
31+
// Instantiates a client
32+
const transcoderServiceClient = new TranscoderServiceClient();
33+
34+
async function createJobWithPeriodicImagesSpritesheet() {
35+
// Construct request
36+
const request = {
37+
parent: transcoderServiceClient.locationPath(projectId, location),
38+
job: {
39+
inputUri: inputUri,
40+
outputUri: outputUri,
41+
config: {
42+
elementaryStreams: [
43+
{
44+
key: 'video-stream0',
45+
videoStream: {
46+
codec: 'h264',
47+
heightPixels: 360,
48+
widthPixels: 640,
49+
bitrateBps: 550000,
50+
frameRate: 60,
51+
},
52+
},
53+
{
54+
key: 'audio-stream0',
55+
audioStream: {
56+
codec: 'aac',
57+
bitrateBps: 64000,
58+
},
59+
},
60+
],
61+
muxStreams: [
62+
{
63+
key: 'sd',
64+
container: 'mp4',
65+
elementaryStreams: ['video-stream0', 'audio-stream0'],
66+
},
67+
],
68+
spriteSheets: [
69+
{
70+
filePrefix: 'small-sprite-sheet',
71+
spriteHeightPixels: 32,
72+
spriteWidthPixels: 64,
73+
interval: {
74+
seconds: 7,
75+
},
76+
},
77+
{
78+
filePrefix: 'large-sprite-sheet',
79+
spriteHeightPixels: 72,
80+
spriteWidthPixels: 128,
81+
interval: {
82+
seconds: 7,
83+
},
84+
},
85+
],
86+
},
87+
},
88+
};
89+
90+
// Run request
91+
const [response] = await transcoderServiceClient.createJob(request);
92+
console.log(`Job: ${response.name}`);
93+
}
94+
95+
createJobWithPeriodicImagesSpritesheet();
96+
// [END transcoder_create_job_with_periodic_images_spritesheet]
97+
}
98+
99+
// node createJobWithPeriodicImagesSpritesheet.js <projectId> <location> <inputUri> <outputUri>
100+
process.on('unhandledRejection', err => {
101+
console.error(err.message);
102+
process.exitCode = 1;
103+
});
104+
main(...process.argv.slice(2));
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* Copyright 2021, Google, Inc.
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+
* http://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+
16+
'use strict';
17+
18+
function main(projectId, location, inputUri, outputUri) {
19+
// [START transcoder_create_job_with_set_number_images_spritesheet]
20+
/**
21+
* TODO(developer): Uncomment these variables before running the sample.
22+
*/
23+
// projectId = 'my-project-id';
24+
// location = 'us-central1';
25+
// inputUri = 'gs://my-bucket/my-video-file';
26+
// outputUri = 'gs://my-bucket/my-output-folder/';
27+
28+
// Imports the Transcoder library
29+
const {TranscoderServiceClient} = require('@google-cloud/video-transcoder');
30+
31+
// Instantiates a client
32+
const transcoderServiceClient = new TranscoderServiceClient();
33+
34+
async function createJobWithSetNumberImagesSpritesheet() {
35+
// Construct request
36+
const request = {
37+
parent: transcoderServiceClient.locationPath(projectId, location),
38+
job: {
39+
inputUri: inputUri,
40+
outputUri: outputUri,
41+
config: {
42+
elementaryStreams: [
43+
{
44+
key: 'video-stream0',
45+
videoStream: {
46+
codec: 'h264',
47+
heightPixels: 360,
48+
widthPixels: 640,
49+
bitrateBps: 550000,
50+
frameRate: 60,
51+
},
52+
},
53+
{
54+
key: 'audio-stream0',
55+
audioStream: {
56+
codec: 'aac',
57+
bitrateBps: 64000,
58+
},
59+
},
60+
],
61+
muxStreams: [
62+
{
63+
key: 'sd',
64+
container: 'mp4',
65+
elementaryStreams: ['video-stream0', 'audio-stream0'],
66+
},
67+
],
68+
spriteSheets: [
69+
{
70+
filePrefix: 'small-sprite-sheet',
71+
spriteHeightPixels: 32,
72+
spriteWidthPixels: 64,
73+
columnCount: 10,
74+
rowCount: 10,
75+
totalCount: 100,
76+
},
77+
{
78+
filePrefix: 'large-sprite-sheet',
79+
spriteHeightPixels: 72,
80+
spriteWidthPixels: 128,
81+
columnCount: 10,
82+
rowCount: 10,
83+
totalCount: 100,
84+
},
85+
],
86+
},
87+
},
88+
};
89+
90+
// Run request
91+
const [response] = await transcoderServiceClient.createJob(request);
92+
console.log(`Job: ${response.name}`);
93+
}
94+
95+
createJobWithSetNumberImagesSpritesheet();
96+
// [END transcoder_create_job_with_set_number_images_spritesheet]
97+
}
98+
99+
// node createJobWithSetNumberImagesSpritesheet.js <projectId> <location> <inputUri> <outputUri>
100+
process.on('unhandledRejection', err => {
101+
console.error(err.message);
102+
process.exitCode = 1;
103+
});
104+
main(...process.argv.slice(2));

samples/test/transcoder.test.js

Lines changed: 132 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ const outputUriForTemplate = `gs://${bucketName}/test-output-template/`;
4343
const outputUriForAdHoc = `gs://${bucketName}/test-output-adhoc/`;
4444
const outputUriForStaticOverlay = `gs://${bucketName}/test-output-static-overlay/`;
4545
const outputUriForAnimatedOverlay = `gs://${bucketName}/test-output-animated-overlay/`;
46+
const outputDirForSetNumberImagesSpritesheet =
47+
'test-output-set-number-spritesheet/';
48+
const outputUriForSetNumberImagesSpritesheet = `gs://${bucketName}/${outputDirForSetNumberImagesSpritesheet}`;
49+
const outputDirForPeriodicImagesSpritesheet =
50+
'test-output-periodic-spritesheet/';
51+
const outputUriForPeriodicImagesSpritesheet = `gs://${bucketName}/${outputDirForPeriodicImagesSpritesheet}`;
52+
// Spritesheets are generated from the input video into the bucket directories above.
53+
// Spritesheets use the following file naming conventions:
54+
const smallSpriteSheetFileName = 'small-sprite-sheet0000000000.jpeg';
55+
const largeSpriteSheetFileName = 'large-sprite-sheet0000000000.jpeg';
4656

4757
const cwd = path.join(__dirname, '..');
4858
const videoFile = `testdata/${testFileName}`;
@@ -56,6 +66,16 @@ function wait(ms) {
5666
});
5767
}
5868

69+
const checkFileExists = async function (bucketName, fileName) {
70+
const [files] = await storage.bucket(bucketName).getFiles();
71+
for (let i = 0; i < files.length; i++) {
72+
if (files[i].name === fileName) {
73+
return true;
74+
}
75+
}
76+
return false;
77+
};
78+
5979
before(async () => {
6080
assert(
6181
process.env.GOOGLE_CLOUD_PROJECT_NUMBER,
@@ -308,14 +328,6 @@ describe('Job with static overlay functions', () => {
308328
assert.ok(output.includes(jobName));
309329
});
310330

311-
it('should show a list of jobs', function () {
312-
const output = execSync(`node listJobs.js ${projectId} ${location}`, {
313-
cwd,
314-
});
315-
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.staticOverlayJobId}`;
316-
assert.ok(output.includes(jobName));
317-
});
318-
319331
it('should check that the job succeeded', async function () {
320332
this.retries(5);
321333
await wait(90000);
@@ -356,21 +368,127 @@ describe('Job with animated overlay functions', () => {
356368
assert.ok(output.includes(jobName));
357369
});
358370

359-
it('should show a list of jobs', function () {
360-
const output = execSync(`node listJobs.js ${projectId} ${location}`, {
361-
cwd,
362-
});
363-
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.animatedOverlayJobId}`;
371+
it('should check that the job succeeded', async function () {
372+
this.retries(5);
373+
await wait(90000);
374+
const output = execSync(
375+
`node getJobState.js ${projectId} ${location} ${this.animatedOverlayJobId}`,
376+
{cwd}
377+
);
378+
assert.ok(output.includes('Job state: SUCCEEDED'));
379+
});
380+
});
381+
382+
describe('Job with set number of images spritesheet', () => {
383+
before(function () {
384+
const output = execSync(
385+
`node createJobWithSetNumberImagesSpritesheet.js ${projectId} ${location} ${inputUri} ${outputUriForSetNumberImagesSpritesheet}`,
386+
{cwd}
387+
);
388+
assert.ok(
389+
output.includes(`projects/${projectNumber}/locations/${location}/jobs/`)
390+
);
391+
this.setNumberSpritesheetJobId = output.toString().split('/').pop();
392+
});
393+
394+
after(function () {
395+
const output = execSync(
396+
`node deleteJob.js ${projectId} ${location} ${this.setNumberSpritesheetJobId}`,
397+
{cwd}
398+
);
399+
assert.ok(output.includes('Deleted job'));
400+
});
401+
402+
it('should get a job', function () {
403+
const output = execSync(
404+
`node getJob.js ${projectId} ${location} ${this.setNumberSpritesheetJobId}`,
405+
{cwd}
406+
);
407+
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.setNumberSpritesheetJobId}`;
364408
assert.ok(output.includes(jobName));
365409
});
366410

367411
it('should check that the job succeeded', async function () {
368412
this.retries(5);
369413
await wait(90000);
370414
const output = execSync(
371-
`node getJobState.js ${projectId} ${location} ${this.animatedOverlayJobId}`,
415+
`node getJobState.js ${projectId} ${location} ${this.setNumberSpritesheetJobId}`,
372416
{cwd}
373417
);
374418
assert.ok(output.includes('Job state: SUCCEEDED'));
375419
});
420+
421+
it('should check that the spritesheet files exist in the bucket', async () => {
422+
assert.equal(
423+
await checkFileExists(
424+
bucketName,
425+
`${outputDirForSetNumberImagesSpritesheet}${smallSpriteSheetFileName}`
426+
),
427+
true
428+
);
429+
assert.equal(
430+
await checkFileExists(
431+
bucketName,
432+
`${outputDirForSetNumberImagesSpritesheet}${largeSpriteSheetFileName}`
433+
),
434+
true
435+
);
436+
});
437+
});
438+
439+
describe('Job with periodic images spritesheet', () => {
440+
before(function () {
441+
const output = execSync(
442+
`node createJobWithPeriodicImagesSpritesheet.js ${projectId} ${location} ${inputUri} ${outputUriForPeriodicImagesSpritesheet}`,
443+
{cwd}
444+
);
445+
assert.ok(
446+
output.includes(`projects/${projectNumber}/locations/${location}/jobs/`)
447+
);
448+
this.periodicSpritesheetJobId = output.toString().split('/').pop();
449+
});
450+
451+
after(function () {
452+
const output = execSync(
453+
`node deleteJob.js ${projectId} ${location} ${this.periodicSpritesheetJobId}`,
454+
{cwd}
455+
);
456+
assert.ok(output.includes('Deleted job'));
457+
});
458+
459+
it('should get a job', function () {
460+
const output = execSync(
461+
`node getJob.js ${projectId} ${location} ${this.periodicSpritesheetJobId}`,
462+
{cwd}
463+
);
464+
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.periodicSpritesheetJobId}`;
465+
assert.ok(output.includes(jobName));
466+
});
467+
468+
it('should check that the job succeeded', async function () {
469+
this.retries(5);
470+
await wait(90000);
471+
const output = execSync(
472+
`node getJobState.js ${projectId} ${location} ${this.periodicSpritesheetJobId}`,
473+
{cwd}
474+
);
475+
assert.ok(output.includes('Job state: SUCCEEDED'));
476+
});
477+
478+
it('should check that the spritesheet files exist in the bucket', async () => {
479+
assert.equal(
480+
await checkFileExists(
481+
bucketName,
482+
`${outputDirForPeriodicImagesSpritesheet}${smallSpriteSheetFileName}`
483+
),
484+
true
485+
);
486+
assert.equal(
487+
await checkFileExists(
488+
bucketName,
489+
`${outputDirForPeriodicImagesSpritesheet}${largeSpriteSheetFileName}`
490+
),
491+
true
492+
);
493+
});
376494
});

0 commit comments

Comments
 (0)