

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

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

本教學說明如何使用 Java Lambda 函數，取得標籤偵測影片分析操作的結果。

**注意**  
本教學課程使用適用於 Java 的 AWS SDK 1.x。如需使用 Rekognition 和適用於 Java 的 AWS SDK 第 2 版的教學課程，請參閱 [AWS 文件開發套件範例 GitHub 儲存庫](https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/usecases/video_analyzer_application)。

您可以將 Lambda 函數與 Amazon Rekognition Video 操作搭配使用。例如，以下圖表顯示網站使用 Lambda 函數，在影片上傳到 Amazon S3 儲存貯體時自動開始分析影片。當 Lambda 函數觸發時，會呼叫 [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html) 開始偵測上傳的影片中的標籤。如需使用 Lambda 處理來自 Amazon S3 儲存貯體事件通知的相關資訊，請參閱[搭配 Amazon S3 事件使用 AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html)。

當分析完成狀態傳送到註冊的 Amazon SNS 主題時，第二個 Lambda 函數就會觸發。第二個 Lambda 函數呼叫 [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html)，以取得分析結果。然後，結果會存放在資料庫以準備顯示於網頁。本教學的重點在於此第二個 lambda 函數。

![圖表顯示 Amazon Rekognition Video 的影片處理 worfkflow，從上傳影片到將結果儲存在 Amazon DynamoDB 中以在網站上顯示。](http://docs.aws.amazon.com/zh_tw/rekognition/latest/dg/images/VideoRekognitionLambda.png)


在本教學中，當 Amazon Rekognition Video 將影片分析完成狀態傳送到註冊的 Amazon SNS 主題時，Lambda 函數就會觸發。然後，它會呼叫 [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 管理主控台 並將其訂閱 Amazon 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 SNS 主題的 Amazon Rekognition Video 權限。請記下 Amazon Resource Name (ARN)。如需詳細資訊，請參閱 [提供對多個 Amazon SNS 主題的存取權限](api-video-roles.md#api-video-roles-all-topics)。

1. 使用 [Amazon SNS 主控台建立](https://docs.aws.amazon.com/sns/latest/dg/CreateTopic.html) [Amazon SNS ](https://console.aws.amazon.com/sns/v2/home)主題。您只需指定主題名稱。將 *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 管理主控台，並開啟位於 [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) 的 AWS Lambda 主控台。

1. 選擇**建立函數**。

1. 選擇**從頭開始撰寫**。

1. 在 **Function Name (函數名稱)** 中，為您的函數輸入名稱。

1. 在 **Runtime\* (執行時間\*)** 中，選擇 **Java 8**。

1. 選擇 **Choose or create an execution role (選擇或建立執行角色)**。

1. 在 **Execution role (執行角色)** 中，選擇 **Create a new role with basic Lambda permissions (建立具備基本 Lambda 許可的新角色)**。

1. 請注意，新角色名稱會顯示在 **Basic information (基本資訊)** 區段的底部。

1. 選擇**建立函數**。

## 設定 Lambda 函數
<a name="lambda-configure-function"></a>

建立 Lambda 函數後，您可以設定它來讓您在 [建立 SNS 主題：](#lambda-create-sns-topic) 中建立的 Amazon SNS 主題予以觸發。您也將調整 Lambda 函數的記憶體需求和逾時期間。

**設定和部署 Lambda 函數**

1. 在 **Function Code** (函數程式碼) 的 `com.amazonaws.lambda.demo.JobCompletionHandler`Handler** (處理常式) 中輸入 **。

1. 在 **Basic settings (基本設定)** 中，選擇 **Edit (編輯)**。**Edit basic settings (編輯基本設定)** 對話方塊隨即顯示。

   1. 在**記憶體**中選擇 **1024**。

   1. 在 **Timeout (逾時)** 中選擇 **10** 秒。

   1. 選擇**儲存**。

1. 在 **Designer (設計工具)** 中，選擇 **\+Add trigger (\+新增觸發條件)**。[Add trigger (新增觸發條件)] 對話方塊隨即顯示。

1. 在 **Trigger configuration (觸發條件組態)** 中選擇 **SNS**。

   在 **SNS 主題**中，選擇您在 [建立 SNS 主題：](#lambda-create-sns-topic) 中建立的 Amazon SNS 主題。

1. 選擇 **Enable trigger** (啟用觸發條件)。

1. 若要新增觸發條件，請選擇 **Add** (新增)。

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)，還需要傳遞 IAM 服務角色的角色許可，以供 Amazon Rekognition Video 用於存取 Amazon SNS 主題。

**設定角色**

1. 登入 AWS 管理主控台 ，並在 https：//[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 開啟 IAM 主控台。

1. 在導覽窗格中，選擇**角色**。

1. 在清單中，選擇您在 [建立 Lambda 函式](#lambda-create-function) 中建立之執行角色的名稱。

1. 選擇**許可**索引標籤。

1. 選擇**連接政策**。

1. 從政策清單中選擇 *AmazonRekognitionFullAccess*。

1. 選擇 **Attach policy** (連接政策)。

1. 再次選擇執行角色。

1. 選擇**新增內嵌政策**。

1. 選擇 **JSON** 標籤。

1. 用以下政策取代現有政策。用您在 [建立 SNS 主題：](#lambda-create-sns-topic) 中建立的 IAM 服務角色取代 `servicerole`。

1. 選擇**檢閱政策**。

1. 在 **Name\*** (名稱\*) 中輸入政策的名稱。

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)。
   + 在 **Project name:** (專案名稱：) 中，輸入您選擇的專案名稱。
   + 在 **Class Name: (類別名稱：)** 中，輸入 *JobCompletionHandler*。
   + 在 **Input type:** (輸入類型：) 中選擇 **SNS Event** (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;` 這行上有底線的部分。
   + 選擇 **Fix project set up...** (修復專案設定…)。
   + 選擇 Amazon Rekognition存檔的最新版本。
   + 選擇 **OK** 以新增存檔到專案。

1. 儲存檔案。

1. 在 Eclipse 程式碼視窗中按一下滑鼠右鍵，選擇 **AWS Lambda**，然後選擇 **Upload function to AWS Lambda** (將函數上傳至 AWS Lambda)。

1. 在 **Select Target Lambda Function** (選擇目標 Lambda 函數) 頁面中，選擇要使用的 AWS 區域。

1. 選擇 **Choose an existing lambda function** (選擇現有的 Lambda 函數)，然後選取您在 [建立 Lambda 函式](#lambda-create-function) 中建立的 Lambda 函數。

1. 選擇**下一步**。**Function Configuration (功能組態)** 對話方塊隨即顯示。

1. 在 **IAM role (IAM 角色)** 中選擇您在 [建立 Lambda 函式](#lambda-create-function) 建立的 IAM 角色。

1. 選擇**完成**，Lambda 函數就會上傳至 AWS。

## 測試 Lambda 函數
<a name="lambda-test-function"></a>

使用以下 AWS CLI 命令，透過啟動影片的標籤偵測分析來測試 Lambda 函數。在分析完成後，就會觸發 Lambda 函數。檢查 CloudWatch Log 日誌，確認分析已成功。

**測試 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"，以及偵測到的標籤類別清單，例如 Bottle、Clothing、Crowd 和 Food：  
![顯示影片辨識操作詳細資訊的日誌輸出。](http://docs.aws.amazon.com/zh_tw/rekognition/latest/dg/images/log.png)

   **ID** 的值應符合您在步驟 3 記下的 `JobId` 值。