Analyzing Videos for Explicit Content Detection Annotations

Explicit Content Detection detects adult content within a video. Adult content is content generally appropriate for 18 years of age and older, including but not limited to nudity, sexual activities, and pornography (including cartoons or anime).

The response includes a bucketized likelihood value, from VERY_UNLIKELY to VERY_LIKELY.

When Explicit Content Detection evaluates a video, it does so on a per-frame basis and considers visual content only. The audio component of the video is not used to evaluate the explicit content level. Google does not guarantee the accuracy of its Explicit Content Detection predictions.

Here is an example of performing video analysis for Explicit Content Detection features on a file located in Google Cloud Storage.

Protocol

Refer to the videos:annotate API endpoint for complete details.

To perform label detection, make a POST request and provide the appropriate request body:

POST https://videointelligence.googleapis.com/v1/videos:annotate?key=YOUR_API_KEY
{
  "inputUri": "gs://demomaker/gbikes_dinosaur.mp4",
  "features": ["EXPLICIT_CONTENT_DETECTION"]
}

A successful Video Intelligence annotation request returns a response with a single name field:

{
  "name": "us-west1.16680573"
}

This name represents a long-running operation, which can be queried using the v1.operations API.

To retrieve your video annotation response, send a GET request to the v1.operations endpoint, passing the value of name in the URL. If the operation has completed, it will return your annotation results.

Label search annotations are returned as a explicitAnnotation list.

{
  "name": "us-west1.10950655717927258341",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.videointelligence.v1.AnnotateVideoProgress",
    "annotationProgress": [
      {
        "inputUri": "/demomaker/gbikes_dinosaur.mp4",
        "progressPercent": 100,
        "startTime": "2017-08-26T00:16:35.112404Z",
        "updateTime": "2017-08-26T00:16:55.937889Z"
      }
    ]
  },
  "done": true,
  "response": {
   "@type": "type.googleapis.com/google.cloud.videointelligence.v1.AnnotateVideoResponse",
    "annotationResults": [
      {
        "inputUri": "/demomaker/gbikes_dinosaur.mp4",
        "explicitAnnotation": {
          "frames": [
            {
              "timeOffset": "0.056149s",
              "pornographyLikelihood": "VERY_UNLIKELY"
            },
            {
              "timeOffset": "1.166841s",
              "pornographyLikelihood": "VERY_UNLIKELY"
            },
        ...
            {
              "timeOffset": "41.678209s",
              "pornographyLikelihood": "VERY_UNLIKELY"
            },
            {
              "timeOffset": "42.596413s",
              "pornographyLikelihood": "VERY_UNLIKELY"
            }
          ]
        }
      }
    ]
  }
}

C#

public static object AnalyzeExplicitContentGcs(string uri)
{
    var client = VideoIntelligenceServiceClient.Create();
    var request = new AnnotateVideoRequest()
    {
        InputUri = uri,
        Features = { Feature.ExplicitContentDetection }
    };
    var op = client.AnnotateVideo(request).PollUntilCompleted();
    foreach (var result in op.Result.AnnotationResults)
    {
        foreach (var frame in result.ExplicitAnnotation.Frames)
        {
            Console.WriteLine("Time Offset: {0}", frame.TimeOffset);
            Console.WriteLine("Pornography Likelihood: {0}", frame.PornographyLikelihood);
            Console.WriteLine();
        }
    }
    return 0;
}

Go

func explicitContentURI(w io.Writer, file string) error {
	ctx := context.Background()
	client, err := video.NewClient(ctx)
	if err != nil {
		return err
	}

	op, err := client.AnnotateVideo(ctx, &videopb.AnnotateVideoRequest{
		Features: []videopb.Feature{
			videopb.Feature_EXPLICIT_CONTENT_DETECTION,
		},
		InputUri: file,
	})
	if err != nil {
		return err
	}
	resp, err := op.Wait(ctx)
	if err != nil {
		return err
	}

	// A single video was processed. Get the first result.
	result := resp.AnnotationResults[0].ExplicitAnnotation

	for _, frame := range result.Frames {
		offset, _ := ptypes.Duration(frame.TimeOffset)
		fmt.Fprintf(w, "%s - %s\n", offset, frame.PornographyLikelihood.String())
	}

	return nil
}

Java

// Instantiate a com.google.cloud.videointelligence.v1.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<AnnotateVideoResponse, AnnotateVideoProgress> response =
      client.annotateVideoAsync(request);

  System.out.println("Waiting for operation to complete...");
  // Print detected annotations and their positions in the analyzed video.
  for (VideoAnnotationResults result : response.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());
    }
  }

Node.js

// Imports the Google Cloud Video Intelligence library
const video = require('@google-cloud/video-intelligence').v1;

// Creates a client
const client = new video.VideoIntelligenceServiceClient();

/**
 * TODO(developer): Uncomment the following line before running the sample.
 */
// const gcsUri = 'GCS URI of video to analyze, e.g. gs://my-bucket/my-video.mp4';

const request = {
  inputUri: gcsUri,
  features: ['EXPLICIT_CONTENT_DETECTION'],
};

// Human-readable likelihoods
const likelihoods = [
  'UNKNOWN',
  'VERY_UNLIKELY',
  'UNLIKELY',
  'POSSIBLE',
  'LIKELY',
  'VERY_LIKELY',
];

// Detects unsafe content
client
  .annotateVideo(request)
  .then(results => {
    const operation = results[0];
    console.log('Waiting for operation to complete...');
    return operation.promise();
  })
  .then(results => {
    // Gets unsafe content
    const explicitContentResults =
      results[0].annotationResults[0].explicitAnnotation;
    console.log('Explicit annotation results:');
    explicitContentResults.frames.forEach(result => {
      if (result.timeOffset === undefined) {
        result.timeOffset = {};
      }
      if (result.timeOffset.seconds === undefined) {
        result.timeOffset.seconds = 0;
      }
      if (result.timeOffset.nanos === undefined) {
        result.timeOffset.nanos = 0;
      }
      console.log(
        `\tTime: ${result.timeOffset.seconds}` +
          `.${(result.timeOffset.nanos / 1e6).toFixed(0)}s`
      );
      console.log(
        `\t\tPornography liklihood: ${
          likelihoods[result.pornographyLikelihood]
        }`
      );
    });
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

Python

For more information on installing and using the Cloud Video Intelligence API Client Library for Python, refer to Cloud Video Intelligence API Client Libraries.
def analyze_explicit_content(path):
    """ Detects explicit content from the GCS path to a video. """
    video_client = videointelligence.VideoIntelligenceServiceClient()
    features = [videointelligence.enums.Feature.EXPLICIT_CONTENT_DETECTION]

    operation = video_client.annotate_video(path, features=features)
    print('\nProcessing video for explicit content annotations:')

    result = operation.result(timeout=90)
    print('\nFinished processing.')

    likely_string = ("Unknown", "Very unlikely", "Unlikely", "Possible",
                     "Likely", "Very likely")

    # first result is retrieved because a single video was processed
    for frame in result.annotation_results[0].explicit_annotation.frames:
        frame_time = frame.time_offset.seconds + frame.time_offset.nanos / 1e9
        print('Time: {}s'.format(frame_time))
        print('\tpornography: {}'.format(
            likely_string[frame.pornography_likelihood]))

PHP

use Google\Cloud\VideoIntelligence\V1\VideoIntelligenceServiceClient;
use Google\Cloud\Videointelligence\V1\Feature;

/**
 * Analyze explicit content in the video.
 *
 * @param string $uri The cloud storage object to analyze. Must be formatted
 *                    like gs://bucketname/objectname
 */
function analyze_explicit_content($uri)
{
    # Instantiate a client.
    $video = new VideoIntelligenceServiceClient();

    # Execute a request.
    $options = ['inputUri'=>$uri, 'features'=>[Feature::EXPLICIT_CONTENT_DETECTION]];
    $operation = $video->annotateVideo($options);

    # Wait for the request to complete.
    $operation->pollUntilComplete();

    # Print the result.
    if ($operation->operationSucceeded()) {
        $likelihoods = ['Unknown', 'Very unlikely', 'Unlikely', 'Possible',
                        'Likely', 'Very likely'];
        $results = $operation->getResult()->getAnnotationResults()[0];
        $explicitAnnotation = $results->getExplicitAnnotation();
        foreach ($explicitAnnotation->getFrames() as $frame) {
            $timeOffset = $frame->getTimeOffset();
            $seconds = $timeOffset->getSeconds();
            $nanoseconds = floatval($timeOffset->getNanos())/1000000000.00;
            $time = $seconds + $nanoseconds;
            printf('At %ss:' . PHP_EOL, $time);
            printf('  pornography: ' . $likelihoods[$frame->getPornographyLikelihood()] . PHP_EOL);
        }
    } else {
        print_r($operation->getError());
    }
}

Ruby

# path = "Path to a video file on Google Cloud Storage: gs://bucket/video.mp4"

require "google/cloud/video_intelligence"

video = Google::Cloud::VideoIntelligence.new

# Register a callback during the method call
operation = video.annotate_video input_uri: path, features: [:EXPLICIT_CONTENT_DETECTION] do |operation|
  raise operation.results.message? if operation.error?
  puts "Finished Processing."

  explicit_annotation = operation.results.annotation_results.first.explicit_annotation

  explicit_annotation.frames.each do |frame|
    frame_time = frame.time_offset.seconds + frame.time_offset.nanos / 1e9

    puts "Time: #{frame_time}"
    puts "pornography: #{frame.pornography_likelihood}"
  end
end

puts "Processing video for label annotations:"
operation.wait_until_done!

Was this page helpful? Let us know how we did:

Send feedback about...

Cloud Video Intelligence API Documentation