Skip to content

Commit

Permalink
feat: add spritesheet samples and tests. Remove unneeded list jobs ca… (
Browse files Browse the repository at this point in the history
  • Loading branch information
irataxy committed Jan 18, 2023
1 parent 1b941bb commit bee30e0
Show file tree
Hide file tree
Showing 3 changed files with 340 additions and 14 deletions.
104 changes: 104 additions & 0 deletions media/transcoder/createJobWithPeriodicImagesSpritesheet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright 2021, Google, Inc.
* 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.
*/

'use strict';

function main(projectId, location, inputUri, outputUri) {
// [START transcoder_create_job_with_periodic_images_spritesheet]
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// projectId = 'my-project-id';
// location = 'us-central1';
// inputUri = 'gs://my-bucket/my-video-file';
// outputUri = 'gs://my-bucket/my-output-folder/';

// Imports the Transcoder library
const {TranscoderServiceClient} = require('@google-cloud/video-transcoder');

// Instantiates a client
const transcoderServiceClient = new TranscoderServiceClient();

async function createJobWithPeriodicImagesSpritesheet() {
// Construct request
const request = {
parent: transcoderServiceClient.locationPath(projectId, location),
job: {
inputUri: inputUri,
outputUri: outputUri,
config: {
elementaryStreams: [
{
key: 'video-stream0',
videoStream: {
codec: 'h264',
heightPixels: 360,
widthPixels: 640,
bitrateBps: 550000,
frameRate: 60,
},
},
{
key: 'audio-stream0',
audioStream: {
codec: 'aac',
bitrateBps: 64000,
},
},
],
muxStreams: [
{
key: 'sd',
container: 'mp4',
elementaryStreams: ['video-stream0', 'audio-stream0'],
},
],
spriteSheets: [
{
filePrefix: 'small-sprite-sheet',
spriteHeightPixels: 32,
spriteWidthPixels: 64,
interval: {
seconds: 7,
},
},
{
filePrefix: 'large-sprite-sheet',
spriteHeightPixels: 72,
spriteWidthPixels: 128,
interval: {
seconds: 7,
},
},
],
},
},
};

// Run request
const [response] = await transcoderServiceClient.createJob(request);
console.log(`Job: ${response.name}`);
}

createJobWithPeriodicImagesSpritesheet();
// [END transcoder_create_job_with_periodic_images_spritesheet]
}

// node createJobWithPeriodicImagesSpritesheet.js <projectId> <location> <inputUri> <outputUri>
process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
104 changes: 104 additions & 0 deletions media/transcoder/createJobWithSetNumberImagesSpritesheet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright 2021, Google, Inc.
* 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.
*/

'use strict';

function main(projectId, location, inputUri, outputUri) {
// [START transcoder_create_job_with_set_number_images_spritesheet]
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// projectId = 'my-project-id';
// location = 'us-central1';
// inputUri = 'gs://my-bucket/my-video-file';
// outputUri = 'gs://my-bucket/my-output-folder/';

// Imports the Transcoder library
const {TranscoderServiceClient} = require('@google-cloud/video-transcoder');

// Instantiates a client
const transcoderServiceClient = new TranscoderServiceClient();

async function createJobWithSetNumberImagesSpritesheet() {
// Construct request
const request = {
parent: transcoderServiceClient.locationPath(projectId, location),
job: {
inputUri: inputUri,
outputUri: outputUri,
config: {
elementaryStreams: [
{
key: 'video-stream0',
videoStream: {
codec: 'h264',
heightPixels: 360,
widthPixels: 640,
bitrateBps: 550000,
frameRate: 60,
},
},
{
key: 'audio-stream0',
audioStream: {
codec: 'aac',
bitrateBps: 64000,
},
},
],
muxStreams: [
{
key: 'sd',
container: 'mp4',
elementaryStreams: ['video-stream0', 'audio-stream0'],
},
],
spriteSheets: [
{
filePrefix: 'small-sprite-sheet',
spriteHeightPixels: 32,
spriteWidthPixels: 64,
columnCount: 10,
rowCount: 10,
totalCount: 100,
},
{
filePrefix: 'large-sprite-sheet',
spriteHeightPixels: 72,
spriteWidthPixels: 128,
columnCount: 10,
rowCount: 10,
totalCount: 100,
},
],
},
},
};

// Run request
const [response] = await transcoderServiceClient.createJob(request);
console.log(`Job: ${response.name}`);
}

createJobWithSetNumberImagesSpritesheet();
// [END transcoder_create_job_with_set_number_images_spritesheet]
}

// node createJobWithSetNumberImagesSpritesheet.js <projectId> <location> <inputUri> <outputUri>
process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
146 changes: 132 additions & 14 deletions media/transcoder/test/transcoder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ const outputUriForTemplate = `gs://${bucketName}/test-output-template/`;
const outputUriForAdHoc = `gs://${bucketName}/test-output-adhoc/`;
const outputUriForStaticOverlay = `gs://${bucketName}/test-output-static-overlay/`;
const outputUriForAnimatedOverlay = `gs://${bucketName}/test-output-animated-overlay/`;
const outputDirForSetNumberImagesSpritesheet =
'test-output-set-number-spritesheet/';
const outputUriForSetNumberImagesSpritesheet = `gs://${bucketName}/${outputDirForSetNumberImagesSpritesheet}`;
const outputDirForPeriodicImagesSpritesheet =
'test-output-periodic-spritesheet/';
const outputUriForPeriodicImagesSpritesheet = `gs://${bucketName}/${outputDirForPeriodicImagesSpritesheet}`;
// Spritesheets are generated from the input video into the bucket directories above.
// Spritesheets use the following file naming conventions:
const smallSpriteSheetFileName = 'small-sprite-sheet0000000000.jpeg';
const largeSpriteSheetFileName = 'large-sprite-sheet0000000000.jpeg';

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

const checkFileExists = async function (bucketName, fileName) {
const [files] = await storage.bucket(bucketName).getFiles();
for (let i = 0; i < files.length; i++) {
if (files[i].name === fileName) {
return true;
}
}
return false;
};

before(async () => {
assert(
process.env.GOOGLE_CLOUD_PROJECT_NUMBER,
Expand Down Expand Up @@ -308,14 +328,6 @@ describe('Job with static overlay functions', () => {
assert.ok(output.includes(jobName));
});

it('should show a list of jobs', function () {
const output = execSync(`node listJobs.js ${projectId} ${location}`, {
cwd,
});
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.staticOverlayJobId}`;
assert.ok(output.includes(jobName));
});

it('should check that the job succeeded', async function () {
this.retries(5);
await wait(90000);
Expand Down Expand Up @@ -356,21 +368,127 @@ describe('Job with animated overlay functions', () => {
assert.ok(output.includes(jobName));
});

it('should show a list of jobs', function () {
const output = execSync(`node listJobs.js ${projectId} ${location}`, {
cwd,
});
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.animatedOverlayJobId}`;
it('should check that the job succeeded', async function () {
this.retries(5);
await wait(90000);
const output = execSync(
`node getJobState.js ${projectId} ${location} ${this.animatedOverlayJobId}`,
{cwd}
);
assert.ok(output.includes('Job state: SUCCEEDED'));
});
});

describe('Job with set number of images spritesheet', () => {
before(function () {
const output = execSync(
`node createJobWithSetNumberImagesSpritesheet.js ${projectId} ${location} ${inputUri} ${outputUriForSetNumberImagesSpritesheet}`,
{cwd}
);
assert.ok(
output.includes(`projects/${projectNumber}/locations/${location}/jobs/`)
);
this.setNumberSpritesheetJobId = output.toString().split('/').pop();
});

after(function () {
const output = execSync(
`node deleteJob.js ${projectId} ${location} ${this.setNumberSpritesheetJobId}`,
{cwd}
);
assert.ok(output.includes('Deleted job'));
});

it('should get a job', function () {
const output = execSync(
`node getJob.js ${projectId} ${location} ${this.setNumberSpritesheetJobId}`,
{cwd}
);
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.setNumberSpritesheetJobId}`;
assert.ok(output.includes(jobName));
});

it('should check that the job succeeded', async function () {
this.retries(5);
await wait(90000);
const output = execSync(
`node getJobState.js ${projectId} ${location} ${this.animatedOverlayJobId}`,
`node getJobState.js ${projectId} ${location} ${this.setNumberSpritesheetJobId}`,
{cwd}
);
assert.ok(output.includes('Job state: SUCCEEDED'));
});

it('should check that the spritesheet files exist in the bucket', async () => {
assert.equal(
await checkFileExists(
bucketName,
`${outputDirForSetNumberImagesSpritesheet}${smallSpriteSheetFileName}`
),
true
);
assert.equal(
await checkFileExists(
bucketName,
`${outputDirForSetNumberImagesSpritesheet}${largeSpriteSheetFileName}`
),
true
);
});
});

describe('Job with periodic images spritesheet', () => {
before(function () {
const output = execSync(
`node createJobWithPeriodicImagesSpritesheet.js ${projectId} ${location} ${inputUri} ${outputUriForPeriodicImagesSpritesheet}`,
{cwd}
);
assert.ok(
output.includes(`projects/${projectNumber}/locations/${location}/jobs/`)
);
this.periodicSpritesheetJobId = output.toString().split('/').pop();
});

after(function () {
const output = execSync(
`node deleteJob.js ${projectId} ${location} ${this.periodicSpritesheetJobId}`,
{cwd}
);
assert.ok(output.includes('Deleted job'));
});

it('should get a job', function () {
const output = execSync(
`node getJob.js ${projectId} ${location} ${this.periodicSpritesheetJobId}`,
{cwd}
);
const jobName = `projects/${projectNumber}/locations/${location}/jobs/${this.periodicSpritesheetJobId}`;
assert.ok(output.includes(jobName));
});

it('should check that the job succeeded', async function () {
this.retries(5);
await wait(90000);
const output = execSync(
`node getJobState.js ${projectId} ${location} ${this.periodicSpritesheetJobId}`,
{cwd}
);
assert.ok(output.includes('Job state: SUCCEEDED'));
});

it('should check that the spritesheet files exist in the bucket', async () => {
assert.equal(
await checkFileExists(
bucketName,
`${outputDirForPeriodicImagesSpritesheet}${smallSpriteSheetFileName}`
),
true
);
assert.equal(
await checkFileExists(
bucketName,
`${outputDirForPeriodicImagesSpritesheet}${largeSpriteSheetFileName}`
),
true
);
});
});

0 comments on commit bee30e0

Please sign in to comment.