

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 创建 Amazon Rekognition Lambda 函数
<a name="stored-video-lambda"></a>

本教程介绍如何使用 Java Lambda 函数获取标签检测的视频分析操作的结果。

**注意**  
本教程使用适用于 Java 的 AWS SDK 1.x。[有关使用 Rekognition 和适用于 AWS Java 的 SDK 版本 2 的教程，请参阅AWS 文档 SDK 示例存储库。 GitHub ](https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/usecases/video_analyzer_application)

您可以将 Lambda 函数与 Amazon Rekognition Video 操作一起使用。例如，下图显示了一个网站，该网站在视频上传到 Amazon S3 存储桶时使用 Lambda 函数自动开始分析视频。触发 Lambda 函数时，它会调用[StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html)以开始检测上传的视频中的标签。有关使用 Lambda 处理来自 Amazon S3 存储桶的事件通知的信息，请参阅[将 AWS Lambda 与 Amazon S3 事件结合使用](https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html)。

另一个 Lambda 函数在分析完成状态发送到已注册的 Amazon SNS 主题时触发。第二个 Lambda 函数调用[GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html)以获取分析结果。结果随后被存储在数据库中以做好在网页上显示的准备。此第二个 lambda 函数是本教程的重点。

![\[该图显示 Amazon Rekognition Video 的视频处理工作流，即从上传视频到将结果存储在 Amazon DynamoDB 中以显示在网站上。\]](http://docs.aws.amazon.com/zh_cn/rekognition/latest/dg/images/VideoRekognitionLambda.png)


在本教程中，Lambda 函数在 Amazon Rekognition Video 将视频分析的完成状态发送到已注册的 Amazon SNS 主题时触发。它随后通过调用 [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html) 来收集视频分析结果。出于演示目的，本教程将标签检测结果写入 CloudWatch 日志。在您的应用程序的 Lambda 函数中，您应该存储分析结果以供稍后使用。例如，您可以使用 Amazon DynamoDB 来保存分析结果。有关更多信息，请参阅[使用 DynamoDB](url-ddb-dev;WorkingWithDynamo.html)。

以下步骤将说明如何：
+ 创建 Amazon SNS 主题并设置权限。
+ 使用创建 Lambda 函数 AWS 管理控制台 并将其订阅亚马逊 SNS 主题。
+ 使用 AWS 管理控制台配置 Lambda 函数。
+ 向 AWS Toolkit for Eclipse 项目添加示例代码并将其上传到 Lambda 函数。
+ 使用 AWS CLI测试 Lambda 函数。

**注意**  
在整个教程中使用相同的 AWS 区域。

## 先决条件
<a name="lambda-stored-video-prerequisites"></a>

本教程假定您熟悉 AWS Toolkit for Eclipse。有关更多信息，请参阅 [AWS Toolkit for Eclipse](https://docs.aws.amazon.com/toolkit-for-eclipse/v1/user-guide/welcome.html)。

## 创建 SNS 主题
<a name="lambda-create-sns-topic"></a>

Amazon Rekognition Video 视频分析操作的完成状态将发送到 Amazon SNS 主题。此过程将创建 Amazon SNS 主题和 IAM 服务角色（向 Amazon Rekognition Video 授予对您的 Amazon SNS 主题的访问权限）。有关更多信息，请参阅 [调用 Amazon Rekognition Video 操作](api-video.md)。

**创建 Amazon SNS 主题**

1. 如果您尚未创建 IAM 服务角色，请创建一个该角色来为 Amazon Rekognition Video 提供对 Amazon SNS 主题的访问权限。记下 Amazon 资源名称（ARN）。有关更多信息，请参阅 [提供对多个 Amazon SNS 主题的访问权限](api-video-roles.md#api-video-roles-all-topics)。

1. 使用 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/v2/home)[创建 Amazon SNS 主题](https://docs.aws.amazon.com/sns/latest/dg/CreateTopic.html)。您只需要指定主题名称即可。在主题名称前面加上。*AmazonRekognition*记录主题 ARN。

## 创建 Lambda 函数
<a name="lambda-create-function"></a>

您可使用 AWS 管理控制台创建 Lambda 函数。然后使用 AWS Toolkit for Eclipse 项目将 Lambda 函数程序包上传到 AWS Lambda。也可以使用 AWS Toolkit for Eclipse创建 Lambda 函数。有关更多信息，请参阅[教程：如何创建、上传和调用 AWS Lambda 函数](https://docs.aws.amazon.com/toolkit-for-eclipse/v1/user-guide/lambda-tutorial.html)。

**创建 Lambda 函数**

1. 登录 AWS 管理控制台，然后在上打开 AWS Lambda 控制台。[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)

1. 选择**创建函数**。

1. 选择**从头开始创作**。

1. 对于**函数名称**，键入函数的名称。

1. 在**运行时系统**中，选择 **Java 8**。

1. 选择**选择或创建执行角色**。

1. 在**执行角色**中，选择**创建具有基本 Lambda 权限的新角色**。

1. 记下**基本信息**部分底部显示的新角色的名称。

1. 选择**创建函数**。

## 配置 Lambda 函数
<a name="lambda-configure-function"></a>

在创建 Lambda 函数后，您可以将其配置为由您在 [创建 SNS 主题](#lambda-create-sns-topic) 中创建的 Amazon SNS 主题触发。您还可以调整 Lambda 函数的内存要求和超时期限。

**配置 Lambda 函数**

1. 在**函数代码**中，为**处理程序**键入 `com.amazonaws.lambda.demo.JobCompletionHandler`。

1. 在**基本设置**中，选择**编辑**。此时将显示**编辑基本设置**对话框。

   1. 为**内存**选择 **1024**。

   1. 对于**超时**，选择 **10** 秒。

   1. 选择**保存**。

1. 在**设计器**中，选择 **\$1 添加触发器**。此时将显示“添加触发器”对话框。

1. 在**触发器配置**中，选择 **SNS**。

   在 **SNS 主题**中，选择您在 [创建 SNS 主题](#lambda-create-sns-topic) 中创建的 Amazon SNS 主题。

1. 选择**启用触发器**。

1. 要添加触发器，请选择**添加**。

1. 选择**保存**以保存 Lambda 函数。

## 配置 IAM Lambda 角色
<a name="configure-lambda-role"></a>

要调用 Amazon Rekognition Video 操作，您需要将 *AmazonRekognitionFullAccess*AWS 托管策略添加到 IAM Lambda 角色中。启动操作（例如 [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html)）还需要 Amazon Rekognition Video 用于访问亚马逊 SNS 主题的 IAM 服务角色的传递角色权限。

**配置角色**

1. 登录 AWS 管理控制台 并打开 IAM 控制台，网址为[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 在导航窗格中，选择**角色**。

1. 在列表中，选择您在 [创建 Lambda 函数](#lambda-create-function)中创建的执行角色的名称。

1. 选择**权限**选项卡。

1. 选择**附加策略**。

1. *AmazonRekognitionFullAccess*从策略列表中选择。

1. 选择**附加策略**。

1. 再次选择此执行角色。

1. 选择**添加内联策略**。

1. 选择 **JSON** 选项卡。

1. 将现有策略替换为以下策略。将 `servicerole` 替换为您在 [创建 SNS 主题](#lambda-create-sns-topic) 中创建的 IAM 服务角色。

1. 选择**查看策略**。

1. 在**名称\$1** 中键入策略的名称。

1. 选择**创建策略**。

## 创建 AWS Toolkit for Eclipse Lambda 项目
<a name="lambda-create-code"></a>

触发 Lambda 函数时，以下代码会从 Amazon SNS 主题中获取完成状态，并[GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html)调用以获取分析结果。将检测到的标签计数和检测到的标签列表写入 CloudWatch 日志。您的 Lambda 函数应该存储视频分析结果以供稍后使用。

**创建 AWS Toolkit for Eclipse Lambda 项目**

1. [创建一个 AWS Toolkit for EclipseAWS Lambda 项目](https://docs.aws.amazon.com/toolkit-for-eclipse/v1/user-guide/lambda-tutorial.html#lambda-tutorial-create-handler-class)。
   + 对于**项目名称:**，键入您选择的项目名称。
   + 在 “**类名:**” 中，输入*JobCompletionHandler*。
   + 对于**输入类型:**，选择 **SNS 事件**。
   + 使其他字段保持不变。

1. 在 **Eclipse 项目**资源管理器中，打开生成的 Lambda 处理程序方法 (JobCompletionHandler.java)，然后将内容替换为以下内容：

   ```
   //Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   //PDX-License-Identifier: MIT-0 (For details, see https://github.com/awsdocs/amazon-rekognition-developer-guide/blob/master/LICENSE-SAMPLECODE.)
   
   package com.amazonaws.lambda.demo;
   
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.LambdaLogger;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   import com.amazonaws.services.lambda.runtime.events.SNSEvent;
   import java.util.List;
   import com.amazonaws.regions.Regions;
   import com.amazonaws.services.rekognition.AmazonRekognition;
   import com.amazonaws.services.rekognition.AmazonRekognitionClientBuilder;
   import com.amazonaws.services.rekognition.model.GetLabelDetectionRequest;
   import com.amazonaws.services.rekognition.model.GetLabelDetectionResult;
   import com.amazonaws.services.rekognition.model.LabelDetection;
   import com.amazonaws.services.rekognition.model.LabelDetectionSortBy;
   import com.amazonaws.services.rekognition.model.VideoMetadata;
   import com.fasterxml.jackson.databind.JsonNode;
   import com.fasterxml.jackson.databind.ObjectMapper;
   
   
   
   public class JobCompletionHandler implements RequestHandler<SNSEvent, String> {
   
      @Override
      public String handleRequest(SNSEvent event, Context context) {
   
         String message = event.getRecords().get(0).getSNS().getMessage();
         LambdaLogger logger = context.getLogger(); 
   
         // Parse SNS event for analysis results. Log results
         try {
            ObjectMapper operationResultMapper = new ObjectMapper();
            JsonNode jsonResultTree = operationResultMapper.readTree(message);
            logger.log("Rekognition Video Operation:=========================");
            logger.log("Job id: " + jsonResultTree.get("JobId"));
            logger.log("Status : " + jsonResultTree.get("Status"));
            logger.log("Job tag : " + jsonResultTree.get("JobTag"));
            logger.log("Operation : " + jsonResultTree.get("API"));
   
            if (jsonResultTree.get("API").asText().equals("StartLabelDetection")) {
   
               if (jsonResultTree.get("Status").asText().equals("SUCCEEDED")){
                  GetResultsLabels(jsonResultTree.get("JobId").asText(), context);
               }
               else{
                  String errorMessage = "Video analysis failed for job " 
                        + jsonResultTree.get("JobId") 
                        + "State " + jsonResultTree.get("Status");
                  throw new Exception(errorMessage); 
               }
   
            } else
               logger.log("Operation not StartLabelDetection");
   
         } catch (Exception e) {
            logger.log("Error: " + e.getMessage());
            throw new RuntimeException (e);
   
   
         }
   
         return message;
      }
   
      void GetResultsLabels(String startJobId, Context context) throws Exception {
   
         LambdaLogger logger = context.getLogger();
   
         AmazonRekognition rek = AmazonRekognitionClientBuilder.standard().withRegion(Regions.US_EAST_1).build();
   
         int maxResults = 1000;
         String paginationToken = null;
         GetLabelDetectionResult labelDetectionResult = null;
         String labels = "";
         Integer labelsCount = 0;
         String label = "";
         String currentLabel = "";
        
         //Get label detection results and log them. 
         do {
   
            GetLabelDetectionRequest labelDetectionRequest = new GetLabelDetectionRequest().withJobId(startJobId)
                  .withSortBy(LabelDetectionSortBy.NAME).withMaxResults(maxResults).withNextToken(paginationToken);
   
            labelDetectionResult = rek.getLabelDetection(labelDetectionRequest);
            
            paginationToken = labelDetectionResult.getNextToken();
            VideoMetadata videoMetaData = labelDetectionResult.getVideoMetadata();
   
            // Add labels to log
            List<LabelDetection> detectedLabels = labelDetectionResult.getLabels();
            
            for (LabelDetection detectedLabel : detectedLabels) {
               label = detectedLabel.getLabel().getName();
               if (label.equals(currentLabel)) {
                  continue;
               }
               labels = labels + label + " / ";
               currentLabel = label;
               labelsCount++;
   
            }
         } while (labelDetectionResult != null && labelDetectionResult.getNextToken() != null);
   
         logger.log("Total number of labels : " + labelsCount);
         logger.log("labels : " + labels);
   
      }
   
   
   }
   ```

1. Rekognition 命名空间未被解析。纠正方法：
   + 将鼠标指针停留在行 `import com.amazonaws.services.rekognition.AmazonRekognition;` 的带下划线的部分。
   + 选择**修复项目设置...**。
   + 选择最新版本的 Amazon Rekognition 存档。
   + 选择**确定**以将存档保存到项目。

1. 保存该文件。

1. 在 Eclipse 代码窗口中右键单击，选择 **AWS Lambda**，然后选择**将函数上传到 AWS Lambda**。

1. 在**选择目标 Lambda 函数**页面上，选择要使用的 AWS 区域。

1. 选择**选择现有 Lambda 函数**，然后选择您在 [创建 Lambda 函数](#lambda-create-function) 中创建的 Lambda 函数。

1. 选择**下一步**。此时将显示**函数配置**对话框。

1. 在 **IAM 角色**中，选择您在 [创建 Lambda 函数](#lambda-create-function) 中创建的 IAM 角色。

1. 选择**完成**，Lambda 函数将上传到 AWS。

## 测试 Lambda 函数
<a name="lambda-test-function"></a>

使用以下 AWS CLI 命令通过启动视频的标签检测分析来测试 Lambda 函数。分析完成后，将触发 Lambda 函数。通过检查 CloudWatch 日志来确认分析成功。

**测试 Lambda 函数**

1. 将 MOV 或 MPEG-4 格式的视频文件上传到您的 S3 存储桶。对于测试，请上传时长不超过 30 秒的视频。

   有关说明，请参阅**《Amazon Simple Storage Service 用户指南》中的[将对象上传到 Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UploadingObjectsintoAmazonS3.html)。

1. 运行以下 AWS CLI 命令开始检测视频中的标签。

   ```
   aws rekognition start-label-detection --video "S3Object={Bucket="bucketname",Name="videofile"}" \
   --notification-channel "SNSTopicArn=TopicARN,RoleArn=RoleARN" \
   --region Region
   ```

   更新以下值：
   + 将 `bucketname` 和 `videofile` 更改为您要在其中检测标签的视频的 Amazon S3 存储桶名称和文件名。
   + 将 `TopicARN` 更改为您在 [创建 SNS 主题](#lambda-create-sns-topic) 中创建的 Amazon SNS 主题的 ARN。
   + 将 `RoleARN` 更改为您在 [创建 SNS 主题](#lambda-create-sns-topic) 中创建的 IAM 角色的 ARN。
   + 切换`Region`到您正在使用的 AWS 区域。 ``

1. 记下响应中 `JobId` 的值。该响应看上去与以下 JSON 示例类似。

   ```
   {
       "JobId": "547089ce5b9a8a0e7831afa655f42e5d7b5c838553f1a584bf350ennnnnnnnnn"
   }
   ```

1. 打开 [https://console.aws.amazon.com/cloudwatch/ 控制台](https://console.aws.amazon.com/cloudwatch/)。

1. 当分析完成时，Lambda 函数的日志条目将显示在**日志组**中。

1. 选择 Lambda 函数以查看日志流。

1. 选择最新日志流以查看由 Lambda 函数制作的日志条目。如果操作成功，则显示类似于以下输出，其中显示了视频识别操作的详细信息，包括作业 ID、操作类型 StartLabelDetection “” 以及检测到的标签类别列表，例如瓶子、服装、人群和食物：  
![\[日志输出显示视频识别操作详细信息。\]](http://docs.aws.amazon.com/zh_cn/rekognition/latest/dg/images/log.png)

   **任务 ID** 的值应与您在步骤 3 中记下的 `JobId` 的值匹配。