Skip to content

Commit 634af34

Browse files
Ace NassriAhrar Monsur
Ace Nassri
authored and
Ahrar Monsur
committed
Video update (#476)
* Speed up video tests * Update video libraries WIP * Make tests serial to reduce flakiness * Remove old TODOs * Fixes endpoint for faces * Updates to new client library version * update endpoint. * Upgrades to new client library version
1 parent 679f632 commit 634af34

File tree

5 files changed

+172
-130
lines changed

5 files changed

+172
-130
lines changed

video-intelligence/analyze.js

+114-54
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,30 @@ function analyzeFaces (gcsUri) {
4141
.then((results) => {
4242
// Gets faces
4343
const faces = results[0].annotationResults[0].faceAnnotations;
44-
console.log('Faces:');
4544
faces.forEach((face, faceIdx) => {
46-
console.log('Thumbnail size:', face.thumbnail.length);
45+
console.log(`Face #${faceIdx}`);
46+
console.log(`\tThumbnail size: ${face.thumbnail.length}`);
4747
face.segments.forEach((segment, segmentIdx) => {
48-
console.log(`Face #${faceIdx}, appearance #${segmentIdx}:`);
49-
console.log(`\tStart: ${segment.startTimeOffset / 1e6}s`);
50-
console.log(`\tEnd: ${segment.endTimeOffset / 1e6}s`);
48+
segment = segment.segment;
49+
if (segment.startTimeOffset.seconds === undefined) {
50+
segment.startTimeOffset.seconds = 0;
51+
}
52+
if (segment.startTimeOffset.nanos === undefined) {
53+
segment.startTimeOffset.nanos = 0;
54+
}
55+
if (segment.endTimeOffset.seconds === undefined) {
56+
segment.endTimeOffset.seconds = 0;
57+
}
58+
if (segment.endTimeOffset.nanos === undefined) {
59+
segment.endTimeOffset.nanos = 0;
60+
}
61+
console.log(`\tAppearance #${segmentIdx}:`);
62+
console.log(`\t\tStart: ${segment.startTimeOffset.seconds}` +
63+
`.${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s`);
64+
console.log(`\t\tEnd: ${segment.endTimeOffset.seconds}.` +
65+
`${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s`);
5166
});
67+
console.log(`\tLocations:`);
5268
});
5369
})
5470
.catch((err) => {
@@ -63,7 +79,9 @@ function analyzeLabelsGCS (gcsUri) {
6379
const Video = require('@google-cloud/video-intelligence');
6480

6581
// Instantiates a client
66-
const video = Video();
82+
const video = Video({
83+
servicePath: `videointelligence.googleapis.com`
84+
});
6785

6886
// The GCS filepath of the video to analyze
6987
// const gcsUri = 'gs://my-bucket/my-video.mp4';
@@ -81,24 +99,32 @@ function analyzeLabelsGCS (gcsUri) {
8199
return operation.promise();
82100
})
83101
.then((results) => {
84-
// Gets labels
85-
const labels = results[0].annotationResults[0].labelAnnotations;
86-
console.log('Labels:');
102+
// Gets annotations for video
103+
const annotations = results[0].annotationResults[0];
104+
105+
const labels = annotations.segmentLabelAnnotations;
87106
labels.forEach((label) => {
88-
console.log(`Label ${label.description} occurs at:`);
89-
const isEntireVideo = label.locations.some((location) =>
90-
location.segment.startTimeOffset.toNumber() === -1 &&
91-
location.segment.endTimeOffset.toNumber() === -1
92-
);
93-
94-
if (isEntireVideo) {
95-
console.log(`\tEntire video`);
96-
} else {
97-
label.locations.forEach((location) => {
98-
console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`);
99-
console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`);
100-
});
101-
}
107+
console.log(`Label ${label.entity.description} occurs at:`);
108+
label.segments.forEach((segment) => {
109+
let time = segment.segment;
110+
if (time.startTimeOffset.seconds === undefined) {
111+
time.startTimeOffset.seconds = 0;
112+
}
113+
if (time.startTimeOffset.nanos === undefined) {
114+
time.startTimeOffset.nanos = 0;
115+
}
116+
if (time.endTimeOffset.seconds === undefined) {
117+
time.endTimeOffset.seconds = 0;
118+
}
119+
if (time.endTimeOffset.nanos === undefined) {
120+
time.endTimeOffset.nanos = 0;
121+
}
122+
console.log(`\tStart: ${time.startTimeOffset.seconds}` +
123+
`.${(time.startTimeOffset.nanos / 1e6).toFixed(0)}s`);
124+
console.log(`\tEnd: ${time.endTimeOffset.seconds}.` +
125+
`${(time.endTimeOffset.nanos / 1e6).toFixed(0)}s`);
126+
console.log(`\tConfidence: ${segment.confidence}`);
127+
});
102128
});
103129
})
104130
.catch((err) => {
@@ -137,24 +163,32 @@ function analyzeLabelsLocal (path) {
137163
return operation.promise();
138164
})
139165
.then((results) => {
140-
// Gets labels for first video
141-
const labels = results[0].annotationResults[0].labelAnnotations;
142-
console.log('Labels:');
166+
// Gets annotations for video
167+
const annotations = results[0].annotationResults[0];
168+
169+
const labels = annotations.segmentLabelAnnotations;
143170
labels.forEach((label) => {
144-
console.log(`Label ${label.description} occurs at:`);
145-
const isEntireVideo = label.locations.some((location) =>
146-
location.segment.startTimeOffset.toNumber() === -1 &&
147-
location.segment.endTimeOffset.toNumber() === -1
148-
);
149-
150-
if (isEntireVideo) {
151-
console.log(`\tEntire video`);
152-
} else {
153-
label.locations.forEach((location) => {
154-
console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`);
155-
console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`);
156-
});
157-
}
171+
console.log(`Label ${label.entity.description} occurs at:`);
172+
label.segments.forEach((segment) => {
173+
let time = segment.segment;
174+
if (time.startTimeOffset.seconds === undefined) {
175+
time.startTimeOffset.seconds = 0;
176+
}
177+
if (time.startTimeOffset.nanos === undefined) {
178+
time.startTimeOffset.nanos = 0;
179+
}
180+
if (time.endTimeOffset.seconds === undefined) {
181+
time.endTimeOffset.seconds = 0;
182+
}
183+
if (time.endTimeOffset.nanos === undefined) {
184+
time.endTimeOffset.nanos = 0;
185+
}
186+
console.log(`\tStart: ${time.startTimeOffset.seconds}` +
187+
`.${(time.startTimeOffset.nanos / 1e6).toFixed(0)}s`);
188+
console.log(`\tEnd: ${time.endTimeOffset.seconds}.` +
189+
`${(time.endTimeOffset.nanos / 1e6).toFixed(0)}s`);
190+
console.log(`\tConfidence: ${segment.confidence}`);
191+
});
158192
});
159193
})
160194
.catch((err) => {
@@ -195,9 +229,29 @@ function analyzeShots (gcsUri) {
195229
console.log(`The entire video is one shot.`);
196230
} else {
197231
shotChanges.forEach((shot, shotIdx) => {
198-
console.log(`Shot ${shotIdx} occurs from:`);
199-
console.log(`\tStart: ${shot.startTimeOffset / 1e6}s`);
200-
console.log(`\tEnd: ${shot.endTimeOffset / 1e6}s`);
232+
console.log(`Scene ${shotIdx} occurs from:`);
233+
if (shot.startTimeOffset === undefined) {
234+
shot.startTimeOffset = {};
235+
}
236+
if (shot.endTimeOffset === undefined) {
237+
shot.endTimeOffset = {};
238+
}
239+
if (shot.startTimeOffset.seconds === undefined) {
240+
shot.startTimeOffset.seconds = 0;
241+
}
242+
if (shot.startTimeOffset.nanos === undefined) {
243+
shot.startTimeOffset.nanos = 0;
244+
}
245+
if (shot.endTimeOffset.seconds === undefined) {
246+
shot.endTimeOffset.seconds = 0;
247+
}
248+
if (shot.endTimeOffset.nanos === undefined) {
249+
shot.endTimeOffset.nanos = 0;
250+
}
251+
console.log(`\tStart: ${shot.startTimeOffset.seconds}` +
252+
`.${(shot.startTimeOffset.nanos / 1e6).toFixed(0)}s`);
253+
console.log(`\tEnd: ${shot.endTimeOffset.seconds}.` +
254+
`${(shot.endTimeOffset.nanos / 1e6).toFixed(0)}s`);
201255
});
202256
}
203257
})
@@ -220,7 +274,7 @@ function analyzeSafeSearch (gcsUri) {
220274

221275
const request = {
222276
inputUri: gcsUri,
223-
features: ['SAFE_SEARCH_DETECTION']
277+
features: ['EXPLICIT_CONTENT_DETECTION']
224278
};
225279

226280
// Human-readable likelihoods
@@ -235,15 +289,21 @@ function analyzeSafeSearch (gcsUri) {
235289
})
236290
.then((results) => {
237291
// Gets unsafe content
238-
const safeSearchResults = results[0].annotationResults[0].safeSearchAnnotations;
239-
console.log('Safe search results:');
240-
safeSearchResults.forEach((result) => {
241-
console.log(`Time: ${result.timeOffset / 1e6}s`);
242-
console.log(`\tAdult: ${likelihoods[result.adult]}`);
243-
console.log(`\tSpoof: ${likelihoods[result.spoof]}`);
244-
console.log(`\tMedical: ${likelihoods[result.medical]}`);
245-
console.log(`\tViolent: ${likelihoods[result.violent]}`);
246-
console.log(`\tRacy: ${likelihoods[result.racy]}`);
292+
const explicitContentResults = results[0].annotationResults[0].explicitAnnotation;
293+
console.log('Explicit annotation results:');
294+
explicitContentResults.frames.forEach((result) => {
295+
if (result.timeOffset === undefined) {
296+
result.timeOffset = {};
297+
}
298+
if (result.timeOffset.seconds === undefined) {
299+
result.timeOffset.seconds = 0;
300+
}
301+
if (result.timeOffset.nanos === undefined) {
302+
result.timeOffset.nanos = 0;
303+
}
304+
console.log(`\tTime: ${result.timeOffset.seconds}` +
305+
`.${(result.timeOffset.nanos / 1e6).toFixed(0)}s`);
306+
console.log(`\t\tPornography liklihood: ${likelihoods[result.pornographyLikelihood]}`);
247307
});
248308
})
249309
.catch((err) => {
@@ -280,7 +340,7 @@ require(`yargs`) // eslint-disable-line
280340
)
281341
.command(
282342
`safe-search <gcsUri>`,
283-
`Detects adult content in a video stored in Google Cloud Storage.`,
343+
`Detects explicit content in a video stored in Google Cloud Storage.`,
284344
{},
285345
(opts) => analyzeSafeSearch(opts.gcsUri)
286346
)

video-intelligence/package.json

+4-5
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717
"test": "samples test run --cmd ava -- -T 5m --verbose system-test/*.test.js"
1818
},
1919
"dependencies": {
20-
"@google-cloud/video-intelligence": "0.1.0",
21-
"googleapis": "19.0.0",
20+
"@google-cloud/video-intelligence": "^0.3.2",
2221
"long": "^3.2.0",
23-
"safe-buffer": "5.1.0",
22+
"safe-buffer": "5.1.1",
2423
"yargs": "8.0.2"
2524
},
2625
"devDependencies": {
27-
"@google-cloud/nodejs-repo-tools": "1.4.15",
28-
"ava": "0.19.1",
26+
"@google-cloud/nodejs-repo-tools": "1.4.17",
27+
"ava": "0.22.0",
2928
"proxyquire": "1.8.0"
3029
},
3130
"cloud-repo-tools": {

video-intelligence/quickstart.js

+24-43
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,15 @@
2020
const Video = require('@google-cloud/video-intelligence');
2121

2222
// Instantiates a client
23-
const video = Video({
24-
projectId: process.env.GCLOUD_PROJECT // Replace with your Google Cloud project ID
25-
});
23+
const video = Video();
2624

2725
// The GCS filepath of the video to analyze
28-
const gcsUri = 'gs://demomaker/tomatoes.mp4';
26+
const gcsUri = 'gs://nodejs-docs-samples-video/quickstart_short.mp4';
2927

3028
// Construct request
3129
const request = {
3230
inputUri: gcsUri,
33-
features: ['FACE_DETECTION', 'LABEL_DETECTION', 'SHOT_CHANGE_DETECTION']
31+
features: ['LABEL_DETECTION']
3432
};
3533

3634
// Execute request
@@ -44,47 +42,30 @@ video.annotateVideo(request)
4442
// Gets annotations for video
4543
const annotations = results[0].annotationResults[0];
4644

47-
// Gets faces for video from its annotations
48-
const faces = annotations.faceAnnotations;
49-
faces.forEach((face, faceIdx) => {
50-
console.log('Thumbnail size:', face.thumbnail.length);
51-
face.segments.forEach((segment, segmentIdx) => {
52-
console.log(`Face #${faceIdx}, appearance #${segmentIdx}:`);
53-
console.log(`\tStart: ${segment.startTimeOffset / 1e6}s`);
54-
console.log(`\tEnd: ${segment.endTimeOffset / 1e6}s`);
55-
});
56-
});
57-
5845
// Gets labels for video from its annotations
59-
const labels = annotations.labelAnnotations;
46+
const labels = annotations.segmentLabelAnnotations;
6047
labels.forEach((label) => {
61-
console.log(`Label ${label.description} occurs at:`);
62-
const isEntireVideo = label.locations.some((location) =>
63-
location.segment.startTimeOffset.toNumber() === -1 &&
64-
location.segment.endTimeOffset.toNumber() === -1
65-
);
66-
67-
if (isEntireVideo) {
68-
console.log(`\tEntire video`);
69-
} else {
70-
label.locations.forEach((location) => {
71-
console.log(`\tStart: ${location.segment.startTimeOffset / 1e6}s`);
72-
console.log(`\tEnd: ${location.segment.endTimeOffset / 1e6}s`);
73-
});
74-
}
75-
});
76-
77-
// Gets shot changes for video from its annotations
78-
const shotChanges = annotations.shotAnnotations;
79-
if (shotChanges.length === 1) {
80-
console.log(`The entire video is one scene.`);
81-
} else {
82-
shotChanges.forEach((shot, shotIdx) => {
83-
console.log(`Scene ${shotIdx} occurs from:`);
84-
console.log(`\tStart: ${shot.startTimeOffset / 1e6}s`);
85-
console.log(`\tEnd: ${shot.endTimeOffset / 1e6}s`);
48+
console.log(`Label ${label.entity.description} occurs at:`);
49+
label.segments.forEach((segment) => {
50+
segment = segment.segment;
51+
if (segment.startTimeOffset.seconds === undefined) {
52+
segment.startTimeOffset.seconds = 0;
53+
}
54+
if (segment.startTimeOffset.nanos === undefined) {
55+
segment.startTimeOffset.nanos = 0;
56+
}
57+
if (segment.endTimeOffset.seconds === undefined) {
58+
segment.endTimeOffset.seconds = 0;
59+
}
60+
if (segment.endTimeOffset.nanos === undefined) {
61+
segment.endTimeOffset.nanos = 0;
62+
}
63+
console.log(`\tStart: ${segment.startTimeOffset.seconds}` +
64+
`.${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s`);
65+
console.log(`\tEnd: ${segment.endTimeOffset.seconds}.` +
66+
`${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s`);
8667
});
87-
}
68+
});
8869
})
8970
.catch((err) => {
9071
console.error('ERROR:', err);

0 commit comments

Comments
 (0)