Tutoriel de détection de changements de plans

Audience

Ce tutoriel est conçu pour vous permettre d'explorer et de développer rapidement des applications avec l'API Video Intelligence. Il est conçu pour les personnes qui maîtrisent la programmation de base. Cependant, vous ne devriez pas avoir de souci à suivre ce tutoriel, même si vous n'avez aucune connaissance approfondie en programmation. Après avoir parcouru ce tutoriel, vous devriez être capable de créer vos propres applications de base à l'aide de la documentation de référence.

Ce tutoriel vous présente une application de l'API Video Intelligence avec du code Python. Il ne s'agit pas ici d'expliquer les bibliothèques clientes Python, mais d'expliquer comment effectuer des appels à l'API Video Intelligence. Les applications Java et Node.js sont similaires pour l'essentiel.

Si vous recherchez uniquement un exemple de code ou un exemple dans un autre langage, consultez le guide pratique associé.

Prérequis

Ce tutoriel a plusieurs prérequis :

Annoter une vidéo avec la détection de changements de plans

Ce tutoriel vous présente une application de base de l'API Video à l'aide d'une requête SHOT_CHANGE_DETECTION. Une requête SHOT_CHANGE_DETECTION fournit les résultats d'annotation:

  • Liste de tous les plans qui se produisent dans la vidéo
  • Pour chaque plan, temps de début et de fin du plan

Nous affichons d'abord l'ensemble du code. (Notez que nous avons supprimé la plupart des commentaires de ce code afin d'insister sur sa brièveté. Nous ajouterons d'autres commentaires en parcourant le code.)

import argparse

from google.cloud import videointelligence

def analyze_shots(path):
    """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=120)
    print("\nFinished processing.")

    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))

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("path", help="GCS path for shot change detection.")
    args = parser.parse_args()

    analyze_shots(args.path)

Cette application simple effectue les tâches suivantes :

  • Elle importe les bibliothèques nécessaires pour exécuter l'application.
  • Elle utilise un fichier vidéo stocké dans l'URI Cloud Storage en tant qu'argument et le transmet à la fonction main().
  • Elle obtient les identifiants permettant d'exécuter le service de l'API Video Intelligence.
  • Elle crée une requête d'annotation vidéo à destination du service vidéo.
  • Elle envoie la requête et renvoie une opération de longue durée.
  • Elle boucle sur l'opération de longue durée jusqu'à ce que la vidéo soit traitée et renvoie les valeurs disponibles.
  • Elle analyse la réponse du service et envoie la réponse à l'utilisateur.

Nous reviendrons plus en détail sur ces étapes ci-dessous.

Importer des bibliothèques

import argparse

from google.cloud import videointelligence

Nous importons argparse pour permettre à l'application d'accepter des noms de fichiers comme arguments en entrée.

Pour utiliser l'API Video Intelligence, nous importons également la bibliothèque google.cloud.videointelligence. Celle-ci contient le répertoire de nos appels d'API et constantes d'énumération.

Exécuter votre application

parser = argparse.ArgumentParser(
    description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("path", help="GCS path for shot change detection.")
args = parser.parse_args()

analyze_shots(args.path)

Ici, nous analysons l'argument transmis pour l'URI Google Cloud Storage du nom du fichier vidéo, et nous le transmettons à la fonction main().

S'authentifier sur l'API

Avant de communiquer avec le service de l'API Video Intelligence, vous devez authentifier votre service avec les identifiants précédemment acquis. Dans une application, le moyen le plus simple d'obtenir des identifiants est d'utiliser les identifiants par défaut de l'application. Par défaut, la stratégie des identifiants par défaut de l'application (ADC, Application Default Credential) tente d'obtenir les identifiants à partir du fichier d'environnement GOOGLE_APPLICATION_CREDENTIALS. Ce fichier doit être défini pour pointer vers le fichier de clé JSON de votre compte de service. (Vous devez avoir configuré votre compte de service et votre environnement pour utiliser cette stratégie ADC dans le guide de démarrage rapide. Pour en savoir plus, consultez la page sur la configuration d'un compte de service.

Créer la requête

video_client = videointelligence.VideoIntelligenceServiceClient()
features = [videointelligence.Feature.SHOT_CHANGE_DETECTION]
operation = video_client.annotate_video(
    request={"features": features, "input_uri": path}
)

Maintenant que le service de l'API Video Intelligence est prêt, nous pouvons construire une requête vers ce service. Les requêtes adressées à l'API Video Intelligence sont fournies en tant qu'objets JSON. Consultez le document de référence de l'API Video Intelligence pour obtenir des informations complètes sur la structure spécifique d'une telle requête.

Cet extrait de code effectue les tâches suivantes :

  1. Il génère le fichier JSON pour une requête POST vers la méthode annotate_video().
  2. Il injecte dans la requête l'emplacement Google Cloud Storage du nom du fichier vidéo transmis.
  3. Il indique que la méthode annotate doit exécuter une requête SHOT_CHANGE_DETECTION.

Créer l'opération de longue durée

Lorsque nous exécutons une requête pour la première fois sur l'API Video Intelligence, nous n'obtenons pas de résultat immédiat. Au lieu de cela, nous obtenons un nom d'opération, stocké dans le champname de la réponse. Nous pourrons utiliser la valeur de ce champ ultérieurement pour vérifier les résultats.

La transmission du nom de cette opération (qui est une chaîne numérique) à la méthode operations du service Operations de l'API Video Intelligence renvoie l'état actuel de l'opération. Voici un exemple de réponse :

{
   "response":{
      "@type":"type.googleapis.com/google.cloud.videointelligence.v1.AnnotateVideoResponse"
   },
   "name":"us-west1.17159971042783089144",
   "metadata":{
      "annotationProgress":[
         {
            "inputUri":"/video/gbikes_dinosaur.mp4",
            "updateTime":"2017-01-27T19:45:54.297807Z",
            "startTime":"2017-01-27T19:45:54.275023Z"
         }
      ],
      "@type":"type.googleapis.com/google.cloud.videointelligence.v1.AnnotateVideoProgress"
   }
}

Notez qu'à cet instant, le champ response ne contient qu'un champ @type, indiquant le type de cette réponse. Lorsque les résultats sont réellement disponibles, le champ de la réponse contient des résultats de ce type.

Vérifier l'opération

result = operation.result(timeout=120)
print("\nFinished processing.")

La requête d'opération existante pour notre opération existante nous permet de construire une boucle whilepour vérifier de manière périodique l'état de cette opération. Lorsque notre opération nous indique que l'état est done, nous sortons de la boucle. Nous pouvons alors analyser la réponse.

Analyser la réponse

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))

Une fois l'opération terminée, la réponse contient une AnnotateVideoResponse, qui consiste en une liste de annotationResults, un pour chaque vidéo envoyée dans la requête. Comme nous n'avons envoyé qu'une seule vidéo dans la requête, nous prenons le premier shotAnnotations du résultat. Nous parcourons toutes les "séquences" de la vidéo.

Exécuter l'application

Pour exécuter notre application, il suffit de lui transmettre l'URI Cloud Storage d'une vidéo :

$ python shotchange.py gs://cloud-samples-data/video/gbikes_dinosaur.mp4
operationId=us-west1.12468772851081463748
Operation us-west1.12468772851081463748 started: 2017-01-30T01:53:45.981043Z
Processing video for shot change annotations:
Finished processing.
  Shot 0: 0.0 to 5.166666
  Shot 1: 5.233333 to 10.066666
  Shot 2: 10.1 to 28.133333
  Shot 3: 28.166666 to 42.766666

Félicitations ! Vous avez réalisé une annotation à l'aide de l'API Video Intelligence.