diff --git a/video/cloud-client/README.md b/video/cloud-client/README.md index d7b19d912f8..63d5920329e 100644 --- a/video/cloud-client/README.md +++ b/video/cloud-client/README.md @@ -36,7 +36,7 @@ After you have authorized, you can analyze videos. Detect Faces ``` java -cp target/video-google-cloud-samples-1.0.0-jar-with-dependencies.jar \ - com.example.video.Detect faces gs://cloudmleap/video/next/volleyball_court.mp4 + com.example.video.Detect faces gs://demomaker/google_gmail.mp4 ``` Detect Labels @@ -48,19 +48,19 @@ java -cp target/video-google-cloud-samples-1.0.0-jar-with-dependencies.jar \ com.example.video.Detect labels-file ./resources/cat.mp4 ``` -Detect Safe Search annotations +Detect Explicit content annotations ``` java -cp target/video-google-cloud-samples-1.0.0-jar-with-dependencies.jar \ - com.example.video.Detect safesearch gs://demomaker/cat.mp4 + com.example.video.Detect explicit-content gs://demomaker/gbikes_dinosaur.mp4 ``` Detect Shots ``` java -cp target/video-google-cloud-samples-1.0.0-jar-with-dependencies.jar \ - com.example.video.Detect shots gs://cloudmleap/video/next/gbikes_dinosaur.mp4 + com.example.video.Detect shots gs://demomaker/gbikes_dinosaur.mp4 ``` -From Windows, you may need to supply your classpath diferently, for example: +From Windows, you may need to supply your classpath differently, for example: ``` java -cp target\\video-google-cloud-samples-1.0.0-jar-with-dependencies.jar com.example.video.Detect labels gs://demomaker/cat.mp4 ``` diff --git a/video/cloud-client/src/main/java/com/example/video/Detect.java b/video/cloud-client/src/main/java/com/example/video/Detect.java index 4444ff492a8..d0b01152c87 100644 --- a/video/cloud-client/src/main/java/com/example/video/Detect.java +++ b/video/cloud-client/src/main/java/com/example/video/Detect.java @@ -17,25 +17,30 @@ package com.example.video; import com.google.api.gax.rpc.OperationFuture; -import com.google.cloud.videointelligence.v1beta1.AnnotateVideoProgress; -import com.google.cloud.videointelligence.v1beta1.AnnotateVideoRequest; -import com.google.cloud.videointelligence.v1beta1.AnnotateVideoResponse; -import com.google.cloud.videointelligence.v1beta1.FaceAnnotation; -import com.google.cloud.videointelligence.v1beta1.Feature; -import com.google.cloud.videointelligence.v1beta1.LabelAnnotation; -import com.google.cloud.videointelligence.v1beta1.LabelLocation; -import com.google.cloud.videointelligence.v1beta1.Likelihood; -import com.google.cloud.videointelligence.v1beta1.SafeSearchAnnotation; -import com.google.cloud.videointelligence.v1beta1.VideoAnnotationResults; -import com.google.cloud.videointelligence.v1beta1.VideoIntelligenceServiceClient; -import com.google.cloud.videointelligence.v1beta1.VideoIntelligenceServiceSettings; -import com.google.cloud.videointelligence.v1beta1.VideoSegment; +import com.google.cloud.videointelligence.v1beta2.AnnotateVideoProgress; +import com.google.cloud.videointelligence.v1beta2.AnnotateVideoRequest; +import com.google.cloud.videointelligence.v1beta2.AnnotateVideoResponse; +import com.google.cloud.videointelligence.v1beta2.Entity; +import com.google.cloud.videointelligence.v1beta2.ExplicitContentFrame; +import com.google.cloud.videointelligence.v1beta2.FaceAnnotation; +import com.google.cloud.videointelligence.v1beta2.FaceFrame; +import com.google.cloud.videointelligence.v1beta2.FaceSegment; +import com.google.cloud.videointelligence.v1beta2.Feature; +import com.google.cloud.videointelligence.v1beta2.LabelAnnotation; +import com.google.cloud.videointelligence.v1beta2.LabelDetectionConfig; +import com.google.cloud.videointelligence.v1beta2.LabelDetectionMode; +import com.google.cloud.videointelligence.v1beta2.LabelSegment; +import com.google.cloud.videointelligence.v1beta2.NormalizedBoundingBox; +import com.google.cloud.videointelligence.v1beta2.VideoAnnotationResults; +import com.google.cloud.videointelligence.v1beta2.VideoContext; +import com.google.cloud.videointelligence.v1beta2.VideoIntelligenceServiceClient; +import com.google.cloud.videointelligence.v1beta2.VideoSegment; import com.google.longrunning.Operation; +import com.google.protobuf.ByteString; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.concurrent.ExecutionException; import org.apache.commons.codec.binary.Base64; @@ -46,7 +51,7 @@ public class Detect { * * @throws IOException on Input/Output errors. */ - public static void main(String[] args) throws IOException, InterruptedException { + public static void main(String[] args) throws Exception { try { argsHelper(args); } catch (Exception e) { @@ -61,8 +66,7 @@ public static void main(String[] args) throws IOException, InterruptedException * * @throws IOException on Input/Output errors. */ - public static void argsHelper(String[] args) throws - ExecutionException, IOException, InterruptedException { + public static void argsHelper(String[] args) throws Exception { if (args.length < 1) { System.out.println("Usage:"); System.out.printf( @@ -89,8 +93,8 @@ public static void argsHelper(String[] args) throws if (command.equals("shots")) { analyzeShots(path); } - if (command.equals("safesearch")) { - analyzeSafeSearch(path); + if (command.equals("explicit-content")) { + analyzeExplicitContent(path); } } @@ -99,39 +103,60 @@ public static void argsHelper(String[] args) throws * * @param gcsUri the path to the video file to analyze. */ - public static void analyzeFaces(String gcsUri) throws ExecutionException, - IOException, InterruptedException { - VideoIntelligenceServiceSettings settings = - VideoIntelligenceServiceSettings.defaultBuilder().build(); - VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create(settings); - - - // Create an operation that will contain the response when the operation completes. - AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() - .setInputUri(gcsUri) - .addFeatures(Feature.FACE_DETECTION) - .build(); - - OperationFuture operation = - client.annotateVideoAsync(request); - - System.out.println("Waiting for operation to complete..."); - for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { - if (result.getFaceAnnotationsCount() > 0) { - System.out.println("Faces:"); - for (FaceAnnotation annotation : result.getFaceAnnotationsList()) { - System.out.println("\tFace Thumb is of length: " + annotation.getThumbnail().length()); - for (VideoSegment seg : annotation.getSegmentsList()) { - System.out.printf("\t\tLocation: %fs - %fs\n", - seg.getStartTimeOffset() / 1000000.0, - seg.getEndTimeOffset() / 1000000.0); + public static void analyzeFaces(String gcsUri) throws Exception { + // [START detect_faces] + // Instantiate a com.google.cloud.videointelligence.v1beta2.VideoIntelligenceServiceClient + try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) { + // detect shot and frame + LabelDetectionConfig labelDetectionConfig = LabelDetectionConfig.newBuilder() + .setLabelDetectionMode(LabelDetectionMode.SHOT_AND_FRAME_MODE) + .build(); + + VideoContext videoContext = VideoContext.newBuilder() + .setLabelDetectionConfig(labelDetectionConfig) + .build(); + + AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() + .setInputUri(gcsUri) + .setVideoContext(videoContext) + .addFeatures(Feature.LABEL_DETECTION) + .build(); + + // asynchronously perform facial analysis on videos + OperationFuture response + = client.annotateVideoAsync(request); + + boolean faceFound = false; + for (VideoAnnotationResults results : response.get().getAnnotationResultsList()) { + int faceCount = 0; + for (FaceAnnotation faceAnnotation : results.getFaceAnnotationsList()) { + faceFound = true; + System.out.println("Face: " + ++faceCount); + System.out.println("Thumbnail size: " + faceAnnotation.getThumbnail().size()); + for (FaceSegment segment : faceAnnotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location : %.3f:%.3f\n", startTime, endTime); } - System.out.println(); + // printing info on the first frame + FaceFrame frame = faceAnnotation.getFrames(0); + double timeOffset = frame.getTimeOffset().getSeconds() + + frame.getTimeOffset().getNanos() / 1e9; + System.out.printf("First frame time offset: %.3fs", timeOffset); + // print info on the first normalized bounding box + NormalizedBoundingBox box = frame.getNormalizedBoundingBoxesList().get(0); + System.out.printf("Left: %.3f\n", box.getLeft()); + System.out.printf("Top: %.3f\n", box.getTop()); + System.out.printf("Bottom: %.3f\n", box.getBottom()); + System.out.printf("Right: %.3f\n", box.getRight()); } - System.out.println(); - } else { + } + if (!faceFound) { System.out.println("No faces detected in " + gcsUri); } + // [END detect_faces] } } @@ -140,44 +165,81 @@ public static void analyzeFaces(String gcsUri) throws ExecutionException, * * @param gcsUri the path to the video file to analyze. */ - public static void analyzeLabels(String gcsUri) throws - ExecutionException, IOException, InterruptedException { - VideoIntelligenceServiceSettings settings = - VideoIntelligenceServiceSettings.defaultBuilder().build(); - VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create(settings); - - // Create an operation that will contain the response when the operation completes. - AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() - .setInputUri(gcsUri) - .addFeatures(Feature.LABEL_DETECTION) - .build(); + public static void analyzeLabels(String gcsUri) throws Exception { + // [START detect_labels_gcs] + // Instantiate a com.google.cloud.videointelligence.v1beta2.VideoIntelligenceServiceClient + try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) { + // Provide path to file hosted on GCS as "gs://bucket-name/..." + AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() + .setInputUri(gcsUri) + .addFeatures(Feature.LABEL_DETECTION) + .build(); + // Create an operation that will contain the response when the operation completes. + OperationFuture operation = + client.annotateVideoAsync(request); + + System.out.println("Waiting for operation to complete..."); + for (VideoAnnotationResults results : operation.get().getAnnotationResultsList()) { + // process video / segment level label annotations + System.out.println("Locations: "); + for (LabelAnnotation labelAnnotation : results.getSegmentLabelAnnotationsList()) { + System.out + .println("Video label: " + labelAnnotation.getEntity().getDescription()); + // categories + for (Entity categoryEntity : labelAnnotation.getCategoryEntitiesList()) { + System.out.println("Video label category: " + categoryEntity.getDescription()); + } + // segments + for (LabelSegment segment : labelAnnotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location: %.3f:%.3f\n", startTime, endTime); + System.out.println("Confidence: " + segment.getConfidence()); + } + } - OperationFuture operation = - client.annotateVideoAsync(request); + // process shot label annotations + for (LabelAnnotation labelAnnotation : results.getShotLabelAnnotationsList()) { + System.out + .println("Shot label: " + labelAnnotation.getEntity().getDescription()); + // categories + for (Entity categoryEntity : labelAnnotation.getCategoryEntitiesList()) { + System.out.println("Shot label category: " + categoryEntity.getDescription()); + } + // segments + for (LabelSegment segment : labelAnnotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location: %.3f:%.3f\n", startTime, endTime); + System.out.println("Confidence: " + segment.getConfidence()); + } + } - System.out.println("Waiting for operation to complete..."); - for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { - if (result.getLabelAnnotationsCount() > 0) { - System.out.println("Labels:"); - for (LabelAnnotation annotation : result.getLabelAnnotationsList()) { - System.out.println("\tDescription: " + annotation.getDescription()); - for (LabelLocation loc : annotation.getLocationsList()) { - if (loc.getSegment().getStartTimeOffset() == -1 - && loc.getSegment().getEndTimeOffset() == -1) { - System.out.println("\tLocation: Entire video"); - } else { - System.out.printf( - "\tLocation: %fs - %fs\n", - loc.getSegment().getStartTimeOffset() / 1000000.0, - loc.getSegment().getEndTimeOffset() / 1000000.0); - } + // process frame label annotations + for (LabelAnnotation labelAnnotation : results.getFrameLabelAnnotationsList()) { + System.out + .println("Frame label: " + labelAnnotation.getEntity().getDescription()); + // categories + for (Entity categoryEntity : labelAnnotation.getCategoryEntitiesList()) { + System.out.println("Frame label category: " + categoryEntity.getDescription()); + } + // segments + for (LabelSegment segment : labelAnnotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location: %.3f:%.2f\n", startTime, endTime); + System.out.println("Confidence: " + segment.getConfidence()); } - System.out.println(); } - } else { - System.out.println("No labels detected in " + gcsUri); } } + // [END detect_labels_gcs] } /** @@ -185,47 +247,86 @@ public static void analyzeLabels(String gcsUri) throws * * @param filePath the path to the video file to analyze. */ - public static void analyzeLabelsFile(String filePath) throws - ExecutionException, IOException, InterruptedException { - VideoIntelligenceServiceSettings settings = - VideoIntelligenceServiceSettings.defaultBuilder().build(); - VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create(settings); - - Path path = Paths.get(filePath); - byte[] data = Files.readAllBytes(path); - byte[] encodedBytes = Base64.encodeBase64(data); - - AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() - .setInputContent(new String(encodedBytes, "UTF-8")) - .addFeatures(Feature.LABEL_DETECTION) - .build(); + public static void analyzeLabelsFile(String filePath) throws Exception { + // [START detect_labels_file] + // Instantiate a com.google.cloud.videointelligence.v1beta2.VideoIntelligenceServiceClient + try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) { + // Read file and encode into Base64 + Path path = Paths.get(filePath); + byte[] data = Files.readAllBytes(path); + byte[] encodedBytes = Base64.encodeBase64(data); + + AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() + .setInputContent(ByteString.copyFrom(encodedBytes)) + .addFeatures(Feature.LABEL_DETECTION) + .build(); + + // Create an operation that will contain the response when the operation completes. + OperationFuture operation = + client.annotateVideoAsync(request); + + System.out.println("Waiting for operation to complete..."); + for (VideoAnnotationResults results : operation.get().getAnnotationResultsList()) { + // process video / segment level label annotations + System.out.println("Locations: "); + for (LabelAnnotation labelAnnotation : results.getSegmentLabelAnnotationsList()) { + System.out + .println("Video label: " + labelAnnotation.getEntity().getDescription()); + // categories + for (Entity categoryEntity : labelAnnotation.getCategoryEntitiesList()) { + System.out.println("Video label category: " + categoryEntity.getDescription()); + } + // segments + for (LabelSegment segment : labelAnnotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location: %.3f:%.2f\n", startTime, endTime); + System.out.println("Confidence: " + segment.getConfidence()); + } + } - OperationFuture operation = - client.annotateVideoAsync(request); + // process shot label annotations + for (LabelAnnotation labelAnnotation : results.getShotLabelAnnotationsList()) { + System.out + .println("Shot label: " + labelAnnotation.getEntity().getDescription()); + // categories + for (Entity categoryEntity : labelAnnotation.getCategoryEntitiesList()) { + System.out.println("Shot label category: " + categoryEntity.getDescription()); + } + // segments + for (LabelSegment segment : labelAnnotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location: %.3f:%.2f\n", startTime, endTime); + System.out.println("Confidence: " + segment.getConfidence()); + } + } - System.out.println("Waiting for operation to complete..."); - for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { - if (result.getLabelAnnotationsCount() > 0) { - System.out.println("Labels:"); - for (LabelAnnotation annotation : result.getLabelAnnotationsList()) { - System.out.println("\tDescription: " + annotation.getDescription()); - for (LabelLocation loc : annotation.getLocationsList()) { - if (loc.getSegment().getStartTimeOffset() == -1 - && loc.getSegment().getEndTimeOffset() == -1) { - System.out.println("\tLocation: Entire video"); - } else { - System.out.printf( - "\tLocation: %fs - %fs\n", - loc.getSegment().getStartTimeOffset() / 1000000.0, - loc.getSegment().getEndTimeOffset() / 1000000.0); - } + // process frame label annotations + for (LabelAnnotation labelAnnotation : results.getFrameLabelAnnotationsList()) { + System.out + .println("Frame label: " + labelAnnotation.getEntity().getDescription()); + // categories + for (Entity categoryEntity : labelAnnotation.getCategoryEntitiesList()) { + System.out.println("Frame label category: " + categoryEntity.getDescription()); + } + // segments + for (LabelSegment segment : labelAnnotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location: %.3f:%.2f\n", startTime, endTime); + System.out.println("Confidence: " + segment.getConfidence()); } - System.out.println(); } - } else { - System.out.println("No labels detected in " + filePath); } } + // [END detect_labels_file] } /** @@ -233,92 +334,70 @@ public static void analyzeLabelsFile(String filePath) throws * * @param gcsUri the path to the video file to analyze. */ - public static void analyzeShots(String gcsUri) - throws ExecutionException, IOException, InterruptedException { - VideoIntelligenceServiceSettings settings = - VideoIntelligenceServiceSettings.defaultBuilder().build(); - VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create(settings); - - // Create an operation that will contain the response when the operation completes. - AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() - .setInputUri(gcsUri) - .addFeatures(Feature.SHOT_CHANGE_DETECTION) - .build(); - - OperationFuture operation = - client.annotateVideoAsync(request); - - System.out.println("Waiting for operation to complete..."); - - // Print detected shot changes and their location ranges in the analyzed video. - for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { - if (result.getShotAnnotationsCount() > 0) { - System.out.println("Shots:"); - int segCount = 0; - for (VideoSegment seg : result.getShotAnnotationsList()) { - System.out.println("\tSegment: " + segCount++); - System.out.printf("\tLocation: %fs - %fs\n", - seg.getStartTimeOffset() / 1000000.0, - seg.getEndTimeOffset() / 1000000.0); + public static void analyzeShots(String gcsUri) throws Exception { + // [START detect_shots] + // Instantiate a com.google.cloud.videointelligence.v1beta2.VideoIntelligenceServiceClient + try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) { + // Provide path to file hosted on GCS as "gs://bucket-name/..." + AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() + .setInputUri(gcsUri) + .addFeatures(Feature.SHOT_CHANGE_DETECTION) + .build(); + + // Create an operation that will contain the response when the operation completes. + OperationFuture operation = + client.annotateVideoAsync(request); + System.out.println("Waiting for operation to complete..."); + + // Print detected shot changes and their location ranges in the analyzed video. + for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { + if (result.getShotAnnotationsCount() > 0) { + System.out.println("Shots: "); + for (VideoSegment segment : result.getShotAnnotationsList()) { + double startTime = segment.getStartTimeOffset().getSeconds() + + segment.getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getEndTimeOffset().getSeconds() + + segment.getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Location: %.3f:%.3f\n", startTime, endTime); + } + } else { + System.out.println("No shot changes detected in " + gcsUri); } - System.out.println(); - } else { - System.out.println("No shot changes detected in " + gcsUri); } } + // [END detect_shots] } /** - * Performs safe search analysis on the video at the provided Cloud Storage path. + * Performs explicit content analysis on the video at the provided Cloud Storage path. * * @param gcsUri the path to the video file to analyze. */ - public static void analyzeSafeSearch(String gcsUri) - throws ExecutionException, IOException, InterruptedException { - VideoIntelligenceServiceSettings settings = - VideoIntelligenceServiceSettings.defaultBuilder().build(); - VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create(settings); - - // Create an operation that will contain the response when the operation completes. - AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() - .setInputUri(gcsUri) - .addFeatures(Feature.SAFE_SEARCH_DETECTION) - .build(); - - OperationFuture operation = - client.annotateVideoAsync(request); - - System.out.println("Waiting for operation to complete..."); - - // Print detected safe search annotations and their positions in the analyzed video. - boolean foundUnsafe = false; - for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { - if (result.getSafeSearchAnnotationsCount() > 0) { - System.out.println("Safe search annotations:"); - for (SafeSearchAnnotation note : result.getSafeSearchAnnotationsList()) { - System.out.printf("Location: %fs\n", note.getTimeOffset() / 1000000.0); - System.out.println("\tAdult: " + note.getAdult().name()); - System.out.println("\tMedical: " + note.getMedical().name()); - System.out.println("\tRacy: " + note.getRacy().name()); - System.out.println("\tSpoof: " + note.getSpoof().name()); - System.out.println("\tViolent: " + note.getViolent().name()); - System.out.println(); - - if (note.getAdult().compareTo(Likelihood.LIKELY) > 1 - || note.getViolent().compareTo(Likelihood.LIKELY) > 1 - || note.getRacy().compareTo(Likelihood.LIKELY) > 1) { - foundUnsafe = false; - } + public static void analyzeExplicitContent(String gcsUri) throws Exception { + // [START detect_explicit_content] + // Instantiate a com.google.cloud.videointelligence.v1beta2.VideoIntelligenceServiceClient + try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) { + // Create an operation that will contain the response when the operation completes. + AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() + .setInputUri(gcsUri) + .addFeatures(Feature.EXPLICIT_CONTENT_DETECTION) + .build(); + + OperationFuture operation = + client.annotateVideoAsync(request); + + System.out.println("Waiting for operation to complete..."); + + // Print detected annotations and their positions in the analyzed video. + for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { + for (ExplicitContentFrame frame : result.getExplicitAnnotation().getFramesList()) { + double frameTime = + frame.getTimeOffset().getSeconds() + frame.getTimeOffset().getNanos() / 1e9; + System.out.printf("Location: %.3fs\n", frameTime); + System.out.println("Adult: " + frame.getPornographyLikelihood()); } - } else { - System.out.println("No safe search annotations detected in " + gcsUri); } - } - - if (foundUnsafe) { - System.out.println("Found potentially unsafe content."); - } else { - System.out.println("Did not detect unsafe content."); + // [END detect_explicit_content] } } } diff --git a/video/cloud-client/src/main/java/com/example/video/QuickstartSample.java b/video/cloud-client/src/main/java/com/example/video/QuickstartSample.java index dbf166eb567..b6f8c8cee75 100644 --- a/video/cloud-client/src/main/java/com/example/video/QuickstartSample.java +++ b/video/cloud-client/src/main/java/com/example/video/QuickstartSample.java @@ -19,61 +19,65 @@ // [START videointelligence_quickstart] import com.google.api.gax.rpc.OperationFuture; -import com.google.cloud.videointelligence.v1beta1.AnnotateVideoProgress; -import com.google.cloud.videointelligence.v1beta1.AnnotateVideoRequest; -import com.google.cloud.videointelligence.v1beta1.AnnotateVideoResponse; -import com.google.cloud.videointelligence.v1beta1.Feature; -import com.google.cloud.videointelligence.v1beta1.LabelAnnotation; -import com.google.cloud.videointelligence.v1beta1.LabelLocation; -import com.google.cloud.videointelligence.v1beta1.VideoAnnotationResults; -import com.google.cloud.videointelligence.v1beta1.VideoIntelligenceServiceClient; -import com.google.cloud.videointelligence.v1beta1.VideoIntelligenceServiceSettings; +import com.google.cloud.videointelligence.v1beta2.AnnotateVideoProgress; +import com.google.cloud.videointelligence.v1beta2.AnnotateVideoRequest; +import com.google.cloud.videointelligence.v1beta2.AnnotateVideoResponse; +import com.google.cloud.videointelligence.v1beta2.Entity; +import com.google.cloud.videointelligence.v1beta2.Feature; +import com.google.cloud.videointelligence.v1beta2.LabelAnnotation; +import com.google.cloud.videointelligence.v1beta2.LabelSegment; +import com.google.cloud.videointelligence.v1beta2.VideoAnnotationResults; +import com.google.cloud.videointelligence.v1beta2.VideoIntelligenceServiceClient; import com.google.longrunning.Operation; -import java.io.IOException; -import java.util.concurrent.ExecutionException; - +import java.util.List; public class QuickstartSample { - public static void main(String[] args) throws - ExecutionException, IOException, InterruptedException { - // Instantiate the client - VideoIntelligenceServiceSettings settings = - VideoIntelligenceServiceSettings.defaultBuilder().build(); - VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create(settings); - // The Google Cloud Storage path to the video to annotate. - String gcsUri = "gs://demomaker/cat.mp4"; + /** + * Demonstrates using the video intelligence client to detect labels in a video file. + */ + public static void main(String[] args) throws Exception { + // Instantiate a video intelligence client + try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) { + // The Google Cloud Storage path to the video to annotate. + String gcsUri = "gs://demomaker/cat.mp4"; + + // Create an operation that will contain the response when the operation completes. + AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() + .setInputUri(gcsUri) + .addFeatures(Feature.LABEL_DETECTION) + .build(); - // Create an operation that will contain the response when the operation completes. - AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() - .setInputUri(gcsUri) - .addFeatures(Feature.LABEL_DETECTION) - .build(); + OperationFuture operation = + client.annotateVideoAsync(request); - OperationFuture operation = - client.annotateVideoAsync(request); + System.out.println("Waiting for operation to complete..."); - System.out.println("Waiting for operation to complete..."); - for (VideoAnnotationResults result : operation.get().getAnnotationResultsList()) { - if (result.getLabelAnnotationsCount() > 0) { + List results = operation.get().getAnnotationResultsList(); + if (results.isEmpty()) { + System.out.println("No labels detected in " + gcsUri); + return; + } + for (VideoAnnotationResults result : results) { System.out.println("Labels:"); - for (LabelAnnotation annotation : result.getLabelAnnotationsList()) { - System.out.println("\tDescription: " + annotation.getDescription()); - for (LabelLocation loc : annotation.getLocationsList()) { - if (loc.getSegment().getStartTimeOffset() == -1 - && loc.getSegment().getEndTimeOffset() == -1) { - System.out.println("\tLocation: Entire video"); - } else { - System.out.printf( - "\tLocation: %fs - %fs\n", - loc.getSegment().getStartTimeOffset() / 1000000.0, - loc.getSegment().getEndTimeOffset() / 1000000.0); - } + // get video segment label annotations + for (LabelAnnotation annotation : result.getSegmentLabelAnnotationsList()) { + System.out + .println("Video label description : " + annotation.getEntity().getDescription()); + // categories + for (Entity categoryEntity : annotation.getCategoryEntitiesList()) { + System.out.println("Label Category description : " + categoryEntity.getDescription()); + } + // segments + for (LabelSegment segment : annotation.getSegmentsList()) { + double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; + double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; + System.out.printf("Segment location : %.3f:%.3f\n", startTime, endTime); + System.out.println("Confidence : " + segment.getConfidence()); } - System.out.println(); } - } else { - System.out.println("No labels detected in " + gcsUri); } } } diff --git a/video/cloud-client/src/test/java/com/example/video/DetectIT.java b/video/cloud-client/src/test/java/com/example/video/DetectIT.java index eb43a148341..5c6ccba8e4d 100644 --- a/video/cloud-client/src/test/java/com/example/video/DetectIT.java +++ b/video/cloud-client/src/test/java/com/example/video/DetectIT.java @@ -18,29 +18,25 @@ import static com.google.common.truth.Truth.assertThat; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.concurrent.ExecutionException; - /** Tests for video analysis sample. */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") public class DetectIT { private ByteArrayOutputStream bout; private PrintStream out; - private Detect app; static final String FACES_FILE_LOCATION = "gs://demomaker/gbike.mp4"; static final String LABEL_FILE_LOCATION = "gs://demomaker/cat.mp4"; static final String SHOTS_FILE_LOCATION = "gs://demomaker/gbikes_dinosaur.mp4"; - static final String SAFE_SEARCH_FILE_LOCATION = "gs://cloudmleap/video/next/animals.mp4"; + static final String EXPLICIT_CONTENT_LOCATION = "gs://demomaker/cat.mp4"; @Before public void setUp() { @@ -55,16 +51,15 @@ public void tearDown() { } @Test - public void testFaces() throws IOException, InterruptedException, ExecutionException { + public void testFaces() throws Exception { String[] args = {"faces", FACES_FILE_LOCATION}; Detect.argsHelper(args); String got = bout.toString(); - // Model changes have caused the results from face detection to change to an // empty response (e.g. no faces detected) so we check either for an empty // response or that a response with face thumbnails was returned. - if (got.indexOf("No faces detected") == 0) { - assertThat(got).contains("Face Thumb is of size:"); + if (got.indexOf("No faces detected") == -1) { + assertThat(got).contains("Thumbnail size:"); } else { // No faces detected, verify sample reports this. assertThat(got).contains("No faces detected in " + FACES_FILE_LOCATION); @@ -72,37 +67,28 @@ public void testFaces() throws IOException, InterruptedException, ExecutionExcep } @Test - public void testLabels() throws IOException, InterruptedException, ExecutionException { + public void testLabels() throws Exception { String[] args = {"labels", LABEL_FILE_LOCATION}; Detect.argsHelper(args); String got = bout.toString(); - // Test that the video with a cat has the whiskers label (may change). assertThat(got.toUpperCase()).contains("WHISKERS"); } @Test - public void testSafeSearch() throws IOException, InterruptedException, ExecutionException { - String[] args = {"safesearch", SAFE_SEARCH_FILE_LOCATION}; - app.argsHelper(args); + public void testExplicitContent() throws Exception { + String[] args = {"explicit-content", EXPLICIT_CONTENT_LOCATION}; + Detect.argsHelper(args); String got = bout.toString(); - - // Check that the API returned at least one safe search annotation. - assertThat(got).contains("Medical:"); - // Check that the API detected positions for the annotations. - assertThat(got).contains("Location: "); + assertThat(got).contains("Adult: VERY_UNLIKELY"); } @Test - public void testShots() throws IOException, InterruptedException, ExecutionException { + public void testShots() throws Exception { String[] args = {"shots", SHOTS_FILE_LOCATION}; - app.argsHelper(args); + Detect.argsHelper(args); String got = bout.toString(); - - // Check that the API returned at least one segment. - assertThat(got).contains("Segment:"); - // Check that the API detected a segment at the begining of the video. + assertThat(got).contains("Shots:"); assertThat(got).contains("Location: 0"); } - } diff --git a/video/cloud-client/src/test/java/com/example/video/QuickstartIT.java b/video/cloud-client/src/test/java/com/example/video/QuickstartIT.java index e537a199f96..94a7969c242 100644 --- a/video/cloud-client/src/test/java/com/example/video/QuickstartIT.java +++ b/video/cloud-client/src/test/java/com/example/video/QuickstartIT.java @@ -18,17 +18,14 @@ import static com.google.common.truth.Truth.assertThat; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.concurrent.ExecutionException; - /** Tests for video analysis sample. */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") @@ -49,7 +46,7 @@ public void tearDown() { } @Test - public void test() throws IOException, InterruptedException, ExecutionException { + public void test() throws Exception { QuickstartSample.main(new String[0]); String got = bout.toString();