

# Working with stored video analysis operations
<a name="video"></a>

Amazon Rekognition Video is an API that you can use to analyze videos. With Amazon Rekognition Video, you can detect labels, faces, people, celebrities, and adult (suggestive and explicit) content in videos that are stored in an Amazon Simple Storage Service (Amazon S3) bucket. You can use Amazon Rekognition Video in categories such as media/entertainment and public safety. Previously, scanning videos for objects or people would have taken many hours of error-prone viewing by a human being. Amazon Rekognition Video automates the detection of items and when they occur throughout a video.

This section covers the types of analysis that Amazon Rekognition Video can perform, an overview of the API, and examples for using Amazon Rekognition Video.

**Topics**
+ [Types of analysis](#video-recognition-types)
+ [Amazon Rekognition Video API overview](#video-api-overview)
+ [Calling Amazon Rekognition Video operations](api-video.md)
+ [Configuring Amazon Rekognition Video](api-video-roles.md)
+ [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md)
+ [Analyzing a video with the AWS Command Line Interface](video-cli-commands.md)
+ [Reference: Video analysis results notification](video-notification-payload.md)
+ [Troubleshooting Amazon Rekognition Video](video-troubleshooting.md)

## Types of analysis
<a name="video-recognition-types"></a>

You can use Amazon Rekognition Video to analyze videos for the following information:
+ [Video Segments](segments.md)
+ [Labels](labels.md)
+ [Suggestive and explicit adult content](moderation.md)
+ [Text](text-detection.md)
+ [Celebrities](celebrities.md)
+ [Faces](faces.md)
+ [People](persons.md)

For more information, see [How Amazon Rekognition works](how-it-works.md).

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

Amazon Rekognition Video processes a video that's stored in an Amazon S3 bucket. The design pattern is an asynchronous set of operations. You start video analysis by calling a `Start` operation such as [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html). The completion status of the request is published to an Amazon Simple Notification Service (Amazon SNS) topic. To get the completion status from the Amazon SNS topic, you can use an Amazon Simple Queue Service (Amazon SQS) queue or an AWS Lambda function. After you have the completion status, you call a `Get` operation, such as [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html), to get the results of the request. 

The following diagram shows the process for detecting labels in a video that's stored in an Amazon S3 bucket. In the diagram, an Amazon SQS queue gets the completion status from the Amazon SNS topic. Alternatively, you can use an AWS Lambda function. 

![\[Flow diagram depicting the steps for video analysis using Amazon Rekognition Video, Amazon SNS, and Amazon SQS, with components like StartLabelDetection, GetLabelDetection job, and publishing completion status to respective queues.\]](http://docs.aws.amazon.com/rekognition/latest/dg/images/VideoRekognition.png)


The process is the same for other Amazon Rekognition Video operations. The following table lists the `Start` and `Get` operations for each of the non-storage Amazon Rekognition operations.


| Detection | Start Operation | Get Operation | 
| --- | --- | --- | 
|  Video Segments  |  [StartSegmentDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartSegmentDetection.html)  |  [GetSegmentDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetSegmentDetection.html)  | 
|  Labels  |  [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html)  |  [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html)  | 
|  Explicit or suggestive adult content  |  [StartContentModeration](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartContentModeration.html)  |  [GetContentModeration](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetContentModeration.html)  | 
|  Text  |  [StartTextDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartTextDetection.html)  |  [GetTextDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetTextDetection.html)  | 
|  Celebrities  |  [StartCelebrityRecognition](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartCelebrityRecognition.html)  |  [GetCelebrityRecognition](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetCelebrityRecognition.html)  | 
|  Faces  |  [StartFaceDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartFaceDetection.html)  |  [GetFaceDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetFaceDetection.html)  | 
|  People  |  [StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html)  |  [GetPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetPersonTracking.html)  | 

For `Get` operations other than `GetCelebrityRecognition`, Amazon Rekognition Video returns tracking information for when entities are detected throughout the input video.

For more information about using Amazon Rekognition Video, see [Calling Amazon Rekognition Video operations](api-video.md). For an example that does video analysis by using Amazon SQS, see [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md). For AWS CLI examples, see [Analyzing a video with the AWS Command Line Interface](video-cli-commands.md).

### Video formats and storage
<a name="video-storage-formats"></a>

Amazon Rekognition operations can analyze videos that are stored in Amazon S3 buckets. For a list of all limits on video analysis operation, see [Guidelines and quotas in Amazon Rekognition](limits.md).

The video must be encoded using the H.264 codec. The supported file formats are MPEG-4 and MOV. 

A codec is software or hardware that compresses data for faster delivery and decompresses received data into its original form. The H.264 codec is commonly used for recording, compressing, and distributing video content. A video file format can contain one or more codecs. If your MOV or MPEG-4 format video file doesn't work with Amazon Rekognition Video, check that the codec used to encode the video is H.264. 

Any Amazon Rekognition Video API that analyzes audio data only supports AAC audio codecs.

The maximum file size for a stored video is 10GB.

### Searching for people
<a name="video-searching-persons-overview"></a>

You can use facial metadata that's stored in a collection to search for people in a video. For example, you can search an archived video for a specific person or for multiple people. You store facial metadata from source images in a collection by using the [IndexFaces](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_IndexFaces.html) operation. You can then use [StartFaceSearch](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartFaceSearch.html) to start asynchronously searching for faces in the collection. You use [GetFaceSearch](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GeFaceSearch.html) to get the search results. For more information, see [Searching stored videos for faces](procedure-person-search-videos.md). Searching for people is an example of a storage-based Amazon Rekognition operation. For more information, see [Storage-based API operations](how-it-works-storage-non-storage.md#how-it-works-storage-based).

You can also search for people in a streaming video. For more information, see [Working with streaming video events](streaming-video.md).

# Calling Amazon Rekognition Video operations
<a name="api-video"></a>

Amazon Rekognition Video is an asynchronous API that you can use to analyze videos that are stored in an Amazon Simple Storage Service (Amazon S3) bucket. You start the analysis of a video by calling an Amazon Rekognition Video `Start` operation, such as [StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html). Amazon Rekognition Video publishes the result of the analysis request to an Amazon Simple Notification Service (Amazon SNS) topic. You can use an Amazon Simple Queue Service (Amazon SQS) queue or an AWS Lambda function to get the completion status of the video analysis request from the Amazon SNS topic. Finally, you get the video analysis request results by calling an Amazon Rekognition `Get` operation, such as [GetPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetPersonTracking.html). 

The information in the following sections uses label detection operations to show how Amazon Rekognition Video detects labels (objects, events, concepts, and activities) in a video that's stored in an Amazon S3 bucket. The same approach works for the other Amazon Rekognition Video operations—for example, [StartFaceDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartFaceDetection.html) and [StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html). The example [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md) shows how to analyze a video by using an Amazon SQS queue to get the completion status from the Amazon SNS topic. It's also used as a basis for other Amazon Rekognition Video examples, such as [People pathing](persons.md). For AWS CLI examples, see [Analyzing a video with the AWS Command Line Interface](video-cli-commands.md).

**Topics**
+ [Starting video analysis](#api-video-start)
+ [Getting the completion status of an Amazon Rekognition Video analysis request](#api-video-get-status)
+ [Getting Amazon Rekognition Video analysis results](#api-video-get)

## Starting video analysis
<a name="api-video-start"></a>

You start an Amazon Rekognition Video label detection request by calling [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html). The following is an example of a JSON request that's passed by `StartLabelDetection`.

```
{
    "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"
}
```

The input parameter `Video` provides the video file name and the Amazon S3 bucket to retrieve it from. `NotificationChannel` contains the Amazon Resource Name (ARN) of the Amazon SNS topic that Amazon Rekognition Video notifies when the video analysis request finishes. The Amazon SNS topic must be in the same AWS region as the Amazon Rekognition Video endpoint that you're calling. `NotificationChannel` also contains the ARN for a role that allows Amazon Rekognition Video to publish to the Amazon SNS topic. You give Amazon Rekognition publishing permissions to your Amazon SNS topics by creating an IAM service role. For more information, see [Configuring Amazon Rekognition Video](api-video-roles.md).

You can also specify an optional input parameter, `JobTag`, that allows you to identify the job in the completion status that's published to the Amazon SNS topic. 

To prevent accidental duplication of analysis jobs, you can optionally provide an idempotent token, `ClientRequestToken`. If you supply a value for `ClientRequestToken`, the `Start` operation returns the same `JobId` for multiple identical calls to the start operation, such as `StartLabelDetection`. A `ClientRequestToken` token has a lifetime of 7 days. After 7 days, you can reuse it. If you reuse the token during the token lifetime, the following happens: 
+ If you reuse the token with the same `Start` operation and the same input parameters, the same `JobId` is returned. The job is not performed again and Amazon Rekognition Video does not send a completion status to the registered Amazon SNS topic.
+ If you reuse the token with the same `Start` operation and a minor input parameter change, you get an `IdempotentParameterMismatchException` (HTTP status code: 400) exception raised.
+ You shoudn’t reuse a token with different `Start` operations as you’ll get unpredictable results from Amazon Rekognition.

The response to the `StartLabelDetection` operation is a job identifier (`JobId`). Use `JobId` to track requests and get the analysis results after Amazon Rekognition Video has published the completion status to the Amazon SNS topic. For example:

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

If you start too many jobs concurrently, calls to `StartLabelDetection` raise a `LimitExceededException` (HTTP status code: 400) until the number of concurrently running jobs is below the Amazon Rekognition service limit. 

If you find that `LimitExceededException` exceptions are raised with bursts of activity, consider using an Amazon SQS queue to manage incoming requests. Contact AWS support if you find that your average number of concurrent requests cannot be managed by an Amazon SQS queue and you are still receiving `LimitExceededException` exceptions. 

## Getting the completion status of an Amazon Rekognition Video analysis request
<a name="api-video-get-status"></a>

Amazon Rekognition Video sends an analysis completion notification to the registered Amazon SNS topic. The notification includes the job identifier and the completion status of the operation in a JSON string. A successful video analysis request has a `SUCCEEDED` status. For example, the following result shows the successful processing of a label detection job.

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

For more information, see [Reference: Video analysis results notification](video-notification-payload.md).

To get the status information that's published to the Amazon SNS topic by Amazon Rekognition Video, use one of the following options:
+ **AWS Lambda** – You can subscribe an AWS Lambda function that you write to an Amazon SNS topic. The function is called when Amazon Rekognition notifies the Amazon SNS topic that the request has completed. Use a Lambda function if you want server-side code to process the results of a video analysis request. For example, you might want to use server-side code to annotate the video or create a report on the video contents before returning the information to a client application. We also recommend server-side processing for large videos because the Amazon Rekognition API might return large volumes of data. 
+ **Amazon Simple Queue Service** – You can subscribe an Amazon SQS queue to an Amazon SNS topic. You then poll the Amazon SQS queue to retrieve the completion status that's published by Amazon Rekognition when a video analysis request completes. For more information, see [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md). Use an Amazon SQS queue if you want to call Amazon Rekognition Video operations only from a client application. 

**Important**  
We don't recommend getting the request completion status by repeatedly calling the Amazon Rekognition Video `Get` operation. This is because Amazon Rekognition Video throttles the `Get` operation if too many requests are made. If you're processing multiple videos concurrently, it's simpler and more efficient to monitor one SQS queue for the completion notification than to poll Amazon Rekognition Video for the status of each video individually.

## Getting Amazon Rekognition Video analysis results
<a name="api-video-get"></a>

 To get the results of a video analysis request, first ensure that the completion status that's retrieved from the Amazon SNS topic is `SUCCEEDED`. Then call `GetLabelDetection`, which passes the `JobId` value that's returned from `StartLabelDetection`. The request JSON is similar to the following example:

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

JobId is the identifier for the video analysis operation. Because video analysis can generate large amounts of data, use `MaxResults` to specify the maximum number of results to return in a single Get operation. The default value for `MaxResults` is 1000. If you specify a value greater than 1000, a maximum of 1000 results is returned. If the operation doesn't return the entire set of results, a pagination token for the next page is returned in the operation response. If you have a pagination token from a previous Get request, use it with `NextToken` to get the next page of results.

**Note**  
Amazon Rekognition retains the results of a video analysis operation for 7 days. You will not be able to retrieve the analysis results after this time.

The `GetLabelDetection` operation response JSON is similar to the following:

```
{
    "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
    }
}
```

The `GetLabelDetection` and `GetContentModeration` operations allow you to sort the analysis results by timestamp or by label name. You can also aggregate results by video segment or by timestamp. 

You can sort the results by detection time (milliseconds from the start of the video) or alphabetically by the detected entity (object, face, celebrity, moderation label, or person). To sort by time, set the value of the `SortBy` input parameter to `TIMESTAMP`. If `SortBy` isn't specified, the default behavior is to sort by time. The preceding example is sorted by time. To sort by entity, use the `SortBy` input parameter with the value that's appropriate for the operation you're performing. For example, to sort by detected label in a call to `GetLabelDetection`, use the value `NAME`.

To aggregate results by timestamp, set the value of the `AggregateBy` parameter to `TIMESTAMPS`. To aggregate by video segment, set the value of `AggregateBy` to `SEGMENTS`. `SEGMENTS` aggregation mode will aggregate the labels over time, while `TIMESTAMPS` gives the timestamp a label was detected at, using 2 FPS sampling and per frame output (Note: This current sampling rate is subject to change, assumptions shouldn't be made about the current sampling rate). If no value is specified, the default aggregation method is `TIMESTAMPS`. 

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

To use the Amazon Rekognition Video API with stored videos, you have to configure the user and an IAM service role to access your Amazon SNS topics. You also have to subscribe an Amazon SQS queue to your Amazon SNS topics. 

**Note**  
If you're using these instructions to set up the [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md) example, you don't need to do steps 3, 4, 5, and 6. The example includes code to create and configure the Amazon SNS topic and Amazon SQS queue.

The examples in this section create a new Amazon SNS topic by using the instructions that give Amazon Rekognition Video access to multiple topics. If you want to use an existing Amazon SNS topic, use [Giving access to an existing Amazon SNS topic](#api-video-roles-single-topics) for step 3.<a name="configure-rekvid-procedure"></a>

**To configure Amazon Rekognition Video**

1. Set up an AWS account to access Amazon Rekognition Video. For more information, see [Step 1: Set up an AWS account and create a User](setting-up.md).

1. Install and configure the required AWS SDK. For more information, see [Step 2: Set up the AWS CLI and AWS SDKs](setup-awscli-sdk.md). 

1. To run the code examples in this developer guide, ensure that your chosen user has programmatic access. See [Grant programmatic access](sdk-programmatic-access.md) for more information.

   Your user also needs at least the following permissions:
   + AmazonSQSFullAccess
   + AmazonRekognitionFullAccess
   + AmazonS3FullAccess
   + AmazonSNSFullAccess

   If you're using IAM Identity Center to authenticate, add the permissions to the permission set for your role, otherwise add the permissions to your IAM role.

1. [Create an Amazon SNS topic](https://docs.aws.amazon.com/sns/latest/dg/CreateTopic.html) by using the [Amazon SNS console](https://console.aws.amazon.com/sns/v2/home). Prepend the topic name with *AmazonRekognition*. Note the topic Amazon Resource Name (ARN). Ensure the topic is in the same region as the AWS endpoint that you are using.

1. [Create an Amazon SQS standard queue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html) by using the [Amazon SQS console](https://console.aws.amazon.com/sqs/). Note the queue ARN.

1. [Subscribe the queue to the topic](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-subscribe-queue-sns-topic.html) you created in step 3.

1. [Give permission to the Amazon SNS topic to send messages to the Amazon SQS queue](https://docs.aws.amazon.com/sns/latest/dg/SendMessageToSQS.html#SendMessageToSQS.sqs.permissions).

1. Create an IAM service role to give Amazon Rekognition Video access to your Amazon SNS topics. Note the Amazon Resource Name (ARN) of the service role. For more information, see [Giving access to multiple Amazon SNS topics](#api-video-roles-all-topics).

1. To ensure your account is secure, you will want to limit the scope of Rekognition's access to just the resources you are using. This can be done by attaching a Trust policy to your IAM service role. For information on how to do this, see [Cross-service confused deputy prevention](cross-service-confused-deputy-prevention.md).

1. [ Add the following inline policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#embed-inline-policy-console) to the user that you created in step 1: 

   Give the inline policy a name of your choosing.

1. If you use a customer managed AWS Key Management Service key to encrypt the videos in your Amazon S3 bucket, [add](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-modifying.html#key-policy-modifying-how-to-console-policy-view) permissions to the key that allow the service role you created in step 7 to decrypt the videos. At a minimum the service role needs permission for `kms:GenerateDataKey` and `kms:Decrypt` actions. For example:

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

   For more information, see see [My Amazon S3 bucket has default encryption using a custom AWS KMS key. How can I allow users to download from and upload to the bucket?](https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-access-default-encryption/) and [Protecting Data Using Server-Side Encryption with KMS keys Stored in AWS Key Management Service (SSE-KMS)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html). 

1. You can now run the examples in [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md) and [Analyzing a video with the AWS Command Line Interface](video-cli-commands.md).

## Giving access to multiple Amazon SNS topics
<a name="api-video-roles-all-topics"></a>

You use an IAM service role to give Amazon Rekognition Video access to Amazon SNS topics that you create. IAM provides the *Rekognition* use case for creating an Amazon Rekognition Video service role.

You can give Amazon Rekognition Video access to multiple Amazon SNS topics by using the `AmazonRekognitionServiceRole` permissions policy and prepending the topic names with *AmazonRekognition*—for example, `AmazonRekognitionMyTopicName`. 

**To give Amazon Rekognition Video access to multiple Amazon SNS topics**

1. [Create an IAM service role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html?icmpid=docs_iam_console). Use the following information to create the IAM service role:

   1. Choose **Rekognition** for the service name.

   1. Choose **Rekognition** for the service role use case. You should see the **AmazonRekognitionServiceRole** permissions policy listed. **AmazonRekognitionServiceRole** gives Amazon Rekognition Video access to Amazon SNS topics that are prefixed with *AmazonRekognition*.

   1. Give the service role a name of your choosing.

1. Note the ARN of the service role. You need it to start video analysis operations.

## Giving access to an existing Amazon SNS topic
<a name="api-video-roles-single-topics"></a>

You can create a permissions policy that allows Amazon Rekognition Video access to an existing Amazon SNS topic.

**To give Amazon Rekognition Video access to an existing Amazon SNS topic**

1. [ Create a new permissions policy with the IAM JSON policy editor](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html#access_policies_create-json-editor), and use the following policy. Replace `topicarn` with the Amazon Resource Name (ARN) of the desired Amazon SNS topic.

1. [Create an IAM service role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html?icmpid=docs_iam_console), or update an existing IAM service role. Use the following information to create the IAM service role:

   1. Choose **Rekognition** for the service name.

   1. Choose **Rekognition** for the service role use case.

   1. Attach the permissions policy you created in step 1.

1. Note the ARN of the service role. You need it to start video analysis operations.

# Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)
<a name="video-analyzing-with-sqs"></a>

This procedure shows you how to detect labels in a video by using Amazon Rekognition Video label detection operations, a video stored in an Amazon S3 bucket, and an Amazon SNS topic. The procedure also shows how to use an Amazon SQS queue to get the completion status from the Amazon SNS topic. For more information, see [Calling Amazon Rekognition Video operations](api-video.md). You aren't restricted to using an Amazon SQS queue. For example, you can use an AWS Lambda function to get the completion status. For more information, see [Invoking Lambda functions using Amazon SNS notifications](https://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html).

The example code in this procedure shows you how to do the following:

1. Create the Amazon SNS topic.

1. Create the Amazon SQS queue.

1. Give Amazon Rekognition Video permission to publish the completion status of a video analysis operation to the Amazon SNS topic.

1. Subscribe the Amazon SQS queue to the Amazon SNS topic.

1. Start the video analysis request by calling [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html). 

1. Get the completion status from the Amazon SQS queue. The example tracks the job identifier (`JobId`) that's returned in `StartLabelDetection` and only gets the results for matching job identifiers that are read from the completion status. This is an important consideration if other applications are using the same queue and topic. For simplicity, the example deletes jobs that don't match. Consider adding them to an Amazon SQS dead-letter queue for further investigation.

1. Get and display the video analysis results by calling [GetLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_GetLabelDetection.html).

## Prerequisites
<a name="video-prerequisites"></a>

The example code for this procedure is provided in Java and Python. You need to have the appropriate AWS SDK installed. For more information, see [Getting started with Amazon Rekognition](getting-started.md). The AWS account that you use must have access permissions to the Amazon Rekognition API. For more information, see [Actions Defined by Amazon Rekognition](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonrekognition.html#amazonrekognition-actions-as-permissions). 

**To detect labels in a video**

1. Configure user access to Amazon Rekognition Video and configure Amazon Rekognition Video access to Amazon SNS. For more information, see [Configuring Amazon Rekognition Video](api-video-roles.md). You don't need to do steps 3, 4, 5, and 6 because the example code creates and configures the Amazon SNS topic and Amazon SQS queue. 

1. Upload an MOV or MPEG-4 format video file to an Amazon S3 Bucket. For test purposes, upload a video that's no longer than 30 seconds in length.

   For instructions, see [Uploading Objects into Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UploadingObjectsintoAmazonS3.html) in the *Amazon Simple Storage Service User Guide*.

   

1. Use the following code examples to detect labels in a video. 

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

   In the function `main`:
   + Replace `roleArn` with the ARN of the IAM service role that you created in step 7 of [To configure Amazon Rekognition Video](api-video-roles.md#configure-rekvid-procedure).
   + Replace the values of `amzn-s3-demo-bucket` and `video` with the bucket and video file name that you specified in step 2. 

   ```
   //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 ]

   In the function `main`:
   + Replace `roleArn` with the ARN of the IAM service role that you created in step 7 of [To configure Amazon Rekognition Video](api-video-roles.md#configure-rekvid-procedure).
   + Replace the values of `amzn-s3-demo-bucket` and `video` with the bucket and video file name that you specified in step 2. 
   + Replace the value of `profile_name` in the line that creates the Rekognition session with the name of your developer profile.
   + You can also include filtration criteria in the settings paramter. For example, you can use a `LabelsInclusionFilter` or a `LabelsExclusionFilter` alongside a list of desired values. In the code below, you can uncomment the `Features` and `Settings` section and provide your own values to limit the returned results to just the labels your are interested in.
   + In the call to `GetLabelDetection`, you can provide values for the `SortBy` and `AggregateBy` arguments. To sort by time, set the value of the `SortBy` input parameter to `TIMESTAMP`. To sort by entity, use the `SortBy` input parameter with the value that's appropriate for the operation you're performing. To aggregate results by timestamp, set the value of the `AggregateBy` parameter to `TIMESTAMPS`. To aggregate by video segment, use `SEGMENTS`. 

   In the code example, place the following IAM policy within the quotations marks in the line `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 ]

   In the following sample code:
   + Replace the value of `REGION` with the name of your account's operating region.
   + Replace the value of `amzn-s3-demo-bucket` with the name of the Amazon S3 bucket containing your video file.
   + Replace the value of `videoName` with the name of the video file in your Amazon S3 bucket.
   +  Replace the value of `profile_name` in the line that creates the Rekognition session with the name of your developer profile. 
   + Replace `roleArn` with the ARN of the IAM service role that you created in step 7 of [To configure Amazon Rekognition Video](api-video-roles.md#configure-rekvid-procedure).

   ```
   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 ]

   This code is taken from the AWS Documentation SDK examples GitHub repository. See the full example [here](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. Build and run the code. The operation might take a while to finish. After it's finished, a list of the labels detected in the video is displayed. For more information, see [Detecting labels in a video](labels-detecting-labels-video.md).

# Analyzing a video with the AWS Command Line Interface
<a name="video-cli-commands"></a>

You can use the AWS Command Line Interface (AWS CLI) to call Amazon Rekognition Video operations. The design pattern is the same as using the Amazon Rekognition Video API with the AWS SDK for Java or other AWS SDKs. For more information, see [Amazon Rekognition Video API overview](video.md#video-api-overview). The following procedures show how to use the AWS CLI to detect labels in a video.

You start detecting labels in a video by calling `start-label-detection`. When Amazon Rekognition finishes analyzing the video, the completion status is sent to the Amazon SNS topic that's specified in the `--notification-channel` parameter of `start-label-detection`. You can get the completion status by subscribing an Amazon Simple Queue Service (Amazon SQS) queue to the Amazon SNS topic. You then poll [receive-message](https://docs.aws.amazon.com/cli/latest/reference/sqs/receive-message.html) to get the completion status from the Amazon SQS queue.

When calling `StartLabelDetection`, you can filter your results by providing filtration arguments to the `LabelsInclusionFilter` and/or `LabelsExclusionFilter` arguments. For more information, see [Detecting labels in a video](labels-detecting-labels-video.md) .

The completion status notification is a JSON structure within the `receive-message` response. You need to extract the JSON from the response. For information about the completion status JSON, see [Reference: Video analysis results notification](video-notification-payload.md). If the value of the `Status` field of the completed status JSON is `SUCCEEDED`, you can get the results of the video analysis request by calling `get-label-detection`. When calling `GetLabelDetection`, you can sort and aggregate the returned results using the `SortBy` and `AggregateBy` arguments.

The following procedures don't include code to poll the Amazon SQS queue. Also, they don't include code to parse the JSON that's returned from the Amazon SQS queue. For an example in Java, see [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md). 

## Prerequisites
<a name="video-prerequisites"></a>

To run this procedure, you need to have the AWS CLI installed. For more information, see [Getting started with Amazon Rekognition](getting-started.md). The AWS account that you use must have access permissions to the Amazon Rekognition API. For more information, [Actions Defined by Amazon Rekognition](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonrekognition.html#amazonrekognition-actions-as-permissions). 

**To configure Amazon Rekognition Video and upload a video**

1. Configure user access to Amazon Rekognition Video and configure Amazon Rekognition Video access to Amazon SNS. For more information, see [Configuring Amazon Rekognition Video](api-video-roles.md).

1. Upload an MOV or MPEG-4 format video file to your S3 bucket. While developing and testing, we suggest using short videos no longer than 30 seconds in length.

   For instructions, see [Uploading Objects into Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UploadingObjectsintoAmazonS3.html) in the *Amazon Simple Storage Service User Guide*.

**To detect labels in a video**

1. Run the following AWS CLI command to start detecting labels in a video.

   ```
   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"]}}
   ```

   Update the following values:
   + Change `amzn-s3-demo-bucket` and `videofile` to the Amazon S3 bucket name and file name that you specified in step 2.
   + Change `us-east-1` to the AWS region that you're using.
   + Replace the value of `profile_name` in the line that creates the Rekognition session with the name of your developer profile.
   + Change `TopicARN` to the ARN of the Amazon SNS topic you created in step 3 of [Configuring Amazon Rekognition Video](api-video-roles.md).
   + Change `RoleARN` to the ARN of the IAM service role you created in step 7 of [Configuring Amazon Rekognition Video](api-video-roles.md).
   + If required, you can specify the `endpoint-url`. The AWS CLI should automatically determine the proper endpoint URL based on the provided region. However, if you are using an endpoint [from your private VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html#what-is-privatelink), you may need to specify the `endpoint-url`. The [AWS Service Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) resource lists the syntax for specifying endpoint urls and the names and codes for each region.
   + You can also include filtration criteria in the settings paramter. For example, you can use a `LabelsInclusionFilter` or a `LabelsExclusionFilter` alongside a list of desired values.

    If you are accessing the CLI on a Windows device, use double quotes instead of single quotes and escape the inner double quotes by backslash (i.e. \$1) to address any parser errors you may encounter. For an example, see below: 

   ```
   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. Note the value of `JobId` in the response. The response looks similar to the following JSON example.

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

1. Write code to poll the Amazon SQS queue for the completion status JSON (by using [receive-message](https://docs.aws.amazon.com/cli/latest/reference/sqs/receive-message.html)).

1. Write code to extract the `Status` field from the completion status JSON.

1. If the value of `Status` is `SUCCEEDED`, run the following AWS CLI command to show the label detection results.

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

   Update the following values:
   + Change `JobId` to match the job identifier that you noted in step 2.
   + Change `Endpoint` and `us-east-1` to the AWS endpoint and region that you're using.

   The results look similar to the following example 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"
               }
           }, .......
   ```

# Reference: Video analysis results notification
<a name="video-notification-payload"></a>

Amazon Rekognition publishes the results of an Amazon Rekognition Video analysis request, including completion status, to an Amazon Simple Notification Service (Amazon SNS) topic. To get the notification from an Amazon SNS topic, use an Amazon Simple Queue Service queue or an AWS Lambda function. For more information, see [Calling Amazon Rekognition Video operations](api-video.md). For an example, see [Analyzing a video stored in an Amazon S3 bucket with Java or Python (SDK)](video-analyzing-with-sqs.md).

The payload is in the following JSON format:

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


| Name | Description | 
| --- | --- | 
|  JobId  |  The job identifier. Matches a job identifier that's returned from a `Start` operation, such as [StartPersonTracking](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartPersonTracking.html).  | 
|  Status  |  The status of the job. Valid values are SUCCEEDED, FAILED, or ERROR.  | 
|  API  |  The Amazon Rekognition Video operation used to analyze the input video.  | 
|  JobTag  |  Identifier for the job. You specify `JobTag` in a call to Start operation, such as [StartLabelDetection](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_StartLabelDetection.html).  | 
|  Timestamp  |  The Unix time stamp for when the job finished.  | 
|  Video  |  Details about the video that was processed. Includes the file name and the Amazon S3 bucket that the file is stored in.  | 

The following is an example of a successful notification that was sent to an Amazon SNS topic.

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

# Troubleshooting Amazon Rekognition Video
<a name="video-troubleshooting"></a>

The following covers troubleshooting information for working with Amazon Rekognition Video and stored videos.

## I never receive the completion status that's sent to the Amazon SNS topic
<a name="video-no-sns-topic"></a>

 Amazon Rekognition Video publishes status information to an Amazon SNS topic when video analysis completes. Typically, you get the completion status message by subscribing to the topic with an Amazon SQS queue or Lambda function. To help your investigation, subscribe to the Amazon SNS topic by email so you receive the messages that are sent to your Amazon SNS topic in your email inbox. For more information, see [Subscribing to an Amazon SNS topic](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html).

If you don't receive the message in your application, consider the following:
+ Verify that the analysis has completed. Check the `JobStatus` value in the Get operation response (`GetLabelDetection`, for example). If the value is `IN_PROGRESS`, the analysis isn't complete, and the completion status hasn't yet been published to the Amazon SNS topic.
+ Verify that you have an IAM service role that gives Amazon Rekognition Video permissions to publish to your Amazon SNS topics. For more information, see [Configuring Amazon Rekognition Video](api-video-roles.md). 
+ Confirm that the IAM service role that you're using can publish to the Amazon SNS topic by using role credentials and that your service role's permissions are securely scoped to the resources you are using. Carry out the following steps:
  + Get the user Amazon Resource Name (ARN):

    ```
    aws sts get-caller-identity --profile RekognitionUser 
    ```
  + Add the user ARN to the role trust relationship. For more information, see [Modifying a role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_manage_modify.html). The following example trust policy specifies the user's role credentials and restricts the service role's permissions to just the resources you are using (for more information on securely limiting the scope of a service role's permissions, see [Cross-service confused deputy prevention](cross-service-confused-deputy-prevention.md)):
  + Assume the role: `aws sts assume-role --role-arn arn:Role ARN --role-session-name SessionName --profile RekognitionUser`
  + Publish to the Amazon SNS topic: `aws sns publish --topic-arn arn:Topic ARN --message "Hello World!" --region us-east-1 --profile RekognitionUser`

  If the AWS CLI command works, you receive the message (in your email inbox, if you've subscribed to the topic by email). If you don't receive the message:
  + Check that you've configured Amazon Rekognition Video. For more information, see [Configuring Amazon Rekognition Video](api-video-roles.md).
  + Check the other tips for this troubleshooting question.
+ Check that you're using the correct Amazon SNS topic:
  + If you use an IAM service role to give Amazon Rekognition Video access to a single Amazon SNS topic, check that you've given permissions to the correct Amazon SNS topic. For more information, see [Giving access to an existing Amazon SNS topic](api-video-roles.md#api-video-roles-single-topics).
  + If you use an IAM service role to give Amazon Rekognition Video access to multiple SNS topics, verify that you're using the correct topic and that the topic name is prepended with *AmazonRekognition*. For more information, see [Giving access to multiple Amazon SNS topics](api-video-roles.md#api-video-roles-all-topics). 
  + If you use an AWS Lambda function, confirm that your Lambda function is subscribed to the correct Amazon SNS topic. For more information, see [Fanout to Lambda functions](https://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html).
+ If you subscribe an Amazon SQS queue to your Amazon SNS topic, confirm that your Amazon SNS topic has permissions to send messages to the Amazon SQS queue. For more information, see [Give permission to the Amazon SNS topic to send messages to the Amazon SQS queue](https://docs.aws.amazon.com/sns/latest/dg/subscribe-sqs-queue-to-sns-topic.html#SendMessageToSQS.sqs.permissions).

## I need additional help troubleshooting the Amazon SNS topic
<a name="video-troubleshoot-sns"></a>

You can use AWS X-Ray with Amazon SNS to trace and analyze the messages that travel through your application. For more information, see [Amazon SNS and AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-services-sns.html).

For additional help, you can post your question to the [Amazon Rekognition forum](http://forums.aws.amazon.com/forum.jspa?forumID=234) or consider signing up for [AWS technical support](https://aws.amazon.com/premiumsupport/).