@@ -301,6 +301,241 @@ async function analyzeVideoTranscription(gcsUri) {
301301 // [END video_speech_transcription_gcs]
302302}
303303
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+
304539async function main ( ) {
305540 require ( `yargs` )
306541 . demand ( 1 )
@@ -334,11 +569,41 @@ async function main() {
334569 { } ,
335570 opts => analyzeVideoTranscription ( opts . gcsUri )
336571 )
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+ )
337596 . example ( `node $0 shots gs://demomaker/sushi.mp4` )
338597 . example ( `node $0 labels-gcs gs://demomaker/tomatoes.mp4` )
339598 . example ( `node $0 labels-file cat.mp4` )
340599 . example ( `node $0 safe-search gs://demomaker/tomatoes.mp4` )
341600 . 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` )
342607 . wrap ( 120 )
343608 . recommendCommands ( )
344609 . epilogue (
0 commit comments