Détecter les changements de plan

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 Cloud Storage.

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

API REST et ligne de commande

Envoyer une requête d'annotation vidéo

Vous trouverez ci-dessous la procédure à suivre pour envoyer une requête POST à la méthode videos:annotate. Il utilise le jeton (token) d'accès associé à un compte de service configuré pour le projet à l'aide du SDK Cloud. Pour obtenir des instructions sur l'installation du SDK Cloud, la configuration d'un projet avec un compte de service et l'obtention d'un jeton d'accès, consultez la page Guide de démarrage rapide de l'API Video Intelligence.

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • INPUT_URI : bucket Cloud Storage contenant le fichier que vous souhaitez annoter, y compris son nom. Doit commencer par gs://.

Méthode HTTP et URL :

POST https://videointelligence.googleapis.com/v1/videos:annotate

Corps JSON de la requête :

{
    "inputUri": "INPUT_URI",
    "features": ["SHOT_CHANGE_DETECTION"]
}

Pour envoyer votre requête, développez l'une des options suivantes :

Vous devriez recevoir une réponse JSON de ce type :

Si la réponse aboutit, l'API Video Intelligence renvoie le name de votre opération. L'exemple ci-dessus montre un exemple de ce type de réponse, où project-name est le nom de votre projet et operation-id est l'ID de l'opération de longue durée créée pour la requête.

  • PROJECT_NUMBER : numéro de votre projet.
  • LOCATION_ID : région cloud dans laquelle l'annotation doit avoir lieu. Les régions cloud compatibles sont les suivantes : us-east1, us-west1, europe-west1 et asia-east1. Si aucune région n'est spécifiée, une région sera déterminée en fonction de l'emplacement du fichier vidéo.
  • OPERATION_ID : ID de l'opération de longue durée créée pour la requête, qui est fourni dans la réponse renvoyée au démarrage de l'opération, par exemple 12345....

Obtenir des résultats d'annotation

Pour récupérer le résultat de l'opération, envoyez une requête GET en utilisant le nom de l'opération renvoyé par l'appel à videos:annotate, comme indiqué dans l'exemple suivant.

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • OPERATION_NAME: nom de l'opération tel qu'il a été renvoyé par l'API Video Intelligence. Il est au format suivant : projects/PROJECT_NUMBER/locations/LOCATION_ID/operations/OPERATION_ID.

Méthode HTTP et URL :

GET https://videointelligence.googleapis.com/v1/OPERATION_NAME

Pour envoyer votre requête, développez l'une des options suivantes :

Vous devriez recevoir une réponse JSON de ce type :

Les annotations de détection de plans sont renvoyées sous la forme d'une liste shotAnnotations. Remarque : Le champ done n'est renvoyé que lorsque sa valeur est True. Il n'est pas inclus dans les réponses pour lesquelles l'opération n'est pas terminée.

Télécharger les résultats des annotations

Copiez l'annotation de la source vers le bucket de destination (consultez la page Copier des fichiers et des objets) :

gsutil cp gcs_uri gs://my-bucket

Remarque : Si l'URI GCS de sortie est fourni par l'utilisateur, l'annotation est stockée dans cet URI.

Go


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

	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 Video Intelligence pour Python, reportez-vous aux bibliothèques clientes de l'API Video Intelligence.
""" Detects camera shot changes. """
video_client = videointelligence.VideoIntelligenceServiceClient()
features = [videointelligence.Feature.SHOT_CHANGE_DETECTION]
operation = video_client.annotate_video(
    request={"features": features, "input_uri": path}
)
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.microseconds / 1e6
    )
    end_time = (
        shot.end_time_offset.seconds + shot.end_time_offset.microseconds / 1e6
    )
    print("\tShot {}: {} to {}".format(i, start_time, end_time))

Langages supplémentaires

C# : Veuillez suivre les instructions de configuration de C# sur la page des bibliothèques clientes, puis consultez la documentation de référence sur Video Intelligence pour .NET.

PHP : Veuillez suivre les instructions de configuration pour PHP sur la page des bibliothèques clientes, puis consultez la documentation de référence sur Video Intelligence pour PHP.

Ruby : Veuillez suivre les instructions de configuration pour Ruby sur la page des bibliothèques clientes, puis consultez la documentation de référence sur Video Intelligence pour Ruby.