From 89a7a80a0d8836624dcd4272d5c1d890b969887c Mon Sep 17 00:00:00 2001 From: Ace Nassri Date: Wed, 17 May 2017 21:59:24 -0700 Subject: [PATCH] Switch to faster videos + update print statements (#395) --- video-intelligence/analyze.js | 109 ++++++++++-------- video-intelligence/package.json | 5 +- video-intelligence/quickstart.js | 58 ++++++---- .../system-test/analyze.test.js | 41 +++++-- .../system-test/quickstart.test.js | 5 +- 5 files changed, 133 insertions(+), 85 deletions(-) diff --git a/video-intelligence/analyze.js b/video-intelligence/analyze.js index 6296c9377d..a6f1d7b77c 100644 --- a/video-intelligence/analyze.js +++ b/video-intelligence/analyze.js @@ -18,10 +18,10 @@ function analyzeFaces (gcsUri) { // [START analyze_faces] // Imports the Google Cloud Video Intelligence library - const Video = require('@google-cloud/videointelligence'); + const Video = require('@google-cloud/video-intelligence'); // Instantiates a client - const video = Video().videoIntelligenceServiceClient(); + const video = Video(); // The GCS filepath of the video to analyze // const gcsUri = 'gs://my-bucket/my-video.mp4'; @@ -43,15 +43,23 @@ function analyzeFaces (gcsUri) { const faces = results[0].annotationResults[0].faceAnnotations; console.log('Faces:'); faces.forEach((face, faceIdx) => { - console.log('\tThumbnail size:', face.thumbnail.length); - face.segments.forEach((segment, segmentIdx) => { - if (segment.startTimeOffset === -1 && segment.endTimeOffset === -1) { - console.log(`\tEntire video`); - } else { + console.log('Thumbnail size:', face.thumbnail.length); + + const isEntireVideo = face.segments.some((segment) => + segment.startTimeOffset.toNumber() === -1 && + segment.endTimeOffset.toNumber() === -1 + ); + + if (isEntireVideo) { + console.log(`Face #${faceIdx}`); + console.log(`\tEntire video`); + } else { + face.segments.forEach((segment, segmentIdx) => { + console.log(`Face #${faceIdx}, appearance #${segmentIdx}:`); console.log(`\tStart: ${segment.startTimeOffset / 1e6}s`); console.log(`\tEnd: ${segment.endTimeOffset / 1e6}s`); - } - }); + }); + } }); }) .catch((err) => { @@ -63,10 +71,10 @@ function analyzeFaces (gcsUri) { function analyzeLabelsGCS (gcsUri) { // [START analyze_labels_gcs] // Imports the Google Cloud Video Intelligence library - const Video = require('@google-cloud/videointelligence'); + const Video = require('@google-cloud/video-intelligence'); // Instantiates a client - const video = Video().videoIntelligenceServiceClient(); + const video = Video(); // The GCS filepath of the video to analyze // const gcsUri = 'gs://my-bucket/my-video.mp4'; @@ -88,16 +96,20 @@ function analyzeLabelsGCS (gcsUri) { const labels = results[0].annotationResults[0].labelAnnotations; console.log('Labels:'); labels.forEach((label) => { - console.log('Label description:', label.description); - console.log('Locations:'); - label.locations.forEach((location) => { - if (location.segment.startTimeOffset === -1 && location.segment.endTimeOffset === -1) { - console.log(`\tEntire video`); - } else { + console.log(`Label ${label.description} occurs at:`); + const isEntireVideo = label.locations.some((location) => + location.segment.startTimeOffset.toNumber() === -1 && + location.segment.endTimeOffset.toNumber() === -1 + ); + + if (isEntireVideo) { + console.log(`\tEntire video`); + } else { + label.locations.forEach((location) => { console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`); console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`); - } - }); + }); + } }); }) .catch((err) => { @@ -109,11 +121,11 @@ function analyzeLabelsGCS (gcsUri) { function analyzeLabelsLocal (path) { // [START analyze_labels_local] // Imports the Google Cloud Video Intelligence library + Node's fs library - const Video = require('@google-cloud/videointelligence'); + const Video = require('@google-cloud/video-intelligence'); const fs = require('fs'); // Instantiates a client - const video = Video().videoIntelligenceServiceClient(); + const video = Video(); // The local filepath of the video to analyze // const path = 'my-file.mp4'; @@ -140,16 +152,20 @@ function analyzeLabelsLocal (path) { const labels = results[0].annotationResults[0].labelAnnotations; console.log('Labels:'); labels.forEach((label) => { - console.log('Label description:', label.description); - console.log('Locations:'); - label.locations.forEach((location) => { - if (location.segment.startTimeOffset === -1 && location.segment.endTimeOffset === -1) { - console.log(`\tEntire video`); - } else { + console.log(`Label ${label.description} occurs at:`); + const isEntireVideo = label.locations.some((location) => + location.segment.startTimeOffset.toNumber() === -1 && + location.segment.endTimeOffset.toNumber() === -1 + ); + + if (isEntireVideo) { + console.log(`\tEntire video`); + } else { + label.locations.forEach((location) => { console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`); console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`); - } - }); + }); + } }); }) .catch((err) => { @@ -161,10 +177,10 @@ function analyzeLabelsLocal (path) { function analyzeShots (gcsUri) { // [START analyze_shots] // Imports the Google Cloud Video Intelligence library - const Video = require('@google-cloud/videointelligence'); + const Video = require('@google-cloud/video-intelligence'); // Instantiates a client - const video = Video().videoIntelligenceServiceClient(); + const video = Video(); // The GCS filepath of the video to analyze // const gcsUri = 'gs://my-bucket/my-video.mp4'; @@ -185,15 +201,16 @@ function analyzeShots (gcsUri) { // Gets shot changes const shotChanges = results[0].annotationResults[0].shotAnnotations; console.log('Shot changes:'); - shotChanges.forEach((shot, shotIdx) => { - console.log(`Scene ${shotIdx}:`); - if (shot.startTimeOffset === -1 && shot.endTimeOffset === -1) { - console.log(`\tEntire video`); - } else { - console.log(`\tStart: ${shot.startTimeOffset}`); - console.log(`\tEnd: ${shot.endTimeOffset}`); - } - }); + + if (shotChanges.length === 1) { + console.log(`The entire video is one shot.`); + } else { + shotChanges.forEach((shot, shotIdx) => { + console.log(`Shot ${shotIdx} occurs from:`); + console.log(`\tStart: ${shot.startTimeOffset / 1e6}s`); + console.log(`\tEnd: ${shot.endTimeOffset / 1e6}s`); + }); + } }) .catch((err) => { console.error('ERROR:', err); @@ -204,10 +221,10 @@ function analyzeShots (gcsUri) { function analyzeSafeSearch (gcsUri) { // [START analyze_safe_search] // Imports the Google Cloud Video Intelligence library - const Video = require('@google-cloud/videointelligence'); + const Video = require('@google-cloud/video-intelligence'); // Instantiates a client - const video = Video().videoIntelligenceServiceClient(); + const video = Video(); // The GCS filepath of the video to analyze // const gcsUri = 'gs://my-bucket/my-video.mp4'; @@ -278,11 +295,11 @@ require(`yargs`) // eslint-disable-line {}, (opts) => analyzeSafeSearch(opts.gcsUri) ) - .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 faces gs://demomaker/larry_sergey_ice_bucket_short.mp4`) + .example(`node $0 shots gs://demomaker/sushi.mp4`) + .example(`node $0 labels-gcs gs://demomaker/tomatoes.mp4`) .example(`node $0 labels-file cat.mp4`) - .example(`node $0 safe-search gs://demomaker/volleyball_court.mp4`) + .example(`node $0 safe-search gs://demomaker/tomatoes.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 daf9b022aa..a15ca1168a 100644 --- a/video-intelligence/package.json +++ b/video-intelligence/package.json @@ -14,12 +14,13 @@ "scripts": { "lint": "samples lint", "pretest": "npm run lint", - "system-test": "ava -T 10m --verbose system-test/*.test.js", + "system-test": "ava -T 5m --verbose system-test/*.test.js", "test": "npm run system-test" }, "dependencies": { - "@google-cloud/videointelligence": "https://storage.googleapis.com/videointelligence-alpha/videointelligence-nodejs.tar.gz", + "@google-cloud/video-intelligence": "0.1.0", "googleapis": "19.0.0", + "long": "^3.2.0", "safe-buffer": "5.0.1", "yargs": "7.1.0" }, diff --git a/video-intelligence/quickstart.js b/video-intelligence/quickstart.js index f187f35da9..8a1bf3290a 100644 --- a/video-intelligence/quickstart.js +++ b/video-intelligence/quickstart.js @@ -17,15 +17,15 @@ // [START videointelligence_quickstart] // Imports the Google Cloud Video Intelligence library -const Video = require('@google-cloud/videointelligence').v1beta1(); +const Video = require('@google-cloud/video-intelligence'); // Instantiates a client -const video = Video.videoIntelligenceServiceClient({ +const video = Video({ projectId: process.env.GCLOUD_PROJECT // Replace with your Google Cloud project ID }); // The GCS filepath of the video to analyze -const gcsUri = 'gs://demomaker/volleyball_court.mp4'; +const gcsUri = 'gs://demomaker/tomatoes.mp4'; // Construct request const request = { @@ -48,42 +48,54 @@ video.annotateVideo(request) const faces = annotations.faceAnnotations; faces.forEach((face, faceIdx) => { console.log('Thumbnail size:', face.thumbnail.length); - face.segments.forEach((segment, segmentIdx) => { - console.log(`Face #${faceIdx}, appearance #${segmentIdx}:`); - if (segment.startTimeOffset === -1 && segment.endTimeOffset === -1) { - console.log(`\tEntire video`); - } else { + + const isEntireVideo = face.segments.some((segment) => + segment.startTimeOffset.toNumber() === -1 && + segment.endTimeOffset.toNumber() === -1 + ); + + if (isEntireVideo) { + console.log(`Face #${faceIdx}`); + console.log(`\tEntire video`); + } else { + face.segments.forEach((segment, segmentIdx) => { + console.log(`Face #${faceIdx}, appearance #${segmentIdx}:`); 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 ${label.description} occurs at:`); - label.locations.forEach((location) => { - if (location.segment.startTimeOffset === -1 && location.segment.endTimeOffset === -1) { - console.log(`\tEntire video`); - } else { + const isEntireVideo = label.locations.some((location) => + location.segment.startTimeOffset.toNumber() === -1 && + location.segment.endTimeOffset.toNumber() === -1 + ); + + if (isEntireVideo) { + console.log(`\tEntire video`); + } else { + label.locations.forEach((location) => { 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} occurs from:`); - if (shot.startTimeOffset === -1 && shot.endTimeOffset === -1) { - console.log(`\tEntire video`); - } else { + if (shotChanges.length === 1) { + console.log(`The entire video is one scene.`); + } else { + shotChanges.forEach((shot, shotIdx) => { + console.log(`Scene ${shotIdx} occurs from:`); console.log(`\tStart: ${shot.startTimeOffset / 1e6}s`); console.log(`\tEnd: ${shot.endTimeOffset / 1e6}s`); - } - }); + }); + } }) .catch((err) => { console.error('ERROR:', err); diff --git a/video-intelligence/system-test/analyze.test.js b/video-intelligence/system-test/analyze.test.js index 20a8ce8e3d..7ac7d1d7af 100644 --- a/video-intelligence/system-test/analyze.test.js +++ b/video-intelligence/system-test/analyze.test.js @@ -26,31 +26,48 @@ const cwd = path.join(__dirname, `..`); // analyze_faces test(`should analyze faces in a GCS file`, async (t) => { - const output = await tools.runAsync(`${cmd} faces gs://nodejs-docs-samples/video/google_gmail.mp4`, cwd); + const output = await tools.runAsync(`${cmd} faces gs://demomaker/larry_sergey_ice_bucket_short.mp4`, cwd); t.regex(output, /Thumbnail size: \d+/); + t.regex(output, /Start: \d+\.\d+s/); + t.regex(output, /End: \d+\.\d+s/); }); -// analyze_labels_gcs -test(`should analyze labels in a GCS file`, async (t) => { - const output = await tools.runAsync(`${cmd} labels-gcs gs://nodejs-docs-samples/video/cat.mp4`, cwd); - t.regex(output, /Label description: Whiskers/); +// analyze_labels_gcs (one scene) +test(`should analyze labels in a GCS file with one scene`, async (t) => { + const output = await tools.runAsync(`${cmd} labels-gcs gs://demomaker/tomatoes.mp4`, cwd); + t.regex(output, /Label Tomato occurs at:/); + t.regex(output, /Entire video/); +}); + +// analyze_labels_gcs (multiple scenes) +test(`should analyze labels in a GCS file with multiple scenes`, async (t) => { + const output = await tools.runAsync(`${cmd} labels-gcs gs://demomaker/sushi.mp4`, cwd); + t.regex(output, /Label Food occurs at:/); + t.regex(output, /Start: \d+\.\d+s/); + t.regex(output, /End: \d+\.\d+s/); }); // analyze_labels_local test(`should analyze labels in a local file`, async (t) => { const output = await tools.runAsync(`${cmd} labels-file resources/cat.mp4`, cwd); - t.regex(output, /Label description: Whiskers/); + t.regex(output, /Label Whiskers occurs at:/); + t.regex(output, /Entire video/); +}); + +// analyze_shots (multiple shots) +test(`should analyze shots in a GCS file with multiple shots`, async (t) => { + const output = await tools.runAsync(`${cmd} shots gs://demomaker/sushi.mp4`, cwd); + t.regex(output, /Shot 0 occurs from:/); }); -// analyze_shots -test(`should analyze shots in a GCS file`, async (t) => { - const output = await tools.runAsync(`${cmd} shots gs://nodejs-docs-samples/video/google_gmail.mp4`, cwd); - t.regex(output, /Scene 0:/); +// analyze_shots (one shot) +test(`should analyze shots in a GCS file with one shot`, async (t) => { + const output = await tools.runAsync(`${cmd} shots gs://demomaker/tomatoes.mp4`, cwd); + t.regex(output, /The entire video is one shot./); }); // 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, /Time: \d\.\d+s/); + const output = await tools.runAsync(`${cmd} safe-search gs://demomaker/tomatoes.mp4`, cwd); t.regex(output, /Spoof:/); }); diff --git a/video-intelligence/system-test/quickstart.test.js b/video-intelligence/system-test/quickstart.test.js index d7af8b1146..bff0f3c49a 100644 --- a/video-intelligence/system-test/quickstart.test.js +++ b/video-intelligence/system-test/quickstart.test.js @@ -24,6 +24,7 @@ const cwd = path.join(__dirname, `..`); test(`should analyze a hardcoded video`, async (t) => { const output = await tools.runAsync(cmd, cwd); - t.regex(output, /Label Property occurs at:/); - t.regex(output, /Scene \d+ occurs from:/); + t.regex(output, /Label Tomato occurs at:/); + t.regex(output, /Entire video/); + t.regex(output, /The entire video is one scene./); });