From e3efddcdaee263506b0c03e95f814f3e268d5746 Mon Sep 17 00:00:00 2001 From: Ace Nassri Date: Wed, 17 May 2017 17:26:02 -0700 Subject: [PATCH] Address comments (#388) * Address sgreenberg's comments * Massage package.json + generate README --- video-intelligence/analyze.js | 54 +++++++++++++------ video-intelligence/package.json | 19 +++++-- video-intelligence/quickstart.js | 30 ++++++++--- .../system-test/analyze.test.js | 6 +-- .../system-test/quickstart.test.js | 6 +-- 5 files changed, 81 insertions(+), 34 deletions(-) diff --git a/video-intelligence/analyze.js b/video-intelligence/analyze.js index 25330c590b..6296c9377d 100644 --- a/video-intelligence/analyze.js +++ b/video-intelligence/analyze.js @@ -45,7 +45,12 @@ function analyzeFaces (gcsUri) { faces.forEach((face, faceIdx) => { console.log('\tThumbnail size:', face.thumbnail.length); face.segments.forEach((segment, segmentIdx) => { - console.log(`\tTrack ${segmentIdx} of face ${faceIdx}: frames ${segment.startTimeOffset} to ${segment.endTimeOffset}`); + if (segment.startTimeOffset === -1 && segment.endTimeOffset === -1) { + console.log(`\tEntire video`); + } else { + console.log(`\tStart: ${segment.startTimeOffset / 1e6}s`); + console.log(`\tEnd: ${segment.endTimeOffset / 1e6}s`); + } }); }); }) @@ -86,7 +91,12 @@ function analyzeLabelsGCS (gcsUri) { console.log('Label description:', label.description); console.log('Locations:'); label.locations.forEach((location) => { - console.log(`\tFrames ${location.segment.startTimeOffset} to ${location.segment.endTimeOffset}`); + if (location.segment.startTimeOffset === -1 && location.segment.endTimeOffset === -1) { + console.log(`\tEntire video`); + } else { + console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`); + console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`); + } }); }); }) @@ -133,7 +143,12 @@ function analyzeLabelsLocal (path) { console.log('Label description:', label.description); console.log('Locations:'); label.locations.forEach((location) => { - console.log(`\tFrames ${location.segment.startTimeOffset} to ${location.segment.endTimeOffset}`); + if (location.segment.startTimeOffset === -1 && location.segment.endTimeOffset === -1) { + console.log(`\tEntire video`); + } else { + console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`); + console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`); + } }); }); }) @@ -172,8 +187,12 @@ function analyzeShots (gcsUri) { console.log('Shot changes:'); shotChanges.forEach((shot, shotIdx) => { console.log(`Scene ${shotIdx}:`); - console.log(`\tStart: ${shot.startTimeOffset}`); - console.log(`\tEnd: ${shot.endTimeOffset}`); + if (shot.startTimeOffset === -1 && shot.endTimeOffset === -1) { + console.log(`\tEntire video`); + } else { + console.log(`\tStart: ${shot.startTimeOffset}`); + console.log(`\tEnd: ${shot.endTimeOffset}`); + } }); }) .catch((err) => { @@ -198,6 +217,9 @@ function analyzeSafeSearch (gcsUri) { features: ['SAFE_SEARCH_DETECTION'] }; + // Human-readable likelihoods + const likelihoods = ['UNKNOWN', 'VERY_UNLIKELY', 'UNLIKELY', 'POSSIBLE', 'LIKELY', 'VERY_LIKELY']; + // Detects unsafe content video.annotateVideo(request) .then((results) => { @@ -210,12 +232,12 @@ function analyzeSafeSearch (gcsUri) { const safeSearchResults = results[0].annotationResults[0].safeSearchAnnotations; console.log('Safe search results:'); safeSearchResults.forEach((result) => { - console.log(`Frame ${result.timeOffset}:`); - console.log(`\tAdult: ${result.adult}`); - console.log(`\tSpoof: ${result.spoof}`); - console.log(`\tMedical: ${result.medical}`); - console.log(`\tViolent: ${result.violent}`); - console.log(`\tRacy: ${result.racy}`); + console.log(`Time: ${result.timeOffset / 1e6}s`); + console.log(`\tAdult: ${likelihoods[result.adult]}`); + console.log(`\tSpoof: ${likelihoods[result.spoof]}`); + console.log(`\tMedical: ${likelihoods[result.medical]}`); + console.log(`\tViolent: ${likelihoods[result.violent]}`); + console.log(`\tRacy: ${likelihoods[result.racy]}`); }); }) .catch((err) => { @@ -256,11 +278,11 @@ require(`yargs`) // eslint-disable-line {}, (opts) => analyzeSafeSearch(opts.gcsUri) ) - .example(`node $0 faces gs://my-bucket/my-video.mp4`) - .example(`node $0 shots gs://my-bucket/my-video.mp4`) - .example(`node $0 labels-gcs gs://my-bucket/my-video.mp4`) - .example(`node $0 labels-file my-video.mp4`) - .example(`node $0 safe-search gs://my-bucket/my-video.mp4`) + .example(`node $0 faces gs://demomaker/volleyball_court.mp4`) + .example(`node $0 shots gs://demomaker/volleyball_court.mp4`) + .example(`node $0 labels-gcs gs://demomaker/volleyball_court.mp4`) + .example(`node $0 labels-file cat.mp4`) + .example(`node $0 safe-search gs://demomaker/volleyball_court.mp4`) .wrap(120) .recommendCommands() .epilogue(`For more information, see https://cloud.google.com/video-intelligence/docs`) diff --git a/video-intelligence/package.json b/video-intelligence/package.json index ff8d547aec..daf9b022aa 100644 --- a/video-intelligence/package.json +++ b/video-intelligence/package.json @@ -19,14 +19,27 @@ }, "dependencies": { "@google-cloud/videointelligence": "https://storage.googleapis.com/videointelligence-alpha/videointelligence-nodejs.tar.gz", + "googleapis": "19.0.0", + "safe-buffer": "5.0.1", "yargs": "7.1.0" }, "devDependencies": { - "@google-cloud/nodejs-repo-tools": "1.4.7", - "ava": "0.19.1" + "@google-cloud/nodejs-repo-tools": "1.4.13", + "ava": "0.19.1", + "proxyquire": "1.7.11" }, "cloud-repo-tools": { "requiresKeyFile": true, - "requiresProjectId": true + "requiresProjectId": true, + "product": "video", + "samples": [ + { + "id": "video", + "name": "Video Intelligence", + "file": "analyze.js", + "docs_link": "https://cloud.google.com/video-intelligence/docs", + "usage": "node analyze.js --help" + } + ] } } diff --git a/video-intelligence/quickstart.js b/video-intelligence/quickstart.js index df537216ad..f187f35da9 100644 --- a/video-intelligence/quickstart.js +++ b/video-intelligence/quickstart.js @@ -25,7 +25,7 @@ const video = Video.videoIntelligenceServiceClient({ }); // The GCS filepath of the video to analyze -const gcsUri = 'gs://nodejs-docs-samples/videointelligence_quickstart.mp4'; +const gcsUri = 'gs://demomaker/volleyball_court.mp4'; // Construct request const request = { @@ -49,26 +49,40 @@ video.annotateVideo(request) faces.forEach((face, faceIdx) => { console.log('Thumbnail size:', face.thumbnail.length); face.segments.forEach((segment, segmentIdx) => { - console.log(`Track ${segmentIdx} of face ${faceIdx}: frames ${segment.startTimeOffset} to ${segment.endTimeOffset}`); + console.log(`Face #${faceIdx}, appearance #${segmentIdx}:`); + if (segment.startTimeOffset === -1 && segment.endTimeOffset === -1) { + console.log(`\tEntire video`); + } else { + console.log(`\tStart: ${segment.startTimeOffset / 1e6}s`); + console.log(`\tEnd: ${segment.endTimeOffset / 1e6}s`); + } }); }); // Gets labels for video from its annotations const labels = annotations.labelAnnotations; labels.forEach((label) => { - console.log('Label description:', label.description); - console.log('Locations:'); + console.log(`Label ${label.description} occurs at:`); label.locations.forEach((location) => { - console.log(`\tFrames ${location.segment.startTimeOffset} to ${location.segment.endTimeOffset}`); + if (location.segment.startTimeOffset === -1 && location.segment.endTimeOffset === -1) { + console.log(`\tEntire video`); + } else { + console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`); + console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`); + } }); }); // Gets shot changes for video from its annotations const shotChanges = annotations.shotAnnotations; shotChanges.forEach((shot, shotIdx) => { - console.log(`Scene ${shotIdx}:`); - console.log(`\tStart: ${shot.startTimeOffset}`); - console.log(`\tEnd: ${shot.endTimeOffset}`); + console.log(`Scene ${shotIdx} occurs from:`); + if (shot.startTimeOffset === -1 && shot.endTimeOffset === -1) { + console.log(`\tEntire video`); + } else { + console.log(`\tStart: ${shot.startTimeOffset / 1e6}s`); + console.log(`\tEnd: ${shot.endTimeOffset / 1e6}s`); + } }); }) .catch((err) => { diff --git a/video-intelligence/system-test/analyze.test.js b/video-intelligence/system-test/analyze.test.js index d4cf6e0660..20a8ce8e3d 100644 --- a/video-intelligence/system-test/analyze.test.js +++ b/video-intelligence/system-test/analyze.test.js @@ -44,13 +44,13 @@ test(`should analyze labels in a local file`, async (t) => { // analyze_shots test(`should analyze shots in a GCS file`, async (t) => { - const output = await tools.runAsync(`${cmd} shots gs://nodejs-docs-samples/video/gbike_dinosaur.mp4`, cwd); + const output = await tools.runAsync(`${cmd} shots gs://nodejs-docs-samples/video/google_gmail.mp4`, cwd); t.regex(output, /Scene 0:/); }); // analyze_safe_search test(`should analyze safe search results in a GCS file`, async (t) => { const output = await tools.runAsync(`${cmd} safe-search gs://nodejs-docs-samples/video/google_gmail.mp4`, cwd); - t.regex(output, /Frame \d+/); - t.regex(output, /Spoof: \d+/); + t.regex(output, /Time: \d\.\d+s/); + t.regex(output, /Spoof:/); }); diff --git a/video-intelligence/system-test/quickstart.test.js b/video-intelligence/system-test/quickstart.test.js index 46e1dd7b2e..d7af8b1146 100644 --- a/video-intelligence/system-test/quickstart.test.js +++ b/video-intelligence/system-test/quickstart.test.js @@ -24,8 +24,6 @@ const cwd = path.join(__dirname, `..`); test(`should analyze a hardcoded video`, async (t) => { const output = await tools.runAsync(cmd, cwd); - t.regex(output, /Label description:/); - t.regex(output, /Frames \d+ to \d+/); - t.regex(output, /Track \d+ of face \d+: frames \d+ to \d+/); - t.regex(output, /Scene \d+/); + t.regex(output, /Label Property occurs at:/); + t.regex(output, /Scene \d+ occurs from:/); });