@@ -301,6 +301,241 @@ async function analyzeVideoTranscription(gcsUri) {
301
301
// [END video_speech_transcription_gcs]
302
302
}
303
303
304
+ async function analyzeTextGCS ( gcsUri ) {
305
+ //gcsUri - GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4
306
+ //[START video_detect_text_gcs]
307
+ // Imports the Google Cloud Video Intelligence library
308
+ const Video = require ( '@google-cloud/video-intelligence' ) ;
309
+ // Creates a client
310
+ const video = new Video . VideoIntelligenceServiceClient ( ) ;
311
+
312
+ /**
313
+ * TODO(developer): Uncomment the following line before running the sample.
314
+ */
315
+ // const gcsUri = 'GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4';
316
+
317
+ const request = {
318
+ inputUri : gcsUri ,
319
+ features : [ 'TEXT_DETECTION' ] ,
320
+ } ;
321
+ // Detects text in a video
322
+ const [ operation ] = await video . annotateVideo ( request ) ;
323
+ const results = await operation . promise ( ) ;
324
+ console . log ( 'Waiting for operation to complete...' ) ;
325
+ // Gets annotations for video
326
+ const textAnnotations = results [ 0 ] . annotationResults [ 0 ] . textAnnotations ;
327
+ textAnnotations . forEach ( textAnnotation => {
328
+ console . log ( `Text ${ textAnnotation . text } occurs at:` ) ;
329
+ textAnnotation . segments . forEach ( segment => {
330
+ const time = segment . segment ;
331
+ console . log (
332
+ ` Start: ${ time . startTimeOffset . seconds || 0 } .${ (
333
+ time . startTimeOffset . nanos / 1e6
334
+ ) . toFixed ( 0 ) } s`
335
+ ) ;
336
+ console . log (
337
+ ` End: ${ time . endTimeOffset . seconds || 0 } .${ (
338
+ time . endTimeOffset . nanos / 1e6
339
+ ) . toFixed ( 0 ) } s`
340
+ ) ;
341
+ console . log ( ` Confidence: ${ segment . confidence } ` ) ;
342
+ segment . frames . forEach ( frame => {
343
+ const timeOffset = frame . timeOffset ;
344
+ console . log (
345
+ `Time offset for the frame: ${ timeOffset . seconds || 0 } ` +
346
+ `.${ ( timeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
347
+ ) ;
348
+ console . log ( `Rotated Bounding Box Vertices:` ) ;
349
+ frame . rotatedBoundingBox . vertices . forEach ( vertex => {
350
+ console . log ( `Vertex.x:${ vertex . x } , Vertex.y:${ vertex . y } ` ) ;
351
+ } ) ;
352
+ } ) ;
353
+ } ) ;
354
+ } ) ;
355
+ // [END video_detect_text_gcs]
356
+ }
357
+
358
+ async function analyzeObjectTrackingGCS ( gcsUri ) {
359
+ //gcsUri - GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4
360
+ //[START video_object_tracking_gcs]
361
+ // Imports the Google Cloud Video Intelligence library
362
+ const Video = require ( '@google-cloud/video-intelligence' ) ;
363
+
364
+ // Creates a client
365
+ const video = new Video . VideoIntelligenceServiceClient ( ) ;
366
+
367
+ /**
368
+ * TODO(developer): Uncomment the following line before running the sample.
369
+ */
370
+ // const gcsUri = 'GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4';
371
+
372
+ const request = {
373
+ inputUri : gcsUri ,
374
+ features : [ 'OBJECT_TRACKING' ] ,
375
+ //recommended to use us-east1 for the best latency due to different types of processors used in this region and others
376
+ locationId : 'us-east1' ,
377
+ } ;
378
+ // Detects objects in a video
379
+ const [ operation ] = await video . annotateVideo ( request ) ;
380
+ const results = await operation . promise ( ) ;
381
+ console . log ( 'Waiting for operation to complete...' ) ;
382
+ //Gets annotations for video
383
+ const annotations = results [ 0 ] . annotationResults [ 0 ] ;
384
+ const objects = annotations . objectAnnotations ;
385
+ objects . forEach ( object => {
386
+ console . log ( `Entity description: ${ object . entity . description } ` ) ;
387
+ console . log ( `Entity id: ${ object . entity . entityId } ` ) ;
388
+ const time = object . segment ;
389
+ console . log (
390
+ `Segment: ${ time . startTimeOffset . seconds || 0 } ` +
391
+ `.${ ( time . startTimeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s to ${ time
392
+ . endTimeOffset . seconds || 0 } .` +
393
+ `${ ( time . endTimeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
394
+ ) ;
395
+ console . log ( `Confidence: ${ object . confidence } ` ) ;
396
+ const frame = object . frames [ 0 ] ;
397
+ const box = frame . normalizedBoundingBox ;
398
+ const timeOffset = frame . timeOffset ;
399
+ console . log (
400
+ `Time offset for the first frame: ${ timeOffset . seconds || 0 } ` +
401
+ `.${ ( timeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
402
+ ) ;
403
+ console . log ( `Bounding box position:` ) ;
404
+ console . log ( ` left :${ box . left } ` ) ;
405
+ console . log ( ` top :${ box . top } ` ) ;
406
+ console . log ( ` right :${ box . right } ` ) ;
407
+ console . log ( ` bottom :${ box . bottom } ` ) ;
408
+ } ) ;
409
+ // [END video_object_tracking_gcs]
410
+ }
411
+
412
+ async function analyzeText ( path ) {
413
+ //[START video_detect_text]
414
+ // Imports the Google Cloud Video Intelligence library + Node's fs library
415
+ const Video = require ( '@google-cloud/video-intelligence' ) ;
416
+ const fs = require ( 'fs' ) ;
417
+ const util = require ( 'util' ) ;
418
+ // Creates a client
419
+ const video = new Video . VideoIntelligenceServiceClient ( ) ;
420
+
421
+ /**
422
+ * TODO(developer): Uncomment the following line before running the sample.
423
+ */
424
+ // const path = 'Local file to analyze, e.g. ./my-file.mp4';
425
+
426
+ // Reads a local video file and converts it to base64
427
+ const file = await util . promisify ( fs . readFile ) ( path ) ;
428
+ const inputContent = file . toString ( 'base64' ) ;
429
+
430
+ const request = {
431
+ inputContent : inputContent ,
432
+ features : [ 'TEXT_DETECTION' ] ,
433
+ } ;
434
+ // Detects text in a video
435
+ const [ operation ] = await video . annotateVideo ( request ) ;
436
+ const results = await operation . promise ( ) ;
437
+ console . log ( 'Waiting for operation to complete...' ) ;
438
+
439
+ // Gets annotations for video
440
+ const textAnnotations = results [ 0 ] . annotationResults [ 0 ] . textAnnotations ;
441
+ textAnnotations . forEach ( textAnnotation => {
442
+ console . log ( `Text ${ textAnnotation . text } occurs at:` ) ;
443
+ textAnnotation . segments . forEach ( segment => {
444
+ const time = segment . segment ;
445
+ if ( time . startTimeOffset . seconds === undefined ) {
446
+ time . startTimeOffset . seconds = 0 ;
447
+ }
448
+ if ( time . startTimeOffset . nanos === undefined ) {
449
+ time . startTimeOffset . nanos = 0 ;
450
+ }
451
+ if ( time . endTimeOffset . seconds === undefined ) {
452
+ time . endTimeOffset . seconds = 0 ;
453
+ }
454
+ if ( time . endTimeOffset . nanos === undefined ) {
455
+ time . endTimeOffset . nanos = 0 ;
456
+ }
457
+ console . log (
458
+ `\tStart: ${ time . startTimeOffset . seconds || 0 } ` +
459
+ `.${ ( time . startTimeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
460
+ ) ;
461
+ console . log (
462
+ `\tEnd: ${ time . endTimeOffset . seconds || 0 } .` +
463
+ `${ ( time . endTimeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
464
+ ) ;
465
+ console . log ( `\tConfidence: ${ segment . confidence } ` ) ;
466
+ segment . frames . forEach ( frame => {
467
+ const timeOffset = frame . timeOffset ;
468
+ console . log (
469
+ `Time offset for the frame: ${ timeOffset . seconds || 0 } ` +
470
+ `.${ ( timeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
471
+ ) ;
472
+ console . log ( `Rotated Bounding Box Vertices:` ) ;
473
+ frame . rotatedBoundingBox . vertices . forEach ( vertex => {
474
+ console . log ( `Vertex.x:${ vertex . x } , Vertex.y:${ vertex . y } ` ) ;
475
+ } ) ;
476
+ } ) ;
477
+ } ) ;
478
+ } ) ;
479
+ // [END video_detect_text]
480
+ }
481
+
482
+ async function analyzeObjectTracking ( path ) {
483
+ //[START video_object_tracking]
484
+ // Imports the Google Cloud Video Intelligence library
485
+ const Video = require ( '@google-cloud/video-intelligence' ) ;
486
+ const fs = require ( 'fs' ) ;
487
+ const util = require ( 'util' ) ;
488
+ // Creates a client
489
+ const video = new Video . VideoIntelligenceServiceClient ( ) ;
490
+ /**
491
+ * TODO(developer): Uncomment the following line before running the sample.
492
+ */
493
+ // const path = 'Local file to analyze, e.g. ./my-file.mp4';
494
+
495
+ // Reads a local video file and converts it to base64
496
+ const file = await util . promisify ( fs . readFile ) ( path ) ;
497
+ const inputContent = file . toString ( 'base64' ) ;
498
+
499
+ const request = {
500
+ inputContent : inputContent ,
501
+ features : [ 'OBJECT_TRACKING' ] ,
502
+ //recommended to use us-east1 for the best latency due to different types of processors used in this region and others
503
+ locationId : 'us-east1' ,
504
+ } ;
505
+ // Detects objects in a video
506
+ const [ operation ] = await video . annotateVideo ( request ) ;
507
+ const results = await operation . promise ( ) ;
508
+ console . log ( 'Waiting for operation to complete...' ) ;
509
+ //Gets annotations for video
510
+ const annotations = results [ 0 ] . annotationResults [ 0 ] ;
511
+ const objects = annotations . objectAnnotations ;
512
+ objects . forEach ( object => {
513
+ console . log ( `Entity description: ${ object . entity . description } ` ) ;
514
+ console . log ( `Entity id: ${ object . entity . entityId } ` ) ;
515
+ const time = object . segment ;
516
+ console . log (
517
+ `Segment: ${ time . startTimeOffset . seconds || 0 } ` +
518
+ `.${ ( time . startTimeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s to ${ time
519
+ . endTimeOffset . seconds || 0 } .` +
520
+ `${ ( time . endTimeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
521
+ ) ;
522
+ console . log ( `Confidence: ${ object . confidence } ` ) ;
523
+ const frame = object . frames [ 0 ] ;
524
+ const box = frame . normalizedBoundingBox ;
525
+ const timeOffset = frame . timeOffset ;
526
+ console . log (
527
+ `Time offset for the first frame: ${ timeOffset . seconds || 0 } ` +
528
+ `.${ ( timeOffset . nanos / 1e6 ) . toFixed ( 0 ) } s`
529
+ ) ;
530
+ console . log ( `Bounding box position:` ) ;
531
+ console . log ( ` left :${ box . left } ` ) ;
532
+ console . log ( ` top :${ box . top } ` ) ;
533
+ console . log ( ` right :${ box . right } ` ) ;
534
+ console . log ( ` bottom :${ box . bottom } ` ) ;
535
+ } ) ;
536
+ // [END video_object_tracking]
537
+ }
538
+
304
539
async function main ( ) {
305
540
require ( `yargs` )
306
541
. demand ( 1 )
@@ -334,11 +569,41 @@ async function main() {
334
569
{ } ,
335
570
opts => analyzeVideoTranscription ( opts . gcsUri )
336
571
)
572
+ . command (
573
+ `video-text-gcs <gcsUri>` ,
574
+ `Analyzes text in a video stored in Google Cloud Storage using the Cloud Video Intelligence API.` ,
575
+ { } ,
576
+ opts => analyzeTextGCS ( opts . gcsUri )
577
+ )
578
+ . command (
579
+ `track-objects-gcs <gcsUri>` ,
580
+ `Analyzes objects in a video stored in Google Cloud Storage using the Cloud Video Intelligence API.` ,
581
+ { } ,
582
+ opts => analyzeObjectTrackingGCS ( opts . gcsUri )
583
+ )
584
+ . command (
585
+ `video-text <path>` ,
586
+ `Analyzes text in a video stored in a local file using the Cloud Video Intelligence API.` ,
587
+ { } ,
588
+ opts => analyzeText ( opts . path )
589
+ )
590
+ . command (
591
+ `track-objects <path>` ,
592
+ `Analyzes objects in a video stored in a local file using the Cloud Video Intelligence API.` ,
593
+ { } ,
594
+ opts => analyzeObjectTracking ( opts . path )
595
+ )
337
596
. example ( `node $0 shots gs://demomaker/sushi.mp4` )
338
597
. example ( `node $0 labels-gcs gs://demomaker/tomatoes.mp4` )
339
598
. example ( `node $0 labels-file cat.mp4` )
340
599
. example ( `node $0 safe-search gs://demomaker/tomatoes.mp4` )
341
600
. example ( `node $0 transcription gs://demomaker/tomatoes.mp4` )
601
+ . example ( `node $0 video-text ./resources/googlework_short.mp4` )
602
+ . example (
603
+ `node $0 video-text-gcs gs://nodejs-docs-samples/videos/googlework_short.mp4`
604
+ )
605
+ . example ( `node $0 track-objects ./resources/cat.mp4` )
606
+ . example ( `node $0 track-objects-gcs gs://nodejs-docs-samples/video/cat.mp4` )
342
607
. wrap ( 120 )
343
608
. recommendCommands ( )
344
609
. epilogue (
0 commit comments