镜头变化检测教程

受众

本教程旨在让您快速开始使用 Video Intelligence API 探索和开发应用。本指南面向熟悉基本编程的用户,但即使您掌握的编程知识不多,也应该能够理解。阅读完本教程后,您应该能够根据参考文档创建您自己的基本应用。

本教程介绍使用 Python 代码的 Video Intelligence API 应用。但我们的目的不是解说 Python 客户端库,而是说明如何调用 Video Intelligence API。Java 和 Node.js 中的应用基本相似。

如果您想要查看只含代码的示例或其他语言的示例,请查看配套的方法指南

前提条件

本教程有几个前提条件:

使用镜头变化检测功能为视频添加注释

本教程介绍了一个使用 SHOT_CHANGE_DETECTION 请求的基本 Video API 应用。SHOT_CHANGE_DETECTION 请求提供注释结果:

  • 视频中出现的所有镜头的列表
  • 对于每个镜头,提供该镜头的开始时间和结束时间

我们首先显示整个代码。(请注意,我们已从该代码中移除了大多数注释,以便向您展示它的简短程度。在解说代码的过程中,我们将提供更多注释。)

import argparse

from google.cloud import videointelligence

def analyze_shots(path):
    """ Detects camera shot changes. """
    video_client = videointelligence.VideoIntelligenceServiceClient()
    features = [videointelligence.enums.Feature.SHOT_CHANGE_DETECTION]
    operation = video_client.annotate_video(input_uri=path, features=features)
    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.nanos / 1e9)
        end_time = (shot.end_time_offset.seconds +
                    shot.end_time_offset.nanos / 1e9)
        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)

此简单应用执行以下任务:

  • 导入运行应用所需的库
  • 将 Cloud Storage URI 中存储的视频文件作为参数并传递给 main() 函数。
  • 获取凭据以运行 Video Intelligence API 服务
  • 创建要发送到视频服务的视频注释请求
  • 发送请求并返回一个长时间运行的操作
  • 轮询长时间运行的操作,直到视频处理完成并且返回值可用。
  • 解析服务的响应并向用户显示响应。

我们将在下面更详细地介绍这些步骤。

导入库

import argparse

from google.cloud import videointelligence

我们导入 argparse 以允许应用接受输入文件名作为参数。

为了使用 Cloud Video Intelligence API,我们还导入了 google.cloud.videointelligence 库,其中包含我们的 API 调用目录和枚举常量。

运行应用

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)

这里,我们解析传入的参数,获得视频文件名的 Google Cloud Storage URI,并将其传递给 main() 函数。

向 API 进行身份验证

与 Video Intelligence API 服务通信之前,您需要使用先前获得的凭据来对您的服务进行身份验证。在应用中,获取凭据的最简单方法是使用应用默认凭据 (ADC)。 默认情况下,ADC 将尝试从 GOOGLE_APPLICATION_CREDENTIALS 环境文件获取凭据,该文件应设置为指向您的服务帐号的 JSON 密钥文件。(您应该已在快速入门中设置了您的服务帐号和环境以使用 ADC。如需了解详情,请参阅设置服务帐号。)

构建请求

video_client = videointelligence.VideoIntelligenceServiceClient()
features = [videointelligence.enums.Feature.SHOT_CHANGE_DETECTION]
operation = video_client.annotate_video(input_uri=path, features=features)

现在,Video Intelligence API 服务已准备就绪,我们可以构建要发送至该服务的请求。向 Video Intelligence API 发出的请求是作为 JSON 对象提供的。如需全面了解此类请求的具体结构,请参阅 Video Intelligence API 参考

此代码段执行以下任务:

  1. 为发送到 annotate_video() 方法的 POST 请求构造 JSON。
  2. 将传递的视频文件名所在的 Google Cloud Storage 位置注入请求。
  3. 指出 annotate 方法应执行 SHOT_CHANGE_DETECTION

构建长时间运行的操作

当我们首次针对 Video Intelligence API 执行请求时,并不会立即获得结果;而是会获得一个操作名称,该名称存储在响应的 name 字段中,之后我们可以使用该名称查看结果。

如果将操作的名称(数字字符串)传递给 Video Intelligence API 的操作服务 operations 方法,则可返回操作的当前状态。示例响应如下所示:

{
   "response":{
      "@type":"type.googleapis.com/google.cloud.videointelligence.v1.AnnotateVideoResponse"
   },
   "name":"us-west1.17159971042783089144",
   "metadata":{
      "annotationProgress":[
         {
            "inputUri":"/demomaker/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"
   }
}

请注意,目前 response 字段仅包含一个 @type 字段,用于表示该响应的类型。当结果实际可用后,响应字段将包含该类型的结果。

检查操作

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

通过使用现有操作的请求,我们可以构建一个 while 循环,以定期检查该操作的状态。当操作表明其状态变为 done 后,我们可以终止循环并解析响应。

解析响应

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

操作完成后,响应将包含 AnnotateVideoResponse(其中包括一个 annotationResults 列表,在请求中发送的每个视频各有一个结果)。由于我们在请求中仅发送了一个视频,因此我们将选取结果的第一个 shotAnnotations。我们然后依次处理视频的所有“片段”。

运行应用

要运行应用,只需向其传递视频的 Cloud Storage URI 即可:

$ python shotchange.py gs://demomaker/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

恭喜!您已使用 Video Intelligence API 执行了注释任务!