Analyser les changements de plans des vidéos

La fonction d'analyse de changements de plans détecte les changements de plans dans une vidéo.

Cette section présente plusieurs méthodes permettant d'analyser les changements de plans d'une vidéo.

Voici l'exemple d'une analyse des changements de plans d'un fichier vidéo se trouvant dans Google Cloud Storage.

Vous souhaitez obtenir une analyse plus approfondie ? Consultez le tutoriel détaillé en Python.

Protocole

Reportez-vous au point de terminaison videos:annotate de l'API pour obtenir des informations complètes à ce sujet.

Pour lancer une détection de plans, utilisez une requête POST dont le corps approprié est :

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

Si une requête d'annotation Video Intelligence aboutit, elle renvoie une réponse qui contient uniquement un champ de nom :

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

Ce nom représente une opération de longue durée, qui peut être interrogée à l'aide de l'API v1.operations.

Pour récupérer la réponse de l'annotation vidéo, envoyez une requête GET au point de terminaison v1.operations, en transmettant la valeur de name dans l'URL. Si l'opération est terminée, elle renverra les résultats de l'annotation.

Les annotations de détection de plans sont renvoyées sous la forme d'une liste shotAnnotations.

[
  {
    "inputUri": "/demomaker/gbikes_dinosaur.mp4",
    "shotAnnotations": [
      {
        "startTimeOffset": "0s",
        "endTimeOffset": "5.167104s"
      },
      {
        "startTimeOffset": "5.236736s",
        "endTimeOffset": "10.072064s"
      },
      {
        "startTimeOffset": "10.106880s",
        "endTimeOffset": "28.139520s"
      },
      {
        "startTimeOffset": "28.174336s",
        "endTimeOffset": "42.768384s"
      }
    ]
  }
]

C#

public static object AnalyzeShotsGcs(string uri)
{
    var client = VideoIntelligenceServiceClient.Create();
    var request = new AnnotateVideoRequest()
    {
        InputUri = uri,
        Features = { Feature.ShotChangeDetection }
    };
    var op = client.AnnotateVideo(request).PollUntilCompleted();
    foreach (var result in op.Result.AnnotationResults)
    {
        foreach (var annotation in result.ShotAnnotations)
        {
            Console.Out.WriteLine("Start Time Offset: {0}\tEnd Time Offset: {1}",
                annotation.StartTimeOffset, annotation.EndTimeOffset);
        }
    }
    return 0;
}

Go

func shotChangeURI(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_SHOT_CHANGE_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].ShotAnnotations

	for _, shot := range result {
		start, _ := ptypes.Duration(shot.StartTimeOffset)
		end, _ := ptypes.Duration(shot.EndTimeOffset)

		fmt.Fprintf(w, "Shot: %s to %s\n", start, end)
	}

	return nil
}

Java

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

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 file to analyze, e.g. gs://my-bucket/my-video.mp4';

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

// Detects camera shot changes
const [operation] = await client.annotateVideo(request);
console.log('Waiting for operation to complete...');
const [operationResult] = await operation.promise();
// Gets shot changes
const shotChanges = operationResult.annotationResults[0].shotAnnotations;
console.log('Shot changes:');

if (shotChanges.length === 1) {
  console.log(`The entire video is one shot.`);
} else {
  shotChanges.forEach((shot, shotIdx) => {
    console.log(`Scene ${shotIdx} occurs from:`);
    if (shot.startTimeOffset === undefined) {
      shot.startTimeOffset = {};
    }
    if (shot.endTimeOffset === undefined) {
      shot.endTimeOffset = {};
    }
    if (shot.startTimeOffset.seconds === undefined) {
      shot.startTimeOffset.seconds = 0;
    }
    if (shot.startTimeOffset.nanos === undefined) {
      shot.startTimeOffset.nanos = 0;
    }
    if (shot.endTimeOffset.seconds === undefined) {
      shot.endTimeOffset.seconds = 0;
    }
    if (shot.endTimeOffset.nanos === undefined) {
      shot.endTimeOffset.nanos = 0;
    }
    console.log(
      `\tStart: ${shot.startTimeOffset.seconds}` +
        `.${(shot.startTimeOffset.nanos / 1e6).toFixed(0)}s`
    );
    console.log(
      `\tEnd: ${shot.endTimeOffset.seconds}.` +
        `${(shot.endTimeOffset.nanos / 1e6).toFixed(0)}s`
    );
  });
}

Python

Pour en savoir plus sur l'installation et l'utilisation de la bibliothèque cliente de l'API Cloud Video Intelligence pour Python, reportez-vous aux bibliothèques clientes de l'API Cloud Video Intelligence.
""" Detects camera shot changes. """
video_client = videointelligence.VideoIntelligenceServiceClient()
features = [videointelligence.enums.Feature.SHOT_CHANGE_DETECTION]
operation = video_client.annotate_video(path, features=features)
print('\nProcessing video for shot change annotations:')

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

# first result is retrieved because a single video was processed
for i, shot in enumerate(result.annotation_results[0].shot_annotations):
    start_time = (shot.start_time_offset.seconds +
                  shot.start_time_offset.nanos / 1e9)
    end_time = (shot.end_time_offset.seconds +
                shot.end_time_offset.nanos / 1e9)
    print('\tShot {}: {} to {}'.format(i, start_time, end_time))

PHP

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

/**
 * Finds shot changes in the video.
 *
 * @param string $uri The cloud storage object to analyze. Must be formatted
 *                    like gs://bucketname/objectname.
 * @param array $options optional Array of options to pass to
 *                       OperationResponse::pollUntilComplete. This is useful
 *                       for increasing the "pollingIntervalSeconds" option.
 */
function analyze_shots($uri, array $options = [])
{
    # Instantiate a client.
    $video = new VideoIntelligenceServiceClient();

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

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

    # Print the result.
    if ($operation->operationSucceeded()) {
        $results = $operation->getResult()->getAnnotationResults()[0];
        foreach ($results->getShotAnnotations() as $shot) {
            $startTimeOffset = $shot->getStartTimeOffset();
            $startSeconds = $startTimeOffset->getSeconds();
            $startNanoseconds = floatval($startTimeOffset->getNanos())/1000000000.00;
            $startTime = $startSeconds + $startNanoseconds;
            $endTimeOffset = $shot->getEndTimeOffset();
            $endSeconds = $endTimeOffset->getSeconds();
            $endNanoseconds = floatval($endTimeOffset->getNanos())/1000000000.00;
            $endTime = $endSeconds + $endNanoseconds;
            printf('Shot: %ss to %ss' . PHP_EOL, $startTime, $endTime);
        }
    } 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: [:SHOT_CHANGE_DETECTION] do |operation|
  raise operation.results.message? if operation.error?
  puts "Finished processing."

  # first result is retrieved because a single video was processed
  annotation_result = operation.results.annotation_results.first
  puts "Scenes:"

  annotation_result.shot_annotations.each do |shot_annotation|
    start_time = (shot_annotation.start_time_offset.seconds +
                   shot_annotation.start_time_offset.nanos / 1e9)
    end_time =   (shot_annotation.end_time_offset.seconds +
                   shot_annotation.end_time_offset.nanos / 1e9)

    puts "#{start_time} to #{end_time}"
  end
end

puts "Processing video for shot change annotations:"
operation.wait_until_done!

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Documentation de l'API Cloud Video Intelligence