

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

# 使用儲存的影片分析操作
<a name="video"></a>

Amazon Rekognition Video 為可用於分析影片的 API。使用 Amazon Rekognition Video，您可以偵測儲存於 Amazon Simple Storage Service (Amazon S3) 儲存貯體的影片中之標籤、人臉、人物、名人以及成人內容 (包括暗示與露骨)。您可以在媒體/娛樂與公共安全等類別使用 Amazon Rekognition Video。在過去，掃描影片中的物件或人員可能必須耗費數小時的人工檢視，且容易發生錯誤。若專案貫穿影片各處，Amazon Rekognition Video 可對專案執行自動化偵測。

本節涵蓋 Amazon Rekognition Video 可執行的分析類型、API 概觀以及使用 Amazon Rekognition Video 的範例。

**Topics**
+ [分析類型](#video-recognition-types)
+ [Amazon Rekognition Video API 概觀](#video-api-overview)
+ [呼叫 Amazon Rekognition Video 操作](api-video.md)
+ [設定 Amazon Rekognition Video](api-video-roles.md)
+ [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md)
+ [使用 分析影片 AWS Command Line Interface](video-cli-commands.md)
+ [參考：影片分析結果通知](video-notification-payload.md)
+ [對 Amazon Rekognition Video 進行疑難排解](video-troubleshooting.md)

## 分析類型
<a name="video-recognition-types"></a>

您可以使用 Amazon Rekognition Video 來分析影片中的下列資訊：
+ [影片區段](segments.md)
+ [標籤](labels.md)
+ [暗示與露骨的成人內容](moderation.md)
+ [Text (文字)](text-detection.md)
+ [名人](celebrities.md)
+ [臉部](faces.md)
+ [人物](persons.md)

如需詳細資訊，請參閱 [Amazon Rekognition 的運作方式](how-it-works.md)。

## Amazon Rekognition Video API 概觀
<a name="video-api-overview"></a>

Amazon Rekognition Video 會處理存放在 Amazon S3 儲存貯體中的影片。設計模式為一組非同步的操作。呼叫如 [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html) 的 `Start` 操作來開始影片分析。請求的完成狀態會發佈至 Amazon Simple Notification Service (Amazon SNS) 主題。若要從 Amazon SNS 主題取得完成狀態，您可以使用 Amazon Simple Queue Service (Amazon SQS) 佇列或 AWS Lambda 函數。在獲得完成狀態後，可呼叫如 [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html) 的 `Get` 操作來取得請求結果。

下圖顯示在儲存於 Amazon S3 儲存貯體的影片中偵測標籤的程序。在圖表內，佇列將自 Amazon SNS 主題取得完成狀態。或者，您可以使用 AWS Lambda 函數。

![\[流程圖說明使用 Amazon Rekognition Video、Amazon SNS 和 Amazon SQS 進行影片分析的步驟，以及 StartLabelDetection、GetLabelDetection 任務等元件，並將完成狀態發佈至個別佇列。\]](http://docs.aws.amazon.com/zh_tw/rekognition/latest/dg/images/VideoRekognition.png)


其他 Amazon Rekognition Video 操作的過程是相同的。下表列出每個非儲存體 Amazon Rekognition 操作的 `Start` 與 `Get` 操作。


| 偵測 | 開始操作 | 取得操作 | 
| --- | --- | --- | 
|  影片區段  |  [StartSegmentDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartSegmentDetection.html)  |  [GetSegmentDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetSegmentDetection.html)  | 
|  標籤  |  [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html)  |  [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html)  | 
|  露骨或暗示性的成人內容  |  [StartContentModeration](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartContentModeration.html)  |  [GetContentModeration](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetContentModeration.html)  | 
|  文字  |  [StartTextDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartTextDetection.html)  |  [GetTextDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetTextDetection.html)  | 
|  名人  |  [StartCelebrityRecognition](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartCelebrityRecognition.html)  |  [GetCelebrityRecognition](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetCelebrityRecognition.html)  | 
|  臉部  |  [StartFaceDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartFaceDetection.html)  |  [GetFaceDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetFaceDetection.html)  | 
|  人物  |  [StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html)  |  [GetPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetPersonTracking.html)  | 

對於 `Get` 以外的 `GetCelebrityRecognition` 操作，Amazon Rekognition Video 將傳回追蹤資訊，說明將在影片輸入檔的哪個部分偵測到實體。

如需使用 Amazon Rekognition Video 影片的詳細資訊，請參閱 [呼叫 Amazon Rekognition Video 操作](api-video.md)。如需使用 Amazon SQS 執行影片分析的範例，請參閱 [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md)。如需 AWS CLI 範例，請參閱 [使用 分析影片 AWS Command Line Interface](video-cli-commands.md)。

### 影片格式和儲存體
<a name="video-storage-formats"></a>

Amazon Rekognition 操作可分析儲存於 Amazon S3 儲存貯體的影片。如需影片分析作業的所有限制清單，請參閱 [Amazon Rekognition 中的準則和配額](limits.md)。

影片需使用 H.264 編解碼器來編碼。支援的檔案格式為 MPEG-4 與 MOV。

編解碼器為壓縮資料讓傳遞更快速並將收到的資料解壓縮為原始格式的軟體或硬體工具。The H.264 編解碼器通常用於記錄、壓縮和發佈影片內容。影片檔案格式可包含一個或多個編解碼器。若您的 MOV 或 MPEG-4 格式影片檔案不適用於 Amazon Rekognition Video，請確認用於影片編碼的編解碼器為 H.264。

任何可分析音訊資料的 Amazon Rekognition Video API 只支援 AAC 音訊轉碼器。

可儲存影片的檔案大小上限為 10 GB。

### 搜尋人物
<a name="video-searching-persons-overview"></a>

您可以使用儲存在集合中的臉部中繼資料來搜尋影片中的人物。例如，您可以在封存的影片中搜尋特定人物或多個人物。使用 [IndexFaces](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_IndexFaces.html) 操作從集合中的原始映像儲存人臉中繼資料。接著可以使用 [StartFaceSearch](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartFaceSearch.html) 以於集合中啟動非同步人臉搜尋。可使用 [GetFaceSearch](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GeFaceSearch.html) 來取得搜尋結果。如需詳細資訊，請參閱 [在儲存的影片中搜尋人臉](procedure-person-search-videos.md)。搜尋人物為以儲存體為基礎的 Amazon Rekognition 操作之範例。如需詳細資訊，請參閱 [以儲存為基礎的 API 操作](how-it-works-storage-non-storage.md#how-it-works-storage-based)。

您也可以在串流影片中搜尋人物。如需詳細資訊，請參閱 [處理串流影片事件](streaming-video.md)。

# 呼叫 Amazon Rekognition Video 操作
<a name="api-video"></a>

Amazon Rekognition Video 是一種非同步 API，可以用來分析存放在 Amazon Simple Storage Service (Amazon S3) 儲存貯體中的影片。呼叫如 [StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html) 的 Amazon Rekognition Video `Start` 操作來開始影片分析。Amazon Rekognition Video 會將分析請求的結果發佈至 Amazon Simple Notification Service (Amazon SNS) 主題。您可以使用 Amazon Simple Queue Service (Amazon SQS) 佇列或 AWS Lambda 函數，從 Amazon SNS 主題取得影片分析請求的完成狀態。最後，您可以透過呼叫 Amazon Rekognition `Get` 操作 (如 [GetPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetPersonTracking.html)) 來取得影片分析請求結果。

下節中的資訊使用標籤偵測操作來顯示 Amazon Rekognition Video 在儲存於 Amazon S3 儲存貯體中的影片內偵測標籤 (物件、活動、概念與活動) 的方法。相同的方法適用於其他 Amazon Rekognition Video 操作 (例如，[StartFaceDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartFaceDetection.html)和[StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html))。範例 [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md) 說明如何使用 Amazon SQS 佇列自 Amazon SNS 主題取得完成狀態分析以分析影片。同時也用做為其它 Amazon Rekognition Video 範例的基礎，例如 [人物路徑](persons.md)。如需 AWS CLI 範例，請參閱 [使用 分析影片 AWS Command Line Interface](video-cli-commands.md)。

**Topics**
+ [開始影片分析](#api-video-start)
+ [取得 Amazon Rekognition Video 分析請求的完成狀態](#api-video-get-status)
+ [取得 Amazon Rekognition Video 分析結果](#api-video-get)

## 開始影片分析
<a name="api-video-start"></a>

[您可以透過呼叫 StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html) 來啟動 Amazon Rekognition Video 標籤偵測請求。以下是由 `StartLabelDetection` 傳遞的 JSON 請求範例。

```
{
    "Video": {
        "S3Object": {
            "Bucket": "amzn-s3-demo-bucket",
            "Name": "video.mp4"
        }
    },
    "ClientRequestToken": "LabelDetectionToken",
    "MinConfidence": 50,
    "NotificationChannel": {
        "SNSTopicArn": "arn:aws:sns:us-east-1:nnnnnnnnnn:topic",
        "RoleArn": "arn:aws:iam::nnnnnnnnnn:role/roleopic"
    },
    "JobTag": "DetectingLabels"
}
```

輸入參數 `Video` 提供影片檔案名稱以及擷取檔案的 Amazon S3 儲存貯體。`NotificationChannel` 包含在影片分析請求完成時由 Amazon Rekognition Video 所通知的 Amazon SNS 主題 Amazon Resource Name (ARN)。Amazon SNS 主題必須與您呼叫的 Amazon Rekognition Video 端點位於同一個 AWS 區域。`NotificationChannel` 也包含允許 Amazon Rekognition Video 發佈到 Amazon SNS 主題的角色 ARN。透過 IAM 服務角色的建立，您給予 Amazon Rekognition 發佈至 Amazon SNS 主題的許可。如需詳細資訊，請參閱 [設定 Amazon Rekognition Video](api-video-roles.md)。

您也可以指定選用的輸入參數，`JobTag`，可讓您找出顯示完成狀態且已發佈至 Amazon SNS 主題的任務。

為避免分析任務發生意外的重複，您可以選擇性地提供等冪符記 `ClientRequestToken`。如果您提供用於 `ClientRequestToken` 的值，`Start` 操作將傳回相同的 `JobId` 以用於對開始操作執行多個相同的呼叫，例如 `StartLabelDetection`。`ClientRequestToken` 符記有 7 天的存留期。在 7 天後，您可以再次使用它。如果您在符記的存留期內重新使用符記，會發生下列情況：
+ 如果您使用相同的 `Start` 操作與相同的輸入參數來重新使用字符，將傳回相同的 `JobId`。不會再次執行任務，而 Amazon Rekognition Video 也不會傳送完成狀態到已註冊的 Amazon SNS 主題。
+ 如果您以相同的 `Start` 操作搭配些微變更的參數來重新使用符記，您會得到一個 `IdempotentParameterMismatchException` (HTTP 狀態碼：400) 例外狀況。
+ 由於您會從 Amazon Rekognition 取得無法預測的結果，因此您不應使用具有不同 `Start` 操作的字符。

對於 `StartLabelDetection` 操作的回應為任務識別碼 (`JobId`)。使用 `JobId` 來追蹤請求並在 Amazon Rekognition Video 發佈完成狀態到 Amazon SNS 主題後取得分析結果。例如：

```
{"JobId":"270c1cc5e1d0ea2fbc59d97cb69a72a5495da75851976b14a1784ca90fc180e3"}
```

如果您同時開始太多任務，呼叫 `StartLabelDetection` 將引發 `LimitExceededException` (HTTP 狀態碼：400)，直到數量同時執行任務的數量低於 Amazon Rekognition 服務限制。

如果您發現 `LimitExceededException` 例外狀況發生且產生活動激增，請考慮使用 Amazon SQS 佇列來管理傳入的請求。如果您發現 Amazon SQS 佇列無法管理並行請求的平均數量，但仍收到`LimitExceededException`例外狀況，請聯絡 AWS 支援。

## 取得 Amazon Rekognition Video 分析請求的完成狀態
<a name="api-video-get-status"></a>

Amazon Rekognition Video 將傳送分析完成通知到已註冊的 Amazon SNS 主題。通知包含任務識別碼和並以 JSON 字串顯示操作的完成狀態。成功的影片分析請求將包含 `SUCCEEDED` 狀態。例如，以下結果顯示偵測標籤任務已成功處理。

```
{
    "JobId": "270c1cc5e1d0ea2fbc59d97cb69a72a5495da75851976b14a1nnnnnnnnnnnn",
    "Status": "SUCCEEDED",
    "API": "StartLabelDetection",
    "JobTag": "DetectingLabels",
    "Timestamp": 1510865364756,
    "Video": {
        "S3ObjectName": "video.mp4",
        "S3Bucket": "amzn-s3-demo-bucket"
    }
}
```

如需詳細資訊，請參閱 [參考：影片分析結果通知](video-notification-payload.md)。

若要取得 Amazon Rekognition Video 發佈至 Amazon SNS 主題的狀態資訊，請使用以下其中一個選項：
+ **AWS Lambda**：您可以註冊 AWS Lambda 函數，以寫入 Amazon SNS 主題。當 Amazon Rekognition 通知 Amazon SNS 主題請求已完成時，將呼叫此功能。如果您需要伺服器端程式碼來處理影片分析請求的結果，請使用 Lambda 函數。例如，您可能想要使用伺服器端程式碼來標註影片，或在傳回資訊到客戶端應用程式前針對影片內容建立報告。我們也建議使用伺服器端處理大型影片，因為 Amazon Rekognition API 可能會傳回大量資料。
+ **Amazon Simple Queue Service**：您可以訂閱 Amazon SQS 佇列到 Amazon SNS 主題。接著請輪詢 Amazon SQS 佇列以擷取由 Amazon Rekognition 在影片分析請求完成時發佈的完成狀態。如需詳細資訊，請參閱 [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md)。如果您只想從客戶端應用程式呼叫 Amazon Rekognition Video 操作，請使用 Amazon SQS 佇列。

**重要**  
我們不建議您透過重複呼叫 Amazon Rekognition Video `Get` 操作來取得請求完成狀態。這是因為如果執行太多請求，Amazon Rekognition Video 將對 `Get` 操作進行節制。如果您同時處理多個影片，監控一個 SQS 佇列的完成通知將會比輪詢 Amazon Rekognition Video 以獲得個別影片的狀態更容易且有效率。

## 取得 Amazon Rekognition Video 分析結果
<a name="api-video-get"></a>

 若要取得影片分析請求結果，首先請確認自 Amazon SNS 主題擷取的完成狀態為 `SUCCEEDED`。然後呼叫 `GetLabelDetection`，將傳遞自 `StartLabelDetection` 傳回的 `JobId` 值。請求 JSON 格式類似於以下範例：

```
{
    "JobId": "270c1cc5e1d0ea2fbc59d97cb69a72a5495da75851976b14a1784ca90fc180e3",
    "MaxResults": 10,
    "SortBy": "TIMESTAMP"
}
```

JobId 為用於影片分析操作的識別碼。由於影片分析可以產生大量資料，請使用 `MaxResults` 來指定最大數量的結果，以在單次取得操作中傳回結果。`MaxResults` 的預設值為 1000。如果您指定的值大於 1000，最多只能傳回 1000 個結果。如果操作不會傳回整組結果，將在操作回應中傳回下一頁的分頁符記。如果您自前一個取得請求中獲得一個分頁符記，請搭配 `NextToken` 一起使用以取得下一頁結果。

**注意**  
Amazon Rekognition 會保留影片分析操作的結果 7 天。在此時間後您將無法擷取分析結果。

`GetLabelDetection` 操作回應 JSON 格式類似於以下範例：

```
{
    "Labels": [
        {
            "Timestamp": 0,
            "Label": {
                "Instances": [],
                "Confidence": 60.51791763305664,
                "Parents": [],
                "Name": "Electronics"
            }
        },
        {
            "Timestamp": 0,
            "Label": {
                "Instances": [],
                "Confidence": 99.53411102294922,
                "Parents": [],
                "Name": "Human"
            }
        },
        {
            "Timestamp": 0,
            "Label": {
                "Instances": [
                    {
                        "BoundingBox": {
                            "Width": 0.11109819263219833,
                            "Top": 0.08098889887332916,
                            "Left": 0.8881205320358276,
                            "Height": 0.9073750972747803
                        },
                        "Confidence": 99.5831298828125
                    },
                    {
                        "BoundingBox": {
                            "Width": 0.1268676072359085,
                            "Top": 0.14018426835536957,
                            "Left": 0.0003282368124928324,
                            "Height": 0.7993982434272766
                        },
                        "Confidence": 99.46029663085938
                    }
                ],
                "Confidence": 99.53411102294922,
                "Parents": [],
                "Name": "Person"
            }
        },
        .
        .   
        .

        {
            "Timestamp": 166,
            "Label": {
                "Instances": [],
                "Confidence": 73.6471176147461,
                "Parents": [
                    {
                        "Name": "Clothing"
                    }
                ],
                "Name": "Sleeve"
            }
        }
        
    ],
    "LabelModelVersion": "2.0",
    "JobStatus": "SUCCEEDED",
    "VideoMetadata": {
        "Format": "QuickTime / MOV",
        "FrameRate": 23.976024627685547,
        "Codec": "h264",
        "DurationMillis": 5005,
        "FrameHeight": 674,
        "FrameWidth": 1280
    }
}
```

`GetLabelDetection` 和 `GetContentModeration` 操作可讓您依時間戳記或標籤名稱來排序分析結果。您也可以依影片區段或時間戳記彙總結果。

您可以透過偵測時間 (依據影片開始的毫秒計算) 來排序結果，或依照偵測的實體 (物件、臉部、名人、內容管制標籤或人物) 字母排序。若要依時間排序，將 `SortBy` 輸入參數值設為 `TIMESTAMP`。如果未指定 `SortBy`，預設行為是依據時間排序。前述範例是依時間排序。若要依據實體排序，使用 `SortBy` 輸入參數搭配適合您要執行的操作值。例如，在對 `GetLabelDetection` 的呼叫中依偵測的標籤排序時，需使用值 `NAME`。

若要依時間戳記彙總結果，請將 `AggregateBy` 參數值設定為 `TIMESTAMPS`。若要依視訊區段彙總，請將 `AggregateBy` 的值設定為 `SEGMENTS`。`SEGMENTS` 彙總模式將隨著時間的推移彙總標籤，同時使用 2 FPS 採樣和每幀輸出為標籤 `TIMESTAMPS` 提供偵測到的時間戳 (注意：此當前採樣率可能會發生變化，不應對當前採樣率進行假設)。如未指定任何值，預設為 `TIMESTAMPS`。

# 設定 Amazon Rekognition Video
<a name="api-video-roles"></a>

若要在儲存的影片中使用 Amazon Rekognition Video API，您必須設定使用者以及 IAM 服務角色來存取您的 Amazon SNS 主題。您也必須讓 Amazon SQS 佇列訂閱您的 Amazon SNS 主題。

**注意**  
如果您正依照這些說明設定 [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md) 範例，則無需進行步驟 3、4、5 和 6。此範例包括用於建立並設定 Amazon SNS 主題和 Amazon SQS 佇列的程式碼。

本節中的範例將依據說明來提供 Amazon Rekognition Video 存取多個主題的權限，並以此來建立新的 Amazon SNS 主題。如果您想要使用現有 Amazon SNS 主題，請在步驟 3 使用 [提供存取目前 Amazon SNS 主題的權限](#api-video-roles-single-topics)。<a name="configure-rekvid-procedure"></a>

**若要設定 Amazon Rekognition Video**

1. 設定 AWS 帳戶以存取 Amazon Rekognition Video。如需詳細資訊，請參閱[步驟 1：設定 AWS 帳戶並建立使用者](setting-up.md)。

1. 安裝和設定所需的 AWS SDK。如需詳細資訊，請參閱[步驟 2：設定 AWS CLI 和 AWS SDKs](setup-awscli-sdk.md)。

1. 若要執行此開發人員指南中的程式碼範例，請確定您選擇的使用者具有程式設計存取權。如需詳細資訊，請參閱 [授與程式設計存取權](sdk-programmatic-access.md)。

   您的使用者還需要至少下列許可：
   + AmazonSQSFullAccess
   + AmazonRekognitionFullAccess
   + AmazonS3FullAccess
   + AmazonSNSFullAccess

   如果您使用 IAM Identity Center 進行驗證，請將許可新增至角色的權限集，否則將許可新增至 IAM 角色。

1. 使用 [Amazon SNS 主控台建立 Amazon SNS 主題](https://docs.aws.amazon.com/sns/latest/dg/CreateTopic.html)。 [Amazon SNS ](https://console.aws.amazon.com/sns/v2/home) 將 *AmazonRekognition* 置於主題名稱的前面。請記下主題的 Amazon Resource Name (ARN)。請確認此主題與您使用的 AWS 端點位於同一個區域。

1. 使用 [Amazon SQS 主控台](https://console.aws.amazon.com/sqs/)來[建立 Amazon SQS 佇列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)。記下佇列 ARN。

1. [將佇列訂閱至您在步驟 3 中建立的主題](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-subscribe-queue-sns-topic.html)。

1. [將許可提供給 Amazon SNS 主題，以將訊息傳送至 Amazon SQS 佇列](https://docs.aws.amazon.com/sns/latest/dg/SendMessageToSQS.html#SendMessageToSQS.sqs.permissions)。

1. 建立 IAM 服務角色來提供存取您 Amazon SNS 主題的 Amazon Rekognition Video 權限。記下服務角色的 Amazon Resource Name (ARN)。如需詳細資訊，請參閱 [提供對多個 Amazon SNS 主題的存取權限](#api-video-roles-all-topics)。

1. 為了確保您的帳戶安全，您需要將 Rekognition 的存取範圍限制在您正在使用的資源。這可以通過將信任政策附加到您的 IAM 服務角色來完成。如需如何執行此作業的資訊，請參閱 [預防跨服務混淆代理人](cross-service-confused-deputy-prevention.md)。

1. [將以下內嵌政策](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#embed-inline-policy-console)新增到您在步驟 1 所建立的使用者：

   將內嵌政策命名為您想要的名稱。

1. 如果您使用客戶受管 AWS Key Management Service 金鑰來加密 Amazon S3 儲存貯體中的影片，請將許可[新增至](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-modifying.html#key-policy-modifying-how-to-console-policy-view)金鑰，以允許您在步驟 7 中建立的服務角色解密影片。服務角色至少需要 `kms:GenerateDataKey` 和 `kms:Decrypt` 動作的權限。例如：

   ```
   {
       "Sid": "Decrypt only",
       "Effect": "Allow",
       "Principal": {
           "AWS": "arn:aws:iam::111122223333:user/user from step 1"
       },
       "Action": [
           "kms:Decrypt",
           "kms:GenerateDataKey"
       ],
       "Resource": "*"
   }
   ```

   如需詳細資訊，請參閱 [Amazon S3 儲存貯體使用自訂 AWS KMS 金鑰的預設加密。如何允許使用者從儲存貯體下載並上傳至值區？](https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-access-default-encryption/)以及搭配[存放在 AWS Key Management Service (SSE-KMS) 中的 KMS 金鑰使用伺服器端加密來保護資料](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html)。

1. 您現在可執行 [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md) 和 [使用 分析影片 AWS Command Line Interface](video-cli-commands.md) 中的範例。

## 提供對多個 Amazon SNS 主題的存取權限
<a name="api-video-roles-all-topics"></a>

使用 IAM 服務角色來提供存取您所建立的 Amazon SNS 主題的 Amazon Rekognition Video 權限。IAM 提供用於建立 Amazon Rekognition Video 服務角色的 *Rekognition* 使用案例。

您可以提供 Amazon Rekognition Video 存取多個 Amazon SNS 主題的許可，方法包括使用 `AmazonRekognitionServiceRole` 許可政策並將*AmazonRekognition*置於主題名稱前方 (例如，`AmazonRekognitionMyTopicName`)。

**讓 Amazon Rekognition Video 存取多個 Amazon SNS 主題**

1. [建立 IAM 服務角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html?icmpid=docs_iam_console)。請使用下列資訊來建立 IAM 服務角色：

   1. 針對服務名稱選擇 **Rekognition**。

   1. 為服務角色使用案例選擇 **Rekognition**。您應該會看到列出的 **AmazonRekognitionServiceRole** 權限政策。**AmazonRekognitionServiceRole** 將提供 Amazon Rekognition Video 存取名稱前方加上 *AmazonRekognition* 的 Amazon SNS 主題的權限。

   1. 將服務角色命名為您想要的名稱。

1. 請記下服務角色的 ARN。您需要此資訊才可開始影片分析操作。

## 提供存取目前 Amazon SNS 主題的權限
<a name="api-video-roles-single-topics"></a>

您可以建立許可政策，以允許 Amazon Rekognition Video 存取現有的 Amazon SNS 主題。

**提供現有 Amazon SNS 主題的 Amazon Rekognition Video 存取權**

1. [使用 IAM JSON 政策編輯器建立新的許可政策](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html#access_policies_create-json-editor)，並使用下列政策。以想要的 Amazon SNS 主題 Amazon Resource Name (ARN) 來取代 `topicarn`。

1. [建立 IAM 服務角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html?icmpid=docs_iam_console)，或更新現有的 IAM 服務角色。請使用下列資訊來建立 IAM 服務角色：

   1. 針對服務名稱選擇 **Rekognition**。

   1. 為服務角色使用案例選擇 **Rekognition**。

   1. 連接您在步驟 1 中建立的許可政策。

1. 請記下服務角色的 ARN。您需要此資訊才可開始影片分析操作。

# 使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片
<a name="video-analyzing-with-sqs"></a>

此程序說明如何使用 Amazon Rekognition Video 標籤偵測操作、儲存在 Amazon S3 儲存貯體中的影片、以及 Amazon SNS 主題等方法來偵測影片中的標籤。程序同時也將說明如何使用 Amazon SQS 佇列從 Amazon SNS 主題取得完成狀態。如需詳細資訊，請參閱 [呼叫 Amazon Rekognition Video 操作](api-video.md)。不限於使用 Amazon SQS 佇列。例如，您可以使用 AWS Lambda 函數來取得完成狀態。如需詳細資訊，請參閱[使用 Amazon SNS 通知來呼叫 Lambda 函數](https://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html)。

此程序中的範例程式碼說明如何執行下列動作：

1. 建立 Amazon SNS 主題。

1. 建立 Amazon SQS 佇列。

1. 給予 Amazon Rekognition Video 發佈影片分析操作完成狀態到 Amazon SNS 主題的許可。

1. 訂閱佇列至 Amazon SNS 主題。

1. 呼叫 [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html) 以開始影片分析請求。

1. 從 Amazon SQS 佇列取得完成狀態。此範例追蹤在 `StartLabelDetection` 傳回的任務識別碼 (`JobId`)，在自完成狀態中讀取後，只會顯示相符的工作識別碼之結果。如果其他應用程式使用相同的佇列和主題，這便是項重要的考量條件。為了方便起見，此範例刪除不符合的任務。考慮將它們新增到 Amazon SQS 無效字母佇列以供進一步調查。

1. 呼叫 [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html) 來取得並顯示影片分析結果。

## 先決條件
<a name="video-prerequisites"></a>

此程序的範例程式碼以 Java 和 Python 提供。您需要安裝適當的 AWS SDK。如需詳細資訊，請參閱[Amazon Rekognition 入門](getting-started.md)。您使用的 AWS 帳戶必須有 Amazon Rekognition API 的存取許可。如需詳細資訊，請參閱 [Amazon Rekognition 定義的動作](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonrekognition.html#amazonrekognition-actions-as-permissions)。

**若要偵測影片中的標籤**

1. 設定使用者對 Amazon Rekognition Video 的存取權限，並設定 Amazon Rekognition Video 對 Amazon SNS 的存取。如需詳細資訊，請參閱 [設定 Amazon Rekognition Video](api-video-roles.md)。由於範例程式碼會建立並設定 Amazon SNS 主題和 Amazon SQS 佇列，因此無須進行步驟 3、4、5 和 6。

1. 將 MOV 或 MPEG-4 格式的影片上傳到 Amazon S3 儲存貯體。為達測試目的，請上傳長度不超過 30 秒的影片。

   如需指示說明，請參閱《Amazon Simple Storage Service 使用者指南》**中的[上傳物件至 Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UploadingObjectsintoAmazonS3.html)。

   

1. 使用以下程式碼範例來偵測影片中的標籤。

------
#### [ Java ]

   在函數 `main` 中：
   + 將 `roleArn` 取代為您在 [若要設定 Amazon Rekognition Video](api-video-roles.md#configure-rekvid-procedure) 步驟 7 建立的 IAM 服務角色 ARN。
   + 以您在步驟 2 中指定的儲存貯體與影片檔名稱來取代 `amzn-s3-demo-bucket` 與 `video` 的值。

   ```
   //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.samples;
   import com.amazonaws.auth.policy.Policy;
   import com.amazonaws.auth.policy.Condition;
   import com.amazonaws.auth.policy.Principal;
   import com.amazonaws.auth.policy.Resource;
   import com.amazonaws.auth.policy.Statement;
   import com.amazonaws.auth.policy.Statement.Effect;
   import com.amazonaws.auth.policy.actions.SQSActions;
   import com.amazonaws.services.rekognition.AmazonRekognition;
   import com.amazonaws.services.rekognition.AmazonRekognitionClientBuilder;
   import com.amazonaws.services.rekognition.model.CelebrityDetail;
   import com.amazonaws.services.rekognition.model.CelebrityRecognition;
   import com.amazonaws.services.rekognition.model.CelebrityRecognitionSortBy;
   import com.amazonaws.services.rekognition.model.ContentModerationDetection;
   import com.amazonaws.services.rekognition.model.ContentModerationSortBy;
   import com.amazonaws.services.rekognition.model.Face;
   import com.amazonaws.services.rekognition.model.FaceDetection;
   import com.amazonaws.services.rekognition.model.FaceMatch;
   import com.amazonaws.services.rekognition.model.FaceSearchSortBy;
   import com.amazonaws.services.rekognition.model.GetCelebrityRecognitionRequest;
   import com.amazonaws.services.rekognition.model.GetCelebrityRecognitionResult;
   import com.amazonaws.services.rekognition.model.GetContentModerationRequest;
   import com.amazonaws.services.rekognition.model.GetContentModerationResult;
   import com.amazonaws.services.rekognition.model.GetFaceDetectionRequest;
   import com.amazonaws.services.rekognition.model.GetFaceDetectionResult;
   import com.amazonaws.services.rekognition.model.GetFaceSearchRequest;
   import com.amazonaws.services.rekognition.model.GetFaceSearchResult;
   import com.amazonaws.services.rekognition.model.GetLabelDetectionRequest;
   import com.amazonaws.services.rekognition.model.GetLabelDetectionResult;
   import com.amazonaws.services.rekognition.model.GetPersonTrackingRequest;
   import com.amazonaws.services.rekognition.model.GetPersonTrackingResult;
   import com.amazonaws.services.rekognition.model.Instance;
   import com.amazonaws.services.rekognition.model.Label;
   import com.amazonaws.services.rekognition.model.LabelDetection;
   import com.amazonaws.services.rekognition.model.LabelDetectionSortBy;
   import com.amazonaws.services.rekognition.model.NotificationChannel;
   import com.amazonaws.services.rekognition.model.Parent;
   import com.amazonaws.services.rekognition.model.PersonDetection;
   import com.amazonaws.services.rekognition.model.PersonMatch;
   import com.amazonaws.services.rekognition.model.PersonTrackingSortBy;
   import com.amazonaws.services.rekognition.model.S3Object;
   import com.amazonaws.services.rekognition.model.StartCelebrityRecognitionRequest;
   import com.amazonaws.services.rekognition.model.StartCelebrityRecognitionResult;
   import com.amazonaws.services.rekognition.model.StartContentModerationRequest;
   import com.amazonaws.services.rekognition.model.StartContentModerationResult;
   import com.amazonaws.services.rekognition.model.StartFaceDetectionRequest;
   import com.amazonaws.services.rekognition.model.StartFaceDetectionResult;
   import com.amazonaws.services.rekognition.model.StartFaceSearchRequest;
   import com.amazonaws.services.rekognition.model.StartFaceSearchResult;
   import com.amazonaws.services.rekognition.model.StartLabelDetectionRequest;
   import com.amazonaws.services.rekognition.model.StartLabelDetectionResult;
   import com.amazonaws.services.rekognition.model.StartPersonTrackingRequest;
   import com.amazonaws.services.rekognition.model.StartPersonTrackingResult;
   import com.amazonaws.services.rekognition.model.Video;
   import com.amazonaws.services.rekognition.model.VideoMetadata;
   import com.amazonaws.services.sns.AmazonSNS;
   import com.amazonaws.services.sns.AmazonSNSClientBuilder;
   import com.amazonaws.services.sns.model.CreateTopicRequest;
   import com.amazonaws.services.sns.model.CreateTopicResult;
   import com.amazonaws.services.sqs.AmazonSQS;
   import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
   import com.amazonaws.services.sqs.model.CreateQueueRequest;
   import com.amazonaws.services.sqs.model.Message;
   import com.amazonaws.services.sqs.model.QueueAttributeName;
   import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;
   import com.fasterxml.jackson.databind.JsonNode;
   import com.fasterxml.jackson.databind.ObjectMapper;
   import java.util.*;
   
   public class VideoDetect {
    
       
       private static String sqsQueueName=null;
       private static String snsTopicName=null;
       private static String snsTopicArn = null;
       private static String roleArn= null;
       private static String sqsQueueUrl = null;
       private static String sqsQueueArn = null;
       private static String startJobId = null;
       private static String bucket = null;
       private static String video = null; 
       private static AmazonSQS sqs=null;
       private static AmazonSNS sns=null;
       private static AmazonRekognition rek = null;
       
       private static NotificationChannel channel= new NotificationChannel()
               .withSNSTopicArn(snsTopicArn)
               .withRoleArn(roleArn);
   
   
       public static void main(String[] args) throws Exception {
           
           video = "";
           bucket = "";
           roleArn= "";
   
           sns = AmazonSNSClientBuilder.defaultClient();
           sqs= AmazonSQSClientBuilder.defaultClient();
           rek = AmazonRekognitionClientBuilder.defaultClient();
     
           CreateTopicandQueue();
           
           //=================================================
           
           StartLabelDetection(bucket, video);
   
           if (GetSQSMessageSuccess()==true)
           	GetLabelDetectionResults();
           
          //=================================================  
           
   
           DeleteTopicandQueue();
           System.out.println("Done!");
          
       }
   
       
       static boolean GetSQSMessageSuccess() throws Exception
       {
       	boolean success=false;
   
      
           System.out.println("Waiting for job: " + startJobId);
           //Poll queue for messages
           List<Message> messages=null;
           int dotLine=0;
           boolean jobFound=false;
   
           //loop until the job status is published. Ignore other messages in queue.
           do{
               messages = sqs.receiveMessage(sqsQueueUrl).getMessages();
               if (dotLine++<40){
                   System.out.print(".");
               }else{
                   System.out.println();
                   dotLine=0;
               }
   
               if (!messages.isEmpty()) {
                   //Loop through messages received.
                   for (Message message: messages) {
                       String notification = message.getBody();
   
                       // Get status and job id from notification.
                       ObjectMapper mapper = new ObjectMapper();
                       JsonNode jsonMessageTree = mapper.readTree(notification);
                       JsonNode messageBodyText = jsonMessageTree.get("Message");
                       ObjectMapper operationResultMapper = new ObjectMapper();
                       JsonNode jsonResultTree = operationResultMapper.readTree(messageBodyText.textValue());
                       JsonNode operationJobId = jsonResultTree.get("JobId");
                       JsonNode operationStatus = jsonResultTree.get("Status");
                       System.out.println("Job found was " + operationJobId);
                       // Found job. Get the results and display.
                       if(operationJobId.asText().equals(startJobId)){
                           jobFound=true;
                           System.out.println("Job id: " + operationJobId );
                           System.out.println("Status : " + operationStatus.toString());
                           if (operationStatus.asText().equals("SUCCEEDED")){
                           	success=true;
                           }
                           else{
                               System.out.println("Video analysis failed");
                           }
   
                           sqs.deleteMessage(sqsQueueUrl,message.getReceiptHandle());
                       }
   
                       else{
                           System.out.println("Job received was not job " +  startJobId);
                           //Delete unknown message. Consider moving message to dead letter queue
                           sqs.deleteMessage(sqsQueueUrl,message.getReceiptHandle());
                       }
                   }
               }
               else {
                   Thread.sleep(5000);
               }
           } while (!jobFound);
   
           System.out.println("Finished processing video");
           return success;
       }
     
   
       private static void StartLabelDetection(String bucket, String video) throws Exception{
       	
           NotificationChannel channel= new NotificationChannel()
                   .withSNSTopicArn(snsTopicArn)
                   .withRoleArn(roleArn);
   
   
           StartLabelDetectionRequest req = new StartLabelDetectionRequest()
                   .withVideo(new Video()
                           .withS3Object(new S3Object()
                                   .withBucket(bucket)
                                   .withName(video)))
                   .withMinConfidence(50F)
                   .withJobTag("DetectingLabels")
                   .withNotificationChannel(channel);
   
           StartLabelDetectionResult startLabelDetectionResult = rek.startLabelDetection(req);
           startJobId=startLabelDetectionResult.getJobId();
           
       }
     
       private static void GetLabelDetectionResults() throws Exception{
   
           int maxResults=10;
           String paginationToken=null;
           GetLabelDetectionResult labelDetectionResult=null;
   
           do {
               if (labelDetectionResult !=null){
                   paginationToken = labelDetectionResult.getNextToken();
               }
   
               GetLabelDetectionRequest labelDetectionRequest= new GetLabelDetectionRequest()
                       .withJobId(startJobId)
                       .withSortBy(LabelDetectionSortBy.TIMESTAMP)
                       .withMaxResults(maxResults)
                       .withNextToken(paginationToken);
   
   
               labelDetectionResult = rek.getLabelDetection(labelDetectionRequest);
   
               VideoMetadata videoMetaData=labelDetectionResult.getVideoMetadata();
   
               System.out.println("Format: " + videoMetaData.getFormat());
               System.out.println("Codec: " + videoMetaData.getCodec());
               System.out.println("Duration: " + videoMetaData.getDurationMillis());
               System.out.println("FrameRate: " + videoMetaData.getFrameRate());
   
   
               //Show labels, confidence and detection times
               List<LabelDetection> detectedLabels= labelDetectionResult.getLabels();
   
               for (LabelDetection detectedLabel: detectedLabels) {
                   long seconds=detectedLabel.getTimestamp();
                   Label label=detectedLabel.getLabel();
                   System.out.println("Millisecond: " + Long.toString(seconds) + " ");
                   
                   System.out.println("   Label:" + label.getName()); 
                   System.out.println("   Confidence:" + detectedLabel.getLabel().getConfidence().toString());
         
                   List<Instance> instances = label.getInstances();
                   System.out.println("   Instances of " + label.getName());
                   if (instances.isEmpty()) {
                       System.out.println("        " + "None");
                   } else {
                       for (Instance instance : instances) {
                           System.out.println("        Confidence: " + instance.getConfidence().toString());
                           System.out.println("        Bounding box: " + instance.getBoundingBox().toString());
                       }
                   }
                   System.out.println("   Parent labels for " + label.getName() + ":");
                   List<Parent> parents = label.getParents();
                   if (parents.isEmpty()) {
                       System.out.println("        None");
                   } else {
                       for (Parent parent : parents) {
                           System.out.println("        " + parent.getName());
                       }
                   }
                   System.out.println();
               }
           } while (labelDetectionResult !=null && labelDetectionResult.getNextToken() != null);
   
       } 
   
       // Creates an SNS topic and SQS queue. The queue is subscribed to the topic. 
       static void CreateTopicandQueue()
       {
           //create a new SNS topic
           snsTopicName="AmazonRekognitionTopic" + Long.toString(System.currentTimeMillis());
           CreateTopicRequest createTopicRequest = new CreateTopicRequest(snsTopicName);
           CreateTopicResult createTopicResult = sns.createTopic(createTopicRequest);
           snsTopicArn=createTopicResult.getTopicArn();
           
           //Create a new SQS Queue
           sqsQueueName="AmazonRekognitionQueue" + Long.toString(System.currentTimeMillis());
           final CreateQueueRequest createQueueRequest = new CreateQueueRequest(sqsQueueName);
           sqsQueueUrl = sqs.createQueue(createQueueRequest).getQueueUrl();
           sqsQueueArn = sqs.getQueueAttributes(sqsQueueUrl, Arrays.asList("QueueArn")).getAttributes().get("QueueArn");
           
           //Subscribe SQS queue to SNS topic
           String sqsSubscriptionArn = sns.subscribe(snsTopicArn, "sqs", sqsQueueArn).getSubscriptionArn();
           
           // Authorize queue
             Policy policy = new Policy().withStatements(
                     new Statement(Effect.Allow)
                     .withPrincipals(Principal.AllUsers)
                     .withActions(SQSActions.SendMessage)
                     .withResources(new Resource(sqsQueueArn))
                     .withConditions(new Condition().withType("ArnEquals").withConditionKey("aws:SourceArn").withValues(snsTopicArn))
                     );
                     
   
             Map queueAttributes = new HashMap();
             queueAttributes.put(QueueAttributeName.Policy.toString(), policy.toJson());
             sqs.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueUrl, queueAttributes)); 
           
   
            System.out.println("Topic arn: " + snsTopicArn);
            System.out.println("Queue arn: " + sqsQueueArn);
            System.out.println("Queue url: " + sqsQueueUrl);
            System.out.println("Queue sub arn: " + sqsSubscriptionArn );
        }
       static void DeleteTopicandQueue()
       {
           if (sqs !=null) {
               sqs.deleteQueue(sqsQueueUrl);
               System.out.println("SQS queue deleted");
           }
           
           if (sns!=null) {
               sns.deleteTopic(snsTopicArn);
               System.out.println("SNS topic deleted");
           }
       }
   }
   ```

------
#### [ Python ]

   在函數 `main` 中：
   + 將 `roleArn` 取代為您在 [若要設定 Amazon Rekognition Video](api-video-roles.md#configure-rekvid-procedure) 步驟 7 建立的 IAM 服務角色 ARN。
   + 以您在步驟 2 中指定的儲存貯體與影片檔名稱來取代 `amzn-s3-demo-bucket` 與 `video` 的值。
   + 將建立 Rekognition 工作階段的行中 `profile_name` 值取代為您開發人員設定檔的名稱。
   + 您還可以在設定參數中包括過濾條件。例如，您可以在所需值的清單之外，邊使用 `LabelsInclusionFilter` 或 `LabelsExclusionFilter`。在下面的程式碼中，您可以取消註釋 `Features` 和 `Settings` 部分，並提供自己的值，以將傳回的結果限制為只有您感興趣的標籤。
   + 在呼叫 `GetLabelDetection` 中，您可以提供 `SortBy` 和 `AggregateBy` 引數的值。若要依時間排序，將 `SortBy` 輸入參數值設為 `TIMESTAMP`。若要依據實體排序，使用 `SortBy` 輸入參數搭配適合您要執行的操作值。若要依時間戳記彙總結果，請將 `AggregateBy` 參數值設定為 `TIMESTAMPS`。若要依影片片段彙總，請使用 `SEGMENTS`。

   在程式碼範例中，將下列 IAM 政策放在行 的引號內`policy = """""".format(sqsQueueArn, self.snsTopicArn)`。

   ```
   ## 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.)
   
   import boto3
   import json
   import sys
   import time
   
   class VideoDetect:
   
       jobId = ''
   
       roleArn = ''
       bucket = ''
       video = ''
       startJobId = ''
   
       sqsQueueUrl = ''
       snsTopicArn = ''
       processType = ''
   
       def __init__(self, role, bucket, video, client, rek, sqs, sns):
           self.roleArn = role
           self.bucket = bucket
           self.video = video
           self.client = client
           self.rek = rek
           self.sqs = sqs
           self.sns = sns
   
       def GetSQSMessageSuccess(self):
   
           jobFound = False
           succeeded = False
   
           dotLine = 0
           while jobFound == False:
               sqsResponse = self.sqs.receive_message(QueueUrl=self.sqsQueueUrl, MessageAttributeNames=['ALL'],
                                                      MaxNumberOfMessages=10)
   
               if sqsResponse:
   
                   if 'Messages' not in sqsResponse:
                       if dotLine < 40:
                           print('.', end='')
                           dotLine = dotLine + 1
                       else:
                           print()
                           dotLine = 0
                       sys.stdout.flush()
                       time.sleep(5)
                       continue
   
                   for message in sqsResponse['Messages']:
                       notification = json.loads(message['Body'])
                       rekMessage = json.loads(notification['Message'])
                       print(rekMessage['JobId'])
                       print(rekMessage['Status'])
                       if rekMessage['JobId'] == self.startJobId:
                           print('Matching Job Found:' + rekMessage['JobId'])
                           jobFound = True
                           if (rekMessage['Status'] == 'SUCCEEDED'):
                               succeeded = True
   
                           self.sqs.delete_message(QueueUrl=self.sqsQueueUrl,
                                                   ReceiptHandle=message['ReceiptHandle'])
                       else:
                           print("Job didn't match:" +
                                 str(rekMessage['JobId']) + ' : ' + self.startJobId)
                       # Delete the unknown message. Consider sending to dead letter queue
                       self.sqs.delete_message(QueueUrl=self.sqsQueueUrl,
                                               ReceiptHandle=message['ReceiptHandle'])
   
           return succeeded
   
       def StartLabelDetection(self):
           response = self.rek.start_label_detection(Video={'S3Object': {'Bucket': self.bucket, 'Name': self.video}},
                                                     NotificationChannel={'RoleArn': self.roleArn,
                                                                          'SNSTopicArn': self.snsTopicArn},
                                                     MinConfidence=90,
                                                     # Filtration options, uncomment and add desired labels to filter returned labels
                                                     # Features=['GENERAL_LABELS'],
                                                     # Settings={
                                                     # 'GeneralLabels': {
                                                     # 'LabelInclusionFilters': ['Clothing']
                                                     # }}
                                                      )
   
           self.startJobId = response['JobId']
           print('Start Job Id: ' + self.startJobId)
   
       def GetLabelDetectionResults(self):
           maxResults = 10
           paginationToken = ''
           finished = False
   
           while finished == False:
               response = self.rek.get_label_detection(JobId=self.startJobId,
                                                       MaxResults=maxResults,
                                                       NextToken=paginationToken,
                                                       SortBy='TIMESTAMP',
                                                       AggregateBy="TIMESTAMPS")
   
               print('Codec: ' + response['VideoMetadata']['Codec'])
               print('Duration: ' + str(response['VideoMetadata']['DurationMillis']))
               print('Format: ' + response['VideoMetadata']['Format'])
               print('Frame rate: ' + str(response['VideoMetadata']['FrameRate']))
               print()
   
               for labelDetection in response['Labels']:
                   label = labelDetection['Label']
   
                   print("Timestamp: " + str(labelDetection['Timestamp']))
                   print("   Label: " + label['Name'])
                   print("   Confidence: " + str(label['Confidence']))
                   print("   Instances:")
                   for instance in label['Instances']:
                       print("      Confidence: " + str(instance['Confidence']))
                       print("      Bounding box")
                       print("        Top: " + str(instance['BoundingBox']['Top']))
                       print("        Left: " + str(instance['BoundingBox']['Left']))
                       print("        Width: " + str(instance['BoundingBox']['Width']))
                       print("        Height: " + str(instance['BoundingBox']['Height']))
                       print()
                   print()
   
                   print("Parents:")
                   for parent in label['Parents']:
                       print("   " + parent['Name'])
   
                   print("Aliases:")
                   for alias in label['Aliases']:
                       print("   " + alias['Name'])
   
                   print("Categories:")
                   for category in label['Categories']:
                       print("   " + category['Name'])
                   print("----------")
                   print()
   
                   if 'NextToken' in response:
                       paginationToken = response['NextToken']
                   else:
                       finished = True
   
       def CreateTopicandQueue(self):
   
           millis = str(int(round(time.time() * 1000)))
   
           # Create SNS topic
   
           snsTopicName = "AmazonRekognitionExample" + millis
   
           topicResponse = self.sns.create_topic(Name=snsTopicName)
           self.snsTopicArn = topicResponse['TopicArn']
   
           # create SQS queue
           sqsQueueName = "AmazonRekognitionQueue" + millis
           self.sqs.create_queue(QueueName=sqsQueueName)
           self.sqsQueueUrl = self.sqs.get_queue_url(QueueName=sqsQueueName)['QueueUrl']
   
           attribs = self.sqs.get_queue_attributes(QueueUrl=self.sqsQueueUrl,
                                                   AttributeNames=['QueueArn'])['Attributes']
   
           sqsQueueArn = attribs['QueueArn']
   
           # Subscribe SQS queue to SNS topic
           self.sns.subscribe(
               TopicArn=self.snsTopicArn,
               Protocol='sqs',
               Endpoint=sqsQueueArn)
   
           # Authorize SNS to write SQS queue 
           # Insert the policy from the documentation from 
           policy = """
           {{
              "Version":"2012-10-17",              
              "Statement":[
               {{
                   "Sid":"MyPolicy",
                   "Effect":"Allow",
                   "Principal" : {{"AWS" : "*"}},
                   "Action":"SQS:SendMessage",
                   "Resource": "{}",
                   "Condition":{{
                       "ArnEquals":{{
                           "aws:SourceArn": "{}"
                        }}
                   }}
               }}
               ]
           }}""".format(sqsQueueArn, self.snsTopicArn)
   
           response = self.sqs.set_queue_attributes(
               QueueUrl=self.sqsQueueUrl,
               Attributes={
                   'Policy': policy
               })
   
       def DeleteTopicandQueue(self):
           self.sqs.delete_queue(QueueUrl=self.sqsQueueUrl)
           self.sns.delete_topic(TopicArn=self.snsTopicArn)
   
   def main():
       
       roleArn = 'role-arn'
       bucket = 'bucket-name'
       video = 'video-name'
   
       session = boto3.Session(profile_name='profile-name')
       client = session.client('rekognition')
       rek = boto3.client('rekognition')
       sqs = boto3.client('sqs')
       sns = boto3.client('sns')
   
       analyzer = VideoDetect(roleArn, bucket, video, client, rek, sqs, sns)
       analyzer.CreateTopicandQueue()
   
       analyzer.StartLabelDetection()
       if analyzer.GetSQSMessageSuccess() == True:
           analyzer.GetLabelDetectionResults()
   
       analyzer.DeleteTopicandQueue()
   
   if __name__ == "__main__":
       main()
   ```

------
#### [ Node.Js ]

   請參閱以下範本程式碼：
   + 將 `REGION` 的值取代為您帳戶營運地區的名稱。
   + 以包含影片檔案的 Amazon S3 儲存貯體之名稱取代 `amzn-s3-demo-bucket` 的值。
   + 在 Amazon S3 儲存貯體中，以您的 S3 儲存貯體名稱取代 `videoName` 的值。
   +  將建立 Rekognition 工作階段的行中 `profile_name` 值取代為您開發人員設定檔的名稱。
   + 將 `roleArn` 取代為您在 [若要設定 Amazon Rekognition Video](api-video-roles.md#configure-rekvid-procedure) 步驟 7 建立的 IAM 服務角色 ARN。

   ```
   import { CreateQueueCommand, GetQueueAttributesCommand, GetQueueUrlCommand, 
     SetQueueAttributesCommand, DeleteQueueCommand, ReceiveMessageCommand, DeleteMessageCommand } from  "@aws-sdk/client-sqs";
   import {CreateTopicCommand, SubscribeCommand, DeleteTopicCommand } from "@aws-sdk/client-sns";
   import  { SQSClient } from "@aws-sdk/client-sqs";
   import  { SNSClient } from "@aws-sdk/client-sns";
   import  { RekognitionClient, StartLabelDetectionCommand, GetLabelDetectionCommand } from "@aws-sdk/client-rekognition";
   import { stdout } from "process";
   import {fromIni} from '@aws-sdk/credential-providers';
   
   // Set the AWS Region.
   const REGION = "region-name"; //e.g. "us-east-1"
   const profileName = "profile-name"
   // Create SNS service object.
   const sqsClient = new SQSClient({ region: REGION, 
     credentials: fromIni({profile: profileName,}), });
   const snsClient = new SNSClient({ region: REGION, 
     credentials: fromIni({profile: profileName,}), });
   const rekClient = new RekognitionClient({region: REGION, 
     credentials: fromIni({profile: profileName,}), 
   });
   
   // Set bucket and video variables
   const bucket = "bucket-name";
   const videoName = "video-name";
   const roleArn = "role-arn"
   var startJobId = ""
   
   var ts = Date.now();
   const snsTopicName = "AmazonRekognitionExample" + ts;
   const snsTopicParams = {Name: snsTopicName}
   const sqsQueueName = "AmazonRekognitionQueue-" + ts;
   
   // Set the parameters
   const sqsParams = {
     QueueName: sqsQueueName, //SQS_QUEUE_URL
     Attributes: {
       DelaySeconds: "60", // Number of seconds delay.
       MessageRetentionPeriod: "86400", // Number of seconds delay.
     },
   };
   
   const createTopicandQueue = async () => {
     try {
       // Create SNS topic
       const topicResponse = await snsClient.send(new CreateTopicCommand(snsTopicParams));
       const topicArn = topicResponse.TopicArn
       console.log("Success", topicResponse);
       // Create SQS Queue
       const sqsResponse = await sqsClient.send(new CreateQueueCommand(sqsParams));
       console.log("Success", sqsResponse);
       const sqsQueueCommand = await sqsClient.send(new GetQueueUrlCommand({QueueName: sqsQueueName}))
       const sqsQueueUrl = sqsQueueCommand.QueueUrl
       const attribsResponse = await sqsClient.send(new GetQueueAttributesCommand({QueueUrl: sqsQueueUrl, AttributeNames: ['QueueArn']}))
       const attribs = attribsResponse.Attributes
       console.log(attribs)
       const queueArn = attribs.QueueArn
       // subscribe SQS queue to SNS topic
       const subscribed = await snsClient.send(new SubscribeCommand({TopicArn: topicArn, Protocol:'sqs', Endpoint: queueArn}))
       const policy = {
         Version: "2012-10-17",&TCX5-2025-waiver;                
         Statement: [
           {
             Sid: "MyPolicy",
             Effect: "Allow",
             Principal: {AWS: "*"},
             Action: "SQS:SendMessage",
             Resource: queueArn,
             Condition: {
               ArnEquals: {
                 'aws:SourceArn': topicArn
               }
             }
           }
         ]
       };
   
       const response = sqsClient.send(new SetQueueAttributesCommand({QueueUrl: sqsQueueUrl, Attributes: {Policy: JSON.stringify(policy)}}))
       console.log(response)
       console.log(sqsQueueUrl, topicArn)
       return [sqsQueueUrl, topicArn]
   
     } catch (err) {
       console.log("Error", err);
     }
   };
   
   const startLabelDetection = async (roleArn, snsTopicArn) => {
     try {
       //Initiate label detection and update value of startJobId with returned Job ID
      const labelDetectionResponse = await rekClient.send(new StartLabelDetectionCommand({Video:{S3Object:{Bucket:bucket, Name:videoName}}, 
         NotificationChannel:{RoleArn: roleArn, SNSTopicArn: snsTopicArn}}));
         startJobId = labelDetectionResponse.JobId
         console.log(`JobID: ${startJobId}`)
         return startJobId
     } catch (err) {
       console.log("Error", err);
     }
   };
   
   const getLabelDetectionResults = async(startJobId) => {
     console.log("Retrieving Label Detection results")
     // Set max results, paginationToken and finished will be updated depending on response values
     var maxResults = 10
     var paginationToken = ''
     var finished = false
   
     // Begin retrieving label detection results
     while (finished == false){
       var response = await rekClient.send(new GetLabelDetectionCommand({JobId: startJobId, MaxResults: maxResults, 
         NextToken: paginationToken, SortBy:'TIMESTAMP'}))
         // Log metadata
         console.log(`Codec: ${response.VideoMetadata.Codec}`)
         console.log(`Duration: ${response.VideoMetadata.DurationMillis}`)
         console.log(`Format: ${response.VideoMetadata.Format}`)
         console.log(`Frame Rate: ${response.VideoMetadata.FrameRate}`)
         console.log()
         // For every detected label, log label, confidence, bounding box, and timestamp
         response.Labels.forEach(labelDetection => {
           var label = labelDetection.Label
           console.log(`Timestamp: ${labelDetection.Timestamp}`)
           console.log(`Label: ${label.Name}`)
           console.log(`Confidence: ${label.Confidence}`)
           console.log("Instances:")
           label.Instances.forEach(instance =>{
             console.log(`Confidence: ${instance.Confidence}`)
             console.log("Bounding Box:")
             console.log(`Top: ${instance.Confidence}`)
             console.log(`Left: ${instance.Confidence}`)
             console.log(`Width: ${instance.Confidence}`)
             console.log(`Height: ${instance.Confidence}`)
             console.log()
           })
         console.log()
         // Log parent if found
         console.log("   Parents:")
         label.Parents.forEach(parent =>{
           console.log(`    ${parent.Name}`)
         })
         console.log()
         // Searh for pagination token, if found, set variable to next token
         if (String(response).includes("NextToken")){
           paginationToken = response.NextToken
   
         }else{
           finished = true
         }
   
         })
     }
   }
   
   // Checks for status of job completion
   const getSQSMessageSuccess = async(sqsQueueUrl, startJobId) => {
     try {
       // Set job found and success status to false initially
       var jobFound = false
       var succeeded = false
       var dotLine = 0
       // while not found, continue to poll for response
       while (jobFound == false){
         var sqsReceivedResponse = await sqsClient.send(new ReceiveMessageCommand({QueueUrl:sqsQueueUrl, 
           MaxNumberOfMessages:'ALL', MaxNumberOfMessages:10}));
         if (sqsReceivedResponse){
           var responseString = JSON.stringify(sqsReceivedResponse)
           if (!responseString.includes('Body')){
             if (dotLine < 40) {
               console.log('.')
               dotLine = dotLine + 1
             }else {
               console.log('')
               dotLine = 0 
             };
             stdout.write('', () => {
               console.log('');
             });
             await new Promise(resolve => setTimeout(resolve, 5000));
             continue
           }
         }
   
         // Once job found, log Job ID and return true if status is succeeded
         for (var message of sqsReceivedResponse.Messages){
           console.log("Retrieved messages:")
           var notification = JSON.parse(message.Body)
           var rekMessage = JSON.parse(notification.Message)
           var messageJobId = rekMessage.JobId
           if (String(rekMessage.JobId).includes(String(startJobId))){
             console.log('Matching job found:')
             console.log(rekMessage.JobId)
             jobFound = true
             console.log(rekMessage.Status)
             if (String(rekMessage.Status).includes(String("SUCCEEDED"))){
               succeeded = true
               console.log("Job processing succeeded.")
               var sqsDeleteMessage = await sqsClient.send(new DeleteMessageCommand({QueueUrl:sqsQueueUrl, ReceiptHandle:message.ReceiptHandle}));
             }
           }else{
             console.log("Provided Job ID did not match returned ID.")
             var sqsDeleteMessage = await sqsClient.send(new DeleteMessageCommand({QueueUrl:sqsQueueUrl, ReceiptHandle:message.ReceiptHandle}));
           }
         }
       }
     return succeeded
     } catch(err) {
       console.log("Error", err);
     }
   };
   
   // Start label detection job, sent status notification, check for success status
   // Retrieve results if status is "SUCEEDED", delete notification queue and topic
   const runLabelDetectionAndGetResults = async () => {
     try {
       const sqsAndTopic = await createTopicandQueue();
       const startLabelDetectionRes = await startLabelDetection(roleArn, sqsAndTopic[1]);
       const getSQSMessageStatus = await getSQSMessageSuccess(sqsAndTopic[0], startLabelDetectionRes)
       console.log(getSQSMessageSuccess)
       if (getSQSMessageSuccess){
         console.log("Retrieving results:")
         const results = await getLabelDetectionResults(startLabelDetectionRes)
       }
       const deleteQueue = await sqsClient.send(new DeleteQueueCommand({QueueUrl: sqsAndTopic[0]}));
       const deleteTopic = await snsClient.send(new DeleteTopicCommand({TopicArn: sqsAndTopic[1]}));
       console.log("Successfully deleted.")
     } catch (err) {
       console.log("Error", err);
     }
   };
   
   runLabelDetectionAndGetResults()
   ```

------
#### [ Java V2 ]

   此程式碼取自 AWS 文件開發套件範例 GitHub 儲存庫。請參閱[此處](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/rekognition/src/main/java/com/example/rekognition/VideoDetect.java)的完整範例。

   ```
   import com.fasterxml.jackson.core.JsonProcessingException;
   import com.fasterxml.jackson.databind.JsonMappingException;
   import com.fasterxml.jackson.databind.JsonNode;
   import com.fasterxml.jackson.databind.ObjectMapper;
   import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
   import software.amazon.awssdk.regions.Region;
   import software.amazon.awssdk.services.rekognition.RekognitionClient;
   import software.amazon.awssdk.services.rekognition.model.StartLabelDetectionResponse;
   import software.amazon.awssdk.services.rekognition.model.NotificationChannel;
   import software.amazon.awssdk.services.rekognition.model.S3Object;
   import software.amazon.awssdk.services.rekognition.model.Video;
   import software.amazon.awssdk.services.rekognition.model.StartLabelDetectionRequest;
   import software.amazon.awssdk.services.rekognition.model.GetLabelDetectionRequest;
   import software.amazon.awssdk.services.rekognition.model.GetLabelDetectionResponse;
   import software.amazon.awssdk.services.rekognition.model.RekognitionException;
   import software.amazon.awssdk.services.rekognition.model.LabelDetectionSortBy;
   import software.amazon.awssdk.services.rekognition.model.VideoMetadata;
   import software.amazon.awssdk.services.rekognition.model.LabelDetection;
   import software.amazon.awssdk.services.rekognition.model.Label;
   import software.amazon.awssdk.services.rekognition.model.Instance;
   import software.amazon.awssdk.services.rekognition.model.Parent;
   import software.amazon.awssdk.services.sqs.SqsClient;
   import software.amazon.awssdk.services.sqs.model.Message;
   import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
   import software.amazon.awssdk.services.sqs.model.DeleteMessageRequest;
   import java.util.List;
   //snippet-end:[rekognition.java2.recognize_video_detect.import]
   
   /**
   * Before running this Java V2 code example, set up your development environment, including your credentials.
   *
   * For more information, see the following documentation topic:
   *
   * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
   */
   public class VideoDetect {
   
    private static String startJobId ="";
    public static void main(String[] args) {
   
        final String usage = "\n" +
            "Usage: " +
            "   <bucket> <video> <queueUrl> <topicArn> <roleArn>\n\n" +
            "Where:\n" +
            "   bucket - The name of the bucket in which the video is located (for example, (for example, amzn-s3-demo-bucket). \n\n"+
            "   video - The name of the video (for example, people.mp4). \n\n" +
            "   queueUrl- The URL of a SQS queue. \n\n" +
            "   topicArn - The ARN of the Amazon Simple Notification Service (Amazon SNS) topic. \n\n" +
            "   roleArn - The ARN of the AWS Identity and Access Management (IAM) role to use. \n\n" ;
   
        if (args.length != 5) {
            System.out.println(usage);
            System.exit(1);
        }
   
        String bucket = args[0];
        String video = args[1];
        String queueUrl = args[2];
        String topicArn = args[3];
        String roleArn = args[4];
        Region region = Region.US_WEST_2;
        RekognitionClient rekClient = RekognitionClient.builder()
            .region(region)
            .credentialsProvider(ProfileCredentialsProvider.create("profile-name"))
            .build();
   
        SqsClient sqs = SqsClient.builder()
            .region(Region.US_WEST_2)
            .credentialsProvider(ProfileCredentialsProvider.create("profile-name"))
            .build();
   
        NotificationChannel channel = NotificationChannel.builder()
            .snsTopicArn(topicArn)
            .roleArn(roleArn)
            .build();
   
        startLabels(rekClient, channel, bucket, video);
        getLabelJob(rekClient, sqs,  queueUrl);
        System.out.println("This example is done!");
        sqs.close();
        rekClient.close();
    }
   
    // snippet-start:[rekognition.java2.recognize_video_detect.main]
    public static void startLabels(RekognitionClient rekClient,
                                   NotificationChannel channel,
                                   String bucket,
                                   String video) {
        try {
            S3Object s3Obj = S3Object.builder()
                .bucket(bucket)
                .name(video)
                .build();
   
            Video vidOb = Video.builder()
                .s3Object(s3Obj)
                .build();
   
            StartLabelDetectionRequest labelDetectionRequest = StartLabelDetectionRequest.builder()
                .jobTag("DetectingLabels")
                .notificationChannel(channel)
                .video(vidOb)
                .minConfidence(50F)
                .build();
   
            StartLabelDetectionResponse labelDetectionResponse = rekClient.startLabelDetection(labelDetectionRequest);
            startJobId = labelDetectionResponse.jobId();
   
            boolean ans = true;
            String status = "";
            int yy = 0;
            while (ans) {
   
                GetLabelDetectionRequest detectionRequest = GetLabelDetectionRequest.builder()
                    .jobId(startJobId)
                    .maxResults(10)
                    .build();
   
                GetLabelDetectionResponse result = rekClient.getLabelDetection(detectionRequest);
                status = result.jobStatusAsString();
   
                if (status.compareTo("SUCCEEDED") == 0)
                    ans = false;
                else
                    System.out.println(yy +" status is: "+status);
   
                Thread.sleep(1000);
                yy++;
            }
   
            System.out.println(startJobId +" status is: "+status);
   
        } catch(RekognitionException | InterruptedException e) {
            e.getMessage();
            System.exit(1);
        }
    }
   
    public static void getLabelJob(RekognitionClient rekClient, SqsClient sqs, String queueUrl) {
   
        List<Message> messages;
        ReceiveMessageRequest messageRequest = ReceiveMessageRequest.builder()
            .queueUrl(queueUrl)
            .build();
   
        try {
            messages = sqs.receiveMessage(messageRequest).messages();
   
            if (!messages.isEmpty()) {
                for (Message message: messages) {
                    String notification = message.body();
   
                    // Get the status and job id from the notification
                    ObjectMapper mapper = new ObjectMapper();
                    JsonNode jsonMessageTree = mapper.readTree(notification);
                    JsonNode messageBodyText = jsonMessageTree.get("Message");
                    ObjectMapper operationResultMapper = new ObjectMapper();
                    JsonNode jsonResultTree = operationResultMapper.readTree(messageBodyText.textValue());
                    JsonNode operationJobId = jsonResultTree.get("JobId");
                    JsonNode operationStatus = jsonResultTree.get("Status");
                    System.out.println("Job found in JSON is " + operationJobId);
   
                    DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
                        .queueUrl(queueUrl)
                        .build();
   
                    String jobId = operationJobId.textValue();
                    if (startJobId.compareTo(jobId)==0) {
                        System.out.println("Job id: " + operationJobId );
                        System.out.println("Status : " + operationStatus.toString());
   
                        if (operationStatus.asText().equals("SUCCEEDED"))
                            GetResultsLabels(rekClient);
                        else
                            System.out.println("Video analysis failed");
   
                        sqs.deleteMessage(deleteMessageRequest);
                    }
   
                    else{
                        System.out.println("Job received was not job " +  startJobId);
                        sqs.deleteMessage(deleteMessageRequest);
                    }
                }
            }
   
        } catch(RekognitionException e) {
            e.getMessage();
            System.exit(1);
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
   
    // Gets the job results by calling GetLabelDetection
    private static void GetResultsLabels(RekognitionClient rekClient) {
   
        int maxResults=10;
        String paginationToken=null;
        GetLabelDetectionResponse labelDetectionResult=null;
   
        try {
            do {
                if (labelDetectionResult !=null)
                    paginationToken = labelDetectionResult.nextToken();
   
   
                GetLabelDetectionRequest labelDetectionRequest= GetLabelDetectionRequest.builder()
                    .jobId(startJobId)
                    .sortBy(LabelDetectionSortBy.TIMESTAMP)
                    .maxResults(maxResults)
                    .nextToken(paginationToken)
                    .build();
   
                labelDetectionResult = rekClient.getLabelDetection(labelDetectionRequest);
                VideoMetadata videoMetaData=labelDetectionResult.videoMetadata();
                System.out.println("Format: " + videoMetaData.format());
                System.out.println("Codec: " + videoMetaData.codec());
                System.out.println("Duration: " + videoMetaData.durationMillis());
                System.out.println("FrameRate: " + videoMetaData.frameRate());
   
                List<LabelDetection> detectedLabels= labelDetectionResult.labels();
                for (LabelDetection detectedLabel: detectedLabels) {
                    long seconds=detectedLabel.timestamp();
                    Label label=detectedLabel.label();
                    System.out.println("Millisecond: " + seconds + " ");
   
                    System.out.println("   Label:" + label.name());
                    System.out.println("   Confidence:" + detectedLabel.label().confidence().toString());
   
                    List<Instance> instances = label.instances();
                    System.out.println("   Instances of " + label.name());
   
                    if (instances.isEmpty()) {
                        System.out.println("        " + "None");
                    } else {
                        for (Instance instance : instances) {
                            System.out.println("        Confidence: " + instance.confidence().toString());
                            System.out.println("        Bounding box: " + instance.boundingBox().toString());
                        }
                    }
                    System.out.println("   Parent labels for " + label.name() + ":");
                    List<Parent> parents = label.parents();
   
                    if (parents.isEmpty()) {
                        System.out.println("        None");
                    } else {
                        for (Parent parent : parents) {
                            System.out.println("   " + parent.name());
                        }
                    }
                    System.out.println();
                }
            } while (labelDetectionResult !=null && labelDetectionResult.nextToken() != null);
   
        } catch(RekognitionException e) {
            e.getMessage();
            System.exit(1);
        }
    }
    // snippet-end:[rekognition.java2.recognize_video_detect.main]
   }
   ```

------

1. 建置並執行程式碼。此操作可能需要一些時間來完成。完成之後，將顯示在影片中偵測到的標籤清單。如需詳細資訊，請參閱[偵測影片中的標籤](labels-detecting-labels-video.md)。

# 使用 分析影片 AWS Command Line Interface
<a name="video-cli-commands"></a>

您可以使用 AWS Command Line Interface (AWS CLI) 來呼叫 Amazon Rekognition Video 操作。設計模式與搭配 適用於 Java 的 AWS SDK 或其他 AWS SDKs使用 Amazon Rekognition Video API 相同。如需詳細資訊，請參閱[Amazon Rekognition Video API 概觀](video.md#video-api-overview)。下列程序說明如何使用 AWS CLI 來偵測影片中的標籤。

呼叫 `start-label-detection` 來開始偵側影片中的標籤。當 Amazon Rekognition 完成影片分析時，完成狀態會傳送到 `start-label-detection` 的 `--notification-channel` 參數中所指定的 Amazon SNS 主題。您可以透過訂閱 Amazon Simple Queue Service (Amazon SQS) 佇列到 Amazon SNS 主题來取得完成狀態。接著輪詢[接收訊息](https://docs.aws.amazon.com/cli/latest/reference/sqs/receive-message.html)，以自 Amazon SQS 佇列取得完成狀態。

呼叫 `StartLabelDetection` 時，您可以透過向 `LabelsInclusionFilter` 和/或 `LabelsExclusionFilter` 參數提供過濾參數來過濾結果。如需詳細資訊，請參閱 [偵測影片中的標籤](labels-detecting-labels-video.md)。

完成狀態通知的為 `receive-message` 回應內的 JSON 結構。您需要自回應中擷取出 JSON。如需完成狀態 JSON 的相關資訊，請參閱 [參考：影片分析結果通知](video-notification-payload.md)。如果已完整狀態 JSON 的 `Status` 欄位值為 `SUCCEEDED`，您可以呼叫 `get-label-detection` 來取得影片分析請求的結果。呼叫 `GetLabelDetection` 時，您可以使用 `SortBy` 和 `AggregateBy` 引數來排序和彙總傳回的結果。

以下程序不包含用以輪詢 Amazon SQS 佇列的程式碼。此外也不包含用於剖析自 Amazon SQS 佇列傳回的 JSON 之程式碼。如需 Java 範例，請參閱 [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md)。

## 先決條件
<a name="video-prerequisites"></a>

若要執行此程序，您需要 AWS CLI 安裝 。如需詳細資訊，請參閱[Amazon Rekognition 入門](getting-started.md)。您使用的 AWS 帳戶必須有 Amazon Rekognition API 的存取許可。如需詳細資訊，請參閱 [Amazon Rekognition 定義的動作](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonrekognition.html#amazonrekognition-actions-as-permissions)。

**若要設定 Amazon Rekognition Video 並上傳影片**

1. 設定使用者對 Amazon Rekognition Video 的存取權限，並設定 Amazon Rekognition Video 對 Amazon SNS 的存取。如需詳細資訊，請參閱 [設定 Amazon Rekognition Video](api-video-roles.md)。

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":"amzn-s3-demo-bucket","Name":"video-name"}}' \
    --notification-channel '{"SNSTopicArn":"TopicARN","RoleArn":"RoleARN"}' \
   --region region-name  \ 
   --features GENERAL_LABELS \
   --profile profile-name \
   --settings "{"GeneralLabels":{"LabelInclusionFilters":["Car"]}}
   ```

   更新下列的值：
   + 將 `amzn-s3-demo-bucket` 與 `videofile` 變更為您在步驟 2 中指定的 Amazon S3 儲存貯體與文檔名稱。
   + 將 `us-east-1` 變更為您正在使用的 AWS 區域。
   + 將建立 Rekognition 工作階段的行中 `profile_name` 值取代為您開發人員設定檔的名稱。
   + 將 `TopicARN` 變更為您在 [設定 Amazon Rekognition Video](api-video-roles.md) 步驟 3 建立的 Amazon SNS 主題 ARN。
   + 將 `RoleARN` 變更為您在步驟 7 建立的 [設定 Amazon Rekognition Video](api-video-roles.md) IAM 服務角色的 ARN。
   + 如有需要，可以指定 `endpoint-url`。AWS CLI 應根據提供的區域自動判斷適當的端點 URL。但是，如果您使用[私有 VPC 中](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html#what-is-privatelink)的端點，則可能需要指定 `endpoint-url`。[AWS 服務端點](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints)資源會列出指定端點 URL 的語法，以及每個區域的名稱和程式碼。
   + 您還可以在設定參數中包括過濾條件。例如，您可以在所需值的清單之外，邊使用 `LabelsInclusionFilter` 或 `LabelsExclusionFilter`。

    如果您在 Windows 裝置上存取 CLI，請使用雙引號而非單引號，並以反斜線 (即\$1) 替代內部雙引號，以解決您可能遇到的任何剖析器錯誤。如需範例，請參閱下列內容：

   ```
   aws rekognition start-label-detection --video "{\"S3Object\":{\"Bucket\":\"amzn-s3-demo-bucket",\"Name\":\"video-name\"}}" --notification-channel "{\"SNSTopicArn\":\"TopicARN\",\"RoleArn\":\"RoleARN\"}" \
   --region us-east-1 --features GENERAL_LABELS --settings "{\"GeneralLabels\":{\"LabelInclusionFilters\":[\"Car\"]}}" --profile profile-name
   ```

1. 請記下回應中的 `JobId` 值。回應看起來類似以下 JSON 範例。

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

1. 編寫程式碼來輪詢 Amazon SQS 佇列以取得完成狀態 JSON (使用[接收訊息](https://docs.aws.amazon.com/cli/latest/reference/sqs/receive-message.html))。

1. 編寫程式碼以自完成狀態 JSON 擷取 `Status` 欄位。

1. 如果 的值`Status`為 `SUCCEEDED`，請執行下列 AWS CLI 命令以顯示標籤偵測結果。

   ```
   aws rekognition get-label-detection  --job-id JobId \
   --region us-east-1 --sort-by TIMESTAMP aggregate-by TIMESTAMPS
   ```

   更新下列的值：
   + 變更 `JobId` 以符合您在步驟 2 中所記下的任務識別碼。
   + 變更 `Endpoint` 和 `us-east-1` 為 AWS 端點與您正在使用的區域。

   結果看起來類似以下 JSON 範例：

   ```
   {
       "Labels": [
           {
               "Timestamp": 0,
               "Label": {
                   "Confidence": 99.03720092773438,
                   "Name": "Speech"
               }
           },
           {
               "Timestamp": 0,
               "Label": {
                   "Confidence": 71.6698989868164,
                   "Name": "Pumpkin"
               }
           },
           {
               "Timestamp": 0,
               "Label": {
                   "Confidence": 71.6698989868164,
                   "Name": "Squash"
               }
           },
           {
               "Timestamp": 0,
               "Label": {
                   "Confidence": 71.6698989868164,
                   "Name": "Vegetable"
               }
           }, .......
   ```

# 參考：影片分析結果通知
<a name="video-notification-payload"></a>

Amazon Rekognition 將 Amazon Rekognition Video 分析請求的結果 (包括完成狀態) 發佈至 Amazon Simple Notification Service (Amazon SNS) 主題。若要從 Amazon SNS 主題取得通知，請使用 Amazon Simple Queue Service 佇列或 AWS Lambda 函數。如需詳細資訊，請參閱[呼叫 Amazon Rekognition Video 操作](api-video.md)。如需範例，請參閱 [使用 Java 或 Python (SDK) 分析儲存於 Amazon S3 儲存貯體中的影片](video-analyzing-with-sqs.md)。

承載內容以下方 JSON 格式顯示：

```
{
  "JobId": "String",
  "Status": "String",
  "API": "String",
  "JobTag": "String",
  "Timestamp": Number,
  "Video": {
    "S3ObjectName": "String",
    "S3Bucket": "String"
  }
}
```


| 名稱 | 描述 | 
| --- | --- | 
|  JobId  |  任務識別碼。符合自 `Start` 操作傳回的任務識別碼，例如 [StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html)。  | 
|  狀態  |  任務的狀態。有效值為「SUCCEEDED」(成功)、「FAILED」(失敗) 或「ERROR」(錯誤)。  | 
|  API  |  用於分析輸入影片的 Amazon Rekognition Video 操作。  | 
|  JobTag  |  任務的識別碼。在呼叫中指定 `JobTag` 以開始操作，例如 [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html)。  | 
|  時間戳記  |  顯示任務完成的 Unix 時間戳記。  | 
|  影片  |  已完成處理的影片詳細資訊。包含檔案名稱與檔案所存放的 Amazon S3 儲存貯體。  | 

以下為傳送到 Amazon SNS 主題的成功通知範例。

```
{
  "JobId": "6de014b0-2121-4bf0-9e31-856a18719e22",
  "Status": "SUCCEEDED",
  "API": "LABEL_DETECTION",
  "Message": "",
  "Timestamp": 1502230160926,
  "Video": {
    "S3ObjectName": "video.mpg",
    "S3Bucket": "amzn-s3-demo-bucket"
  }
}
```

# 對 Amazon Rekognition Video 進行疑難排解
<a name="video-troubleshooting"></a>

以下內容涵蓋使用 Amazon Rekognition Video 與已儲存影片時的疑難排解資訊。

## 我都沒有收到傳送至 Amazon SNS 主題的完成狀態訊息
<a name="video-no-sns-topic"></a>

 當影片分析完成時，Amazon Rekognition Video 會將狀態資訊發佈至 ​Amazon SNS 主題。一般而言，您可以使用 Amazon SQS​ 佇列或 Lambda 函數​來訂閱主題，以取得完成狀態訊息。為順利進行調查，您可以透過電子郵件訂閱 Amazon SNS 主題。如此，電子郵件收件匣即會收到傳送至 Amazon SNS 主題的訊息。如需詳細資訊，請參閱[訂閱 Amazon SNS 主題](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html)。

如果您的應用程式沒有收到該訊息，請考慮下列情況：
+ 請確認分析已完成。請檢查取得操作中的 `JobStatus` 值 (例如，`GetLabelDetection`)。如果該值為 `IN_PROGRESS`，表示分析尚未完成，而完成狀態也尚未發布至 Amazon SNS 主題。
+ 請確認您擁有 IAM 服務角色，以授予 Amazon Rekognition Video​ 發佈至 Amazon SNS​​ 主題的許可。如需詳細資訊，請參閱 [設定 Amazon Rekognition Video](api-video-roles.md)。
+ 確認您正在使用的 IAM 服務角色可以使用角色憑證發佈到 Amazon SNS 主題，並確認服務角色的許可範圍安全地限於您正在使用的資源。執行以下步驟：
  + 取得使用者的 Amazon Resource Name (ARN)：

    ```
    aws sts get-caller-identity --profile RekognitionUser 
    ```
  + 將使用者 ARN 新增至角色信任關係。如需詳細資訊，請參閱[修改角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_manage_modify.html)。下列範例信任原則會指定使用者的角色憑證，並將服務角色的權限限制為您正在使用的資源 (如需有關安全地限制服務角色權限範圍的詳細資訊，請參閱 [預防跨服務混淆代理人](cross-service-confused-deputy-prevention.md))：
  + 假設該角色：`aws sts assume-role --role-arn arn:Role ARN --role-session-name SessionName --profile RekognitionUser`
  + 發佈至 Amazon SNS 主題。`aws sns publish --topic-arn arn:Topic ARN --message "Hello World!" --region us-east-1 --profile RekognitionUser`

  如果 AWS CLI 命令有效，您會收到訊息 （如果您已透過電子郵件訂閱主題，請在電子郵件收件匣中）。如果您沒有收到該訊息：
  + 確認您已設定 Amazon Rekognition Video。如需詳細資訊，請參閱 [設定 Amazon Rekognition Video](api-video-roles.md)。
  + 請查看對此問題執行故障排除的其他秘訣。
+ 確認您使用的是正確的 Amazon SNS 主題：
  + 如果您使用 IAM 服務角色來授予 Amazon Rekognition Video 存取單一 Amazon SNS 主題的權限，請確認取得許可的 Amazon SNS 主題正確無誤。如需詳細資訊，請參閱 [提供存取目前 Amazon SNS 主題的權限](api-video-roles.md#api-video-roles-single-topics)。
  + 如果您使用 IAM 服務角色來授予 Amazon Rekognition Video 存取多個 SNS 主題的權限，則請確認您使用的是正確主題，且該主題名稱以 *AmazonRekognition* 為開頭。如需詳細資訊，請參閱[提供對多個 Amazon SNS 主題的存取權限](api-video-roles.md#api-video-roles-all-topics)。
  + 如果您使用 AWS Lambda 函數，請確認您的 Lambda 函數已訂閱正確的 Amazon SNS 主題。如需更多資訊，請參閱 [Fanout 至 Lambda 函數 ](https://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html)。
+ 如果 ​Amazon SQS 佇列成功訂閱 ​Amazon SNS 主題，請確定 Amazon SNS​ 主題擁有傳送訊息至 ​Amazon SQS 佇列的許可。如需更多資訊，請參閱[提供許可給 Amazon SNS 主題，以傳送訊息至 Amazon SQS 佇列](https://docs.aws.amazon.com/sns/latest/dg/subscribe-sqs-queue-to-sns-topic.html#SendMessageToSQS.sqs.permissions)。

## 我需要其他協助針對 Amazon SNS 主題進行疑難排解
<a name="video-troubleshoot-sns"></a>

您可以使用 AWS X-Ray 搭配 Amazon SNS 來追蹤和分析透過應用程式傳遞的訊息。如需詳細資訊，請參閱 [Amazon SNS 和 AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-services-sns.html) 。

如需其他協助，您可以將您的問題張貼到 [Amazon Rekognition 論壇](https://forums.aws.amazon.com/forum.jspa?forumID=234)，或考慮註冊取得[AWS 技術支援](https://aws.amazon.com/premiumsupport/)。