

# Use Amazon Kinesis Video Streams with WebRTC to ingest and store media
<a name="webrtc-ingestion"></a>

Amazon Kinesis Video Streams offers capabilities to stream video and audio in real-time via WebRTC to the cloud for storage, playback, and analytical processing. Customers can use our enhanced WebRTC SDK and cloud APIs to enable real-time streaming, as well as media ingestion to the cloud.

To get started, you can install Amazon Kinesis Video Streams with [WebRTC SDK](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c/tree/Release-WebRTC-Streams-Ingestion-Public-Preview) on any security camera or AWS IoT device with a video sensor and use our [APIs](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_Operations_Amazon_Kinesis_Video_Streams.html) to enable media streaming with sub 1-second latency, as well as ingestion and storage in the cloud. Once ingested, you can access your data through our easy-to-use APIs. Amazon Kinesis Video Streams enables you to playback video for live and on-demand viewing, as well as quickly build applications that take advantage of computer vision and video analytics through integration with Amazon Rekognition Video and SageMaker AI.

**Topics**
+ [API operations](#ingestion-apis)
+ [What is Amazon Kinesis Video Streams with WebRTC ingestion and storage?](getting-started-ingestion.md)
+ [Create a signaling channel](ingestion-create-channel.md)
+ [Create a video stream](ingestion-create-stream.md)
+ [Grant permission](ingestion-grant-permission.md)
+ [Configure destination](configure-ingestion.md)
+ [Ingest media](ingest-media.md)
+ [Playback ingested media](ingestion-view-media.md)
+ [Connect to the storage session](ingestion-initiate.md)
+ [Troubleshoot issues connecting with the storage session](troubleshoot-establish-storage.md)

## API operations
<a name="ingestion-apis"></a>

Use the following API operations to configure Amazon Kinesis Video Streams WebRTC ingestion:
+ [DescribeMappedResourceConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeMappedResourceConfiguration.html)
+ [DescribeMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeMediaStorageConfiguration.html)
+ [JoinStorageSession](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSession.html)
+ [JoinStorageSessionAsViewer](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSessionAsViewer.html)
+ [UpdateMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_UpdateMediaStorageConfiguration.html)

# What is Amazon Kinesis Video Streams with WebRTC ingestion and storage?
<a name="getting-started-ingestion"></a>

Amazon Kinesis Video Streams offers capabilities to stream video and audio in real-time via WebRTC to the cloud for storage, playback, and analytical processing. This topic will provide step-by-step instructions to set up and use our WebRTC SDK and cloud APIs to enable both real-time streaming and media ingestion to the cloud. These instructions include guidance for using the AWS Command Line Interface and the Kinesis Video Streams console.

Before you use Amazon Kinesis Video Streams with WebRTC for the first time, see [Set up an AWS account](set-up-account.md).

## Understanding WebRTC ingestion and storage
<a name="understanding-ingestion"></a>

The following sections explain the different ingestion and storage options available in Kinesis Video Streams with WebRTC.

**Topics**
+ [Master participant only](#master-ptp-only)
+ [Master and viewer participants together](#master-viewer-ptp-together)

### Master participant only
<a name="master-ptp-only"></a>

Master participants first connect to Kinesis Video Streams with WebRTC Signaling via [ConnectAsMaster](ConnectAsMaster.md). Next, they call the [JoinStorageSession](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSession.html) API to have the storage session initiate a WebRTC connection. Once a WebRTC connection is established, media will be ingested to the configured Kinesis video stream. 

![\[Diagram showing WebRTC ingestion flow between master participant, storage session, and stream.\]](http://docs.aws.amazon.com/kinesisvideostreams-webrtc-dg/latest/devguide/images/ingestion-flow.png)


### Master and viewer participants together
<a name="master-viewer-ptp-together"></a>

Viewer participants first connect to Kinesis Video Streams with WebRTC Signaling via [ConnectAsViewer](ConnectAsViewer.md). Next, they call the [JoinStorageSessionAsViewer](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSessionAsViewer.html) API to have the storage session initiate a WebRTC connection. Once a WebRTC connection is established, combined media from the master and all viewer participants will be ingested to the configured Kinesis video stream, as long as the master participant is present.

The storage session combines and forwards all viewer participant’s audio to the master participant. Viewer participants receive combined media from the master participant and audio from any other viewer participants from the storage session.

![\[Diagram showing WebRTC ingestion flow with viewer between master participant, storage session, viewer participant, and stream.\]](http://docs.aws.amazon.com/kinesisvideostreams-webrtc-dg/latest/devguide/images/ingestion-flow-with-viewer.png)


## Establish a WebRTC connection with the storage session
<a name="ingestion-establish-connection"></a>

Since the storage session is within the Amazon network, the storage session will only send `relay` (`TURN`) candidates to participants. If the participant's network allows, `srflx` (`STUN`) candidates can be used to connect to the storage session. In other words, from the perspective of the participant, the local nominated ICE candidate can be `srflx` or `relay`, while the remote ICE candidate is always `relay`.

To optimize connection times, don't send `host` candidates to the storage session. The storage session also requires `Trickle ICE` to be used.

See [Troubleshoot issues connecting with the storage session](troubleshoot-establish-storage.md) to troubleshoot connection issues to the storage session.

# Create a signaling channel
<a name="ingestion-create-channel"></a>

A Kinesis Video Streams with WebRTC signaling channel facilitates the exchange of signaling messages required to establish and maintain peer-to-peer connections between WebRTC clients. It handles the negotiation of Session Description Protocol (SDP) offers and answers for session parameters, as well as the exchange of Interactive Connectivity Establishment (ICE) candidates for network information. 

To create a signaling channel, call the [CreateSignalingChannel](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_CreateSignalingChannel.html) API. This page will show you how to invoke that API using the AWS Management Console, AWS CLI, and one of the AWS SDKs. 

**Important**  
Make note of the channel ARN, you'll need it later.

------
#### [ AWS Management Console ]

Do the following:

1. Open the **Kinesis Video Streams Signaling Channels** console at [https://console.aws.amazon.com/kinesisvideo/home/\$1/signalingChannels](https://console.aws.amazon.com//kinesisvideo/home/#/signalingChannels).

1. Choose **Create signaling channel**.

1. On the **Create a new signaling channel** page, type the name for the signaling channel.

   Leave the default **Time-to-live (Ttl)** value as 60 seconds.

   Choose **Create signaling channel**.

1. Once the signaling channel is created, review the details on the channel's details page.

------
#### [ AWS CLI ]

Verify that you have the AWS CLI installed and configured. For more information, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/).

For installation instructions, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html#getting-started-install-instructions). After installation, [configure the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-new) with credentials and region.

Alternatively, open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information.

Run the following [Create-Signaling-Channel](https://docs.aws.amazon.com//cli/latest/reference/kinesisvideo/create-signaling-channel.html) command using the AWS CLI:

```
aws kinesisvideo create-signaling-channel \
  --channel-name "YourChannelName" \
  --region "us-west-2"
```

The response will look like the following:

```
{ 
    "ChannelARN": "arn:aws:kinesisvideo:us-west-2:123456789012:channel/YourChannelName/1234567890123"
}
```

------
#### [ AWS SDK ]

This code snippet shows you how to create a Kinesis Video Streams with WebRTC signaling channel using the AWS SDK for JavaScript v2. The syntax will differ from other AWS SDKs, but the general flow will be the same. View a complete code example on [GitHub](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/createSignalingChannel.js).

Create the Kinesis Video Streams client. This is the client used to call the `CreateSignalingChannel` API.

```
const clientConfig = {
    accessKeyId: 'YourAccessKey',
    secretAccessKey: 'YourSecretKey',
    region: 'us-west-2'
};
const kinesisVideoClient = new AWS.KinesisVideo(clientConfig);
```

Use the client to call the `CreateSignalingChannel` API.

```
const createSignalingChannelResponse = await kinesisVideoClient
    .createSignalingChannel({
        ChannelName: 'YourChannelName',
    })
    .promise();
```

Print the response.

```
console.log(createSignalingChannelResponse.ChannelARN);
```

The live web page with this code sample is available for use on [GitHub](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html). Input your region, AWS credentials, and the name of your signaling channel. 

Select **Create Channel**.

------

# Create a video stream
<a name="ingestion-create-stream"></a>

Follow these procedures to create a stream that the media will be ingested to. If you have already created the destination stream, skip this step.

**Important**  
WebRTC Ingestion requires a Kinesis video stream with data retention greater than 0. The minimum is 1 hour.

To create a stream, call the [CreateStream](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_CreateStream.html) API using the AWS Management Console, AWS CLI, or one of the AWS SDK’s.

**Important**  
Make note of the stream ARN, you'll need it later.

------
#### [ AWS Management Console ]

Do the following:

1. Open the **Kinesis Video Streams** console at [https://console.aws.amazon.com/kinesisvideo/home/](https://console.aws.amazon.com//kinesisvideo/home/).

1. On the **Video streams** page, choose **Create video stream**.

1. On the **Create a new video stream** page, enter `YourStreamName` for the stream name. Leave the **Default configuration** button selected. 

   This will create a stream with a greater than 0 data retention.

   Choose **Create video stream**.

1. After Kinesis Video Streams creates the stream, review the details on the `YourStreamName` page.

------
#### [ AWS CLI ]

Verify that you have the AWS CLI installed and configured. For more information, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/).

For installation instructions, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html#getting-started-install-instructions). After installation, [configure the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-new) with credentials and region.

Alternatively, open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information.

Run the following `Create-Stream` command using the AWS CLI:

```
aws kinesisvideo create-stream \
  --stream-name "YourStreamName" \
  --data-retention-in-hours 24 \
  --region "us-west-2"
```

The response will look like the following:

```
{
    "StreamARN": "arn:aws:kinesisvideo:us-west-2:123456789012:stream/YourStreamName/1234567890123"
}
```

------
#### [ AWS SDK ]

This code snippet shows you how to create a Kinesis video stream using the AWS SDK for JavaScript v2. The syntax will differ from other AWS SDKs, but the general flow will be the same. View a complete code example on [GitHub](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/createStream.js).

Create the Kinesis Video Streams client. This is the client used to call the [CreateStream](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_CreateStream.html) API.

```
const clientConfig = {
    accessKeyId: 'YourAccessKey',
    secretAccessKey: 'YourSecretKey',
    region: 'us-west-2'
};
const kinesisVideoClient = new AWS.KinesisVideo(clientConfig);
```

Use the client to call the `CreateStream` API.

```
const createStreamResponse = await kinesisVideoClient
    .createStream({
        StreamName: 'YourStreamName',
        DataRetentionInHours: 48,
    })
    .promise();
```

Print the response.

```
console.log(createStreamResponse.StreamARN);
```

The live web page with this code sample is available for use on [GitHub](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html). Input your region, AWS credentials, and the name of your signaling channel. 

Expand the **WebRTC Ingestion and Storage** node, type the name of your stream, then choose **Create Stream**. A pop-up asks for the number of hours you'd like to persist the stream's data. Enter a value greater than 0, then choose **Create Stream**.

------

# Grant permission
<a name="ingestion-grant-permission"></a>

You must grant stream permission to your IAM roles in order to ingest streams in Amazon Kinesis Video Streams with WebRTC.

**Note**  
 A service role is an [IAM role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) that a service assumes to perform actions on your behalf. An IAM administrator can create, modify, and delete a service role from within IAM. For more information, see [Create a role to delegate permissions to an AWS service](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html) in the *IAM User Guide*. 

Both Master and Viewer roles must also have `DescribeStream`, `GetDataEndpoint`, and `PutMedia` permissions to ingest media to Kinesis Video Streams. 

Refer to the sample IAM policy below for Master participants: 

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:DescribeSignalingChannel",
        "kinesisvideo:DescribeMediaStorageConfiguration",
        "kinesisvideo:GetSignalingChannelEndpoint",
        "kinesisvideo:GetIceServerConfig",
        "kinesisvideo:ConnectAsMaster",
        "kinesisvideo:JoinStorageSession"
      ],
      "Resource": "arn:aws:kinesisvideo:us-west-2:123456789012:channel/SignalingChannelName/1234567890123"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:GetDataEndpoint",
        "kinesisvideo:DescribeStream",
        "kinesisvideo:PutMedia"
      ],
      "Resource": "arn:aws:kinesisvideo:us-west-2:123456789012:stream/VideoStreamName/1234567890123"
    }
  ]
}
```

------

# Configure destination
<a name="configure-ingestion"></a>

Once you've created the Kinesis Video Streams resources, you need to tell the signaling channel which stream to save it to.

If you want to delete a signaling channel or stream, you must unlink them first. See [Unlink signaling channel and stream](#ingest-unlink).

## Link signaling channel and stream
<a name="ingestion-link"></a>

Use the [UpdateMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_UpdateMediaStorageConfiguration.html) API and input the ARNs for the Kinesis Video Streams resources that you want to link.

**Important**  
Once `StorageStatus` is enabled, direct peer-to-peer (master-viewer) connections no longer occur. Peers connect directly to the storage session. You must call the `JoinStorageSession` API to trigger an SDP offer send and establish a connection between a peer and the storage session.

------
#### [ AWS Management Console ]

**Note**  
This operation isn't currently supported in the Kinesis Video Streams AWS Management Console.

Open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information. 

Follow the instructions in the AWS CLI tab.

------
#### [ AWS CLI ]

Verify that you have the AWS CLI installed and configured. For more information, see the [AWS Command Line Interface](https://docs.aws.amazon.com//cli/latest/userguide/) documentation.

For installation instructions, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html#getting-started-install-instructions). After installation, [configure the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-new) with credentials and region.

Alternatively, open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information.

Run the `Update-Media-Storage-Configuration` command in the AWS CLI:

```
aws kinesisvideo update-media-storage-configuration \
  --channel-arn arn:aws:kinesisvideo:us-west-2:123456789012:channel/YourChannelName/1234567890123 \
  --media-storage-configuration \
    StreamARN="arn:aws:kinesisvideo:us-west-2:123456789012:stream/YourStreamName/1234567890123",Status="ENABLED" \
  --region "us-west-2"
```

------
#### [ AWS SDK ]

This code snippet shows you how to configure the signaling channel to ingest media to the specified Kinesis video stream using the AWS SDK for JavaScript v2. The syntax will differ from other AWS SDKs, but the general flow will be the same. View a complete code example on [GitHub](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/updateMediaStorageConfiguration.js).

Create the Kinesis Video Streams client. This is the client used to call the [UpdateMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_UpdateMediaStorageConfiguration.html) API.

```
const clientConfig = {
    accessKeyId: 'YourAccessKey',
    secretAccessKey: 'YourSecretKey',
    region: 'us-west-2'
};
const kinesisVideoClient = new AWS.KinesisVideo(clientConfig);
```

Use the client to call the `UpdateMediaStorageConfiguration` API.

```
await kinesisVideoClient
    .updateMediaStorageConfiguration({
        ChannelARN: 'YourChannelARN',
        MediaStorageConfiguration: {
            Status: 'ENABLED',
            StreamARN: 'YourStreamARN',
        },
    })
    .promise();
```

The live web page with this code sample is available for use on [GitHub](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html). Input your region, AWS credentials, and the name of your signaling channel. 

Expand the **WebRTC Ingestion and Storage** node, type the name of your stream, then choose **Update Media Storage Configuration**. The channel will be configured to ingest media to the specified stream.

------

## Unlink signaling channel and stream
<a name="ingest-unlink"></a>

**Important**  
You can't delete a signaling channel or stream until they are unlinked from each other.

If you don't want the signaling channel's media ingested to the stream, use the [UpdateMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_UpdateMediaStorageConfiguration.html) API to unlink the Kinesis Video Streams resources. After the channel is unlinked, direct peer-to-peer connections can resume. 

------
#### [ AWS Management Console ]

**Note**  
This operation isn't currently supported in the Kinesis Video Streams AWS Management Console.

Open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information. 

Follow the instructions in the AWS CLI tab.

------
#### [ AWS CLI ]

Verify that you have the AWS CLI installed and configured. For more information, see the [AWS Command Line Interface](https://docs.aws.amazon.com//cli/latest/userguide/) documentation.

For installation instructions, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html#getting-started-install-instructions). After installation, [configure the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-new) with credentials and region.

Alternatively, open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information.

Run the `Update-Media-Storage-Configuration` command in the AWS CLI:

```
aws kinesisvideo update-media-storage-configuration \
  --channel-arn arn:aws:kinesisvideo:us-west-2:123456789012:channel/YourChannelName/1234567890123 \
  --media-storage-configuration \
    StreamARN="null",Status="DISABLED" \
  --region "us-west-2"
```

------
#### [ AWS SDK ]

This code snippet shows you how to configure the signaling channel to ingest media to the specified Kinesis video stream using the AWS SDK for JavaScript v2. The syntax will differ from other AWS SDKs, but the general flow will be the same. View a complete code example on [GitHub](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/updateMediaStorageConfiguration.js).

Create the Kinesis Video Streams client. This is the client used to call the [UpdateMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_UpdateMediaStorageConfiguration.html) API.

```
const clientConfig = {
    accessKeyId: 'YourAccessKey',
    secretAccessKey: 'YourSecretKey',
    region: 'us-west-2'
};
const kinesisVideoClient = new AWS.KinesisVideo(clientConfig);
```

Use the client to call the `UpdateMediaStorageConfiguration` API.

```
await kinesisVideoClient
    .updateMediaStorageConfiguration({
        ChannelARN: 'YourChannelARN',
        MediaStorageConfiguration: {
            Status: 'DISABLED',
            StreamARN: 'null',
        },
    })
    .promise();
```

The live web page with this code sample is available for use on [GitHub](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html). Input your region, AWS credentials, and the name of your signaling channel. 

Expand the **WebRTC Ingestion and Storage** node, verify that the **Stream Name** field is empty, then choose **Update Media Storage Configuration**. The channel will no longer be configured to ingest media to the specified stream.

------

# Ingest media
<a name="ingest-media"></a>

The following limits are in place: 
+ **Session duration:** one hour, maximum
+ **Signaling channels:** maximum of 100 per account with storage configuration enabled

**Topics**
+ [Ingest media from a browser](#ingest-browser)
+ [Ingest media from WebRTC C SDK](#ingest-webrtc-sdk)
+ [Add viewers to the ingestion session](#ingest-add-viewers)

## Ingest media from a browser
<a name="ingest-browser"></a>

**Important**  
Chrome is currently the only supported browser.

1. Open the Amazon Kinesis Video Streams with WebRTC SDK in the JavaScript [sample page](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html).

1. Complete the following information:
   + **KVS Endpoint** - In the **Region** field, select your region. 

     For example, `us-west-2`.
   + **AWS Credentials**

     Complete the following fields:
     + **Access Key ID**
     + **Secret Access Key**
     + **Session Token** - The sample application supports both temporary and long-term credentials. Leave this field blank if you're using long-term IAM credentials. See [Temporary security credentials in IAM](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_credentials_temp.html) for more information.
   + **Signaling Channel** - In the **Channel Name** field, type the name of the signaling channel you configured earlier. For more information, see [Configure destination](configure-ingestion.md).
   + **Tracks** - Select **Send Video** and **Send Audio**.
   + **WebRTC Ingestion and Storage** - Expand the node and select **Automatically determine ingestion mode**. This option makes the sample application call the [DescribeMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeMediaStorageConfiguration.html) API to determine in which mode to run.

1. Select **Start Master**.

   If the signaling channel is configured for ingestion using the [DescribeMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeMediaStorageConfiguration.html) API, the sample application will automatically invoke the [JoinStorageSession](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSession.html) API immediately after connecting to the Signaling channel to start the WebRTC ingestion workflow.

## Ingest media from WebRTC C SDK
<a name="ingest-webrtc-sdk"></a>

Follow the [Amazon Kinesis Video Streams with WebRTC SDK in C for embedded devices](kvswebrtc-sdk-c.md) procedures to build the sample application.

1. Setup your environment with your AWS account credentials:

   ```
   export AWS_ACCESS_KEY_ID=YourAccessKey
   export AWS_SECRET_ACCESS_KEY=YourSecretKey
   export AWS_DEFAULT_REGION=YourAWSRegion
   ```

   If you're using temporary AWS credentials, also export your session token:

   ```
   export AWS_SESSION_TOKEN=YourSessionToken
   ```

1. Run the samples:

   **Master sample**

   Navigate to the `build` folder and use "1" as the second argument. Type:

   ```
   ./samples/kvsWebrtcClientMaster channel-name 1
   ```

   **GStreamer master sample**

   Navigate to the `build` folder and use "audio-video-storage" as the second argument. Type:

   ```
   ./samples/kvsWebrtcClientMasterGstSample channel-name audio-video-storage testsrc
   ```

This starts WebRTC ingestion. 

**Note**  
Your supplied signaling channel must be configured for storage. Use the [DescribeMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeMediaStorageConfiguration.html) API to confirm.

## Add viewers to the ingestion session
<a name="ingest-add-viewers"></a>

Once the signaling channel is in WebRTC Ingestion mode, viewer participants no longer connect directly to the master participant. Viewer participants connect directly to the storage session. Viewer participants receive the media sent by the master participants, and viewer participants can send back optional audio to the master participant. Any audio sent back by viewers will be sent to all other peers connected to the storage session and ingested to the Kinesis Video Stream, as long as the master participant is connected to the storage session.

The following limits are in place:
+ **Maximum number of viewers:** 3 
+ **Maximum time viewer participants can be connected to the storage session without a master participant present:** 3 minutes 

**Important**  
If a viewer disconnects from the storage session (closes the peer connection), their quota (viewer limit) remains consumed for 1 minute. During this 1-minute period, the viewer can invoke this API with the same Client ID to rejoin the session without consuming an additional viewer quota. After 1 minute, the viewer quota is released and available for other viewers to join.

**Browser**

**Important**  
Chrome is the only supported browser.

1. Open another tab in the Amazon Kinesis Video Streams with WebRTC SDK in the JavaScript [sample page](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html). All the information from the previous page will be automatically populated. If not, complete the following information:
   + **KVS Endpoint** - In the **Region** field, select your region. 

     For example, `us-west-2`.
   + **AWS Credentials**

     Complete the following fields:
     + **Access Key ID**
     + **Secret Access Key**
     + **Session Token** - The sample application supports both temporary and long-term credentials. Leave this field blank if you're using long-term IAM credentials. See [Temporary security credentials in IAM](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_credentials_temp.html) for more information.
   + **Signaling Channel** - In the **Channel Name** field, type the name of the signaling channel you configured earlier. For more information, see [Configure destination](configure-ingestion.md).
   + **Tracks** - Select **Send Audio**. Note that if **Send Video** is checked, it will automatically be unchecked when choosing **Start Viewer**.
   + **WebRTC Ingestion and Storage** - Expand the node and select **Automatically determine ingestion mode**. This option makes the sample application call the [DescribeMediaStorageConfiguration](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeMediaStorageConfiguration.html) API to determine in which mode to run.

1. Select **Start Viewer**.

   The application automatically calls the [JoinStorageSessionAsViewer](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSessionAsViewer.html) API immediately after connecting to the signaling channel to trigger an SDP offer send to the viewer from the session.

**Note**  
With peer-to-peer WebRTC, the viewer participant is the controlling peer and the master participant is the controlled peer. In WebRTC ingestion mode, the storage session is now the controlling peer. After connecting to signaling and invoking [JoinStorageSessionAsViewer](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSessionAsViewer.html), the viewer will need to respond to the SDP offer and establish a connection to the storage session through WebRTC.

**Note**  
The storage session will only send `TURN` candidates. When nominating an ICE candidate pair from the perspective of participants, the remote candidate will always be of type `relay`.

# Playback ingested media
<a name="ingestion-view-media"></a>

You can consume media data by either viewing it in the console, or by creating an application that reads media data from a stream using Hypertext Live Streaming (HLS).

## View media in the console
<a name="ingestion-view-media-console"></a>

In another browser tab, open the AWS Management Console. In the Kinesis Video Streams Dashboard, select [Video streams](https://us-west-2.console.aws.amazon.com/kinesisvideo/home?region=us-west-2#/streams).

Select the name of your stream in the list of streams. Use the search bar, if necessary.

Expand the **Media playback** section. If the video is still uploading, it will be shown. If the upload has finished, select the double-left arrow.

## Consume media data using HLS
<a name="ingestion-consume-hls"></a>

You can create a client application that consumes data from a Kinesis video stream using HLS. For information about creating an application that consumes media data using HLS, see [Kinesis Video Streams playback](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/how-playback.html).

## View media using the sample media viewer application
<a name="ingestion-view-application"></a>

Amazon Kinesis Video Streams created a sample web page implementation of a media viewer capable of playing back Kinesis Video Streams in HLS or DASH. You can view the source code on [GitHub](https://github.com/aws-samples/amazon-kinesis-video-streams-media-viewer) and try using the [hosted web page](https://aws-samples.github.io/amazon-kinesis-video-streams-media-viewer/).

1. Open the [Amazon Kinesis Video Streams Media Viewer](https://aws-samples.github.io/amazon-kinesis-video-streams-media-viewer/).

1. Complete the following fields:
   + **Region** - Select **us-west-2**.
   + **AWS Access Key**
   + **AWS Secret Key**
   + **Stream name**
   + **Playback Mode** - Select **Live**.

1. Select **Start Playback**.

# Connect to the storage session
<a name="ingestion-initiate"></a>

Follow these procedures to create the storage session and start the WebRTC connection process. The master participant should call [JoinStorageSession](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSession.html). Viewer participants should call [JoinStorageSessionAsViewer](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSessionAsViewer.html). 

This will have the storage session send an SDP offer and ICE candidates through signaling to the master participant connected through [ConnectAsMaster](ConnectAsMaster.md), or the specified viewer participant connected through [ConnectAsViewer](ConnectAsViewer.md). 

1. Obtain the ARN of the signaling channel, as it is a required input for the next step. If you already know the ARN, continue with the next step.

------
#### [ AWS Management Console ]

   1. Open the [Kinesis Video Streams Signaling Channels console](https://console.aws.amazon.com//kinesisvideo/home/#/signalingChannels).

   1. Choose the name of your signaling channel.

   1. Under the **Signaling channel info** tab, locate the ARN for your signaling channel.

------
#### [ AWS CLI ]

   Verify that you have the AWS CLI installed and configured. For more information, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/).

   For installation instructions, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html#getting-started-install-instructions). After installation, [configure the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-new) with credentials and region.

   Alternatively, open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information.

   Run the following [Describe-Signaling-Channel](https://docs.aws.amazon.com//cli/latest/reference/kinesisvideo/describe-signaling-channel.html) command using the AWS CLI:

   ```
   aws kinesisvideo describe-signaling-channel \
     --channel-name "YourChannelName" \
   ```

   The response will look like the following:

   ```
   {
       "ChannelInfo": {
           "ChannelName": "YourChannelName",
           "ChannelARN": "arn:aws:kinesisvideo:us-west-2:123456789012:channel/YourChannelName/1234567890123",
           "ChannelType": "SINGLE_MASTER", 
           "ChannelStatus": "ACTIVE",
           "CreationTime": "2024-07-07T23:28:24.941000-07:00",
           "SingleMasterConfiguration": {
           "MessageTtlSeconds": 60
       },
       "Version": "Ws0fZvFGXzEpuZ2CE1s9"
       }
   }
   ```

   You'll find the signaling channel ARN in the `ChannelInfo` object.

------
#### [ AWS SDK ]

   This code snippet shows you how to create a Kinesis Video Streams with WebRTC signaling channel using the AWS SDK for JavaScript v2. The syntax will differ from other AWS SDKs, but the general flow will be the same. 

   You can view the complete code example for [JoinStorageSession](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/joinStorageSession.js) or [JoinStorageSessionAsViewer](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/joinStorageSessionAsViewer.js).

   Create the Kinesis Video Streams client. This is used to call the [DescribeSignalingChannel API](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeSignalingChannel.html).

   ```
   const clientConfig = {
       accessKeyId: 'YourAccessKey',
       secretAccessKey: 'YourSecretKey',
       region: 'us-west-2'
   };
   const kinesisVideoClient = new AWS.KinesisVideo(clientConfig);
   ```

   Use the client to call the `DescribeSignalingChannel` API.

   ```
   const describeSignalingChannelResponse = await kinesisVideoClient
       .describeSignalingChannel({
           ChannelName: 'YourChannelName',
       })
       .promise();
   ```

   Save the response.

   ```
   const channelARN =
       describeSignalingChannelResponse.ChannelInfo.ChannelARN;
   ```

------

1. Obtain the WEBRTC endpoint. Requests to [JoinStorageSession](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSession.html) or [JoinStorageSessionAsViewer](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSessionAsViewer.html) for a particular signaling channel must be made to its designated endpoint.

------
#### [ AWS Management Console ]

**Note**  
This operation isn't currently supported in the Kinesis Video Streams AWS Management Console.

   Open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information. 

   Follow the instructions in the AWS CLI tab.

------
#### [ AWS CLI ]

   Verify that you have the AWS CLI installed and configured. For more information, see the [AWS Command Line Interface](https://docs.aws.amazon.com//cli/latest/userguide/) documentation.

   For installation instructions, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html#getting-started-install-instructions). After installation, [configure the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-new) with credentials and region.

   Alternatively, open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information.

   Run the `Get-Signaling-Channel-Endpoint` command in the AWS CLI:

   ```
   aws kinesisvideo get-signaling-channel-endpoint \
     --channel-arn "arn:aws:kinesisvideo:us-west-2:123456789012:channel/YourChannelName/1234567890123" \
     --single-master-channel-endpoint-configuration "Protocols=['WEBRTC'],Role=MASTER" \
     --region "us-west-2"
   ```

   The response looks similar to the following:

   ```
   {
       "ResourceEndpointList": [
           {
               "Protocol": "WEBRTC",
               "ResourceEndpoint": "https://w-abcd1234.kinesisvideo.aws-region.amazonaws.com"
           } 
       ]
   }
   ```

------
#### [ AWS SDK ]

   This code snippet shows you how to call the `GetSignalingChannelEndpoint` API for a Kinesis Video Streams with WebRTC signaling channel using the AWS SDK for JavaScript v2. The syntax will differ from other AWS SDKs, but the general flow will be the same. View a complete code example for [JoinStorageSession](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/joinStorageSession.js) or [JoinStorageSessionAsViewer](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/joinStorageSessionAsViewer.js).

   Create the Kinesis Video Streams client. This is the client used to call the [DescribeSignalingChannel API](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_DescribeSignalingChannel.html). 

   If you created a Kinesis Video Streams client earlier to call `DescribeSignalingChannel`, you can reuse the same client.

   ```
   const clientConfig = {
       accessKeyId: 'YourAccessKey',
       secretAccessKey: 'YourSecretKey',
       region: 'us-west-2'
   };
   const kinesisVideoClient = new AWS.KinesisVideo(clientConfig);
   ```

   Use the client to call the `GetSignalingChannelEndpoint` API.

   ```
   const getSignalingChannelEndpointResponse = await kinesisVideoClient
       .getSignalingChannelEndpoint({
           ChannelARN: channelARN,
           SingleMasterChannelEndpointConfiguration: {
               Protocols: ['WEBRTC'],
               Role: 'MASTER',
           },
       })
       .promise();
   ```

   Save the response:

   ```
   const webrtcEndpoint = getSignalingChannelEndpointResponse.ResourceEndpointList[0].ResourceEndpoint;
   ```

------

1. Use the channel ARN and WEBRTC endpoints to make the API call. If the participants are correctly connected to Kinesis Video Streams with WebRTC Signaling via the `ConnectAsMaster` or `ConnectAsViewer` WebSocket APIs, an SDP offer and a stream of ICE candidate messages will be sent along the WebSocket from the storage session to the participants.

------
#### [ AWS Management Console ]

**Note**  
This operation isn't currently supported in the Kinesis Video Streams AWS Management Console.

   Open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information. 

   Follow the instructions in the AWS CLI tab.

------
#### [ AWS CLI ]

   Verify that you have the AWS CLI installed and configured. For more information, see the [AWS Command Line Interface](https://docs.aws.amazon.com//cli/latest/userguide/) documentation.

   For installation instructions, see the [AWS Command Line Interface User Guide](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html#getting-started-install-instructions). After installation, [configure the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-new) with credentials and region.

   Alternatively, open the AWS CloudShell terminal, which has the AWS CLI installed and configured. See the [AWS CloudShell User Guide](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html#how-to-get-started) for more information.

   Run the `Join-Storage-Session` command for master participants in the AWS CLI using the channel ARN and WEBRTC endpoint from previous steps:

   ```
   aws kinesis-video-webrtc-storage join-storage-session \
     --endpoint-url https://w-abcd1234.kinesisvideo.us-west-2.amazonaws.com \
     --channel-arn arn:aws:kinesisvideo:us-west-2:123456789012:channel/YourChannelName/1234567890123 \
     --region "us-west-2"
   ```

   After a successful run, an empty response is returned and nothing is printed. 

   In the case of a viewer participant, run the following `Join-Storage-Session-As-Viewer` command in the AWS CLI using the channel ARN and WEBRTC endpoint from before:

   ```
   aws kinesis-video-webrtc-storage join-storage-session-as-viewer \
     --endpoint-url https://w-abcd1234.kinesisvideo.us-west-2.amazonaws.com \
     --channel-arn arn:aws:kinesisvideo:us-west-2:123456789012:channel/YourChannelName/1234567890123 \
     --client-id "ExampleViewerClientID"
     --region "us-west-2"
   ```

   After a successful run, an empty response is returned and nothing is printed. 

------
#### [ AWS SDK ]

   This code snippet shows you how to call the `JoinStorageSession` or `JoinStorageSessionAsViewer` API for a Kinesis Video Streams with WebRTC signaling channel using the AWS SDK for JavaScript v2. The syntax will differ from other AWS SDKs, but the general flow will be the same. View a complete code example for [JoinStorageSession](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/joinStorageSession.js) or [JoinStorageSessionAsViewer](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/blob/master/examples/joinStorageSessionAsViewer.js).

   Create the Kinesis Video Streams WebRTC storage client. This is the client used to call `JoinStorageSession` or `JoinStorageSessionAsViewer` and is different than the Kinesis Video Streams client created in earlier steps.

   ```
   const webrtcStorageClientConfig = {
       accessKeyId: 'YourAccessKey',
       secretAccessKey: 'YourSecretKey',
       region: 'us-west-2',
       endpoint: webrtcEndpoint
   };
   const kinesisVideoWebRTCStorageClient = new AWS.KinesisVideoWebRTCStorage(clientConfig);
   ```

   Use the client to call the `JoinStorageSession` API for master participants.

   ```
   await kinesisVideoWebRTCStorageClient
       .joinStorageSession({
           channelArn: channelARN,
       })
       .promise();
   ```

   In the case of a viewer participant, use the client to call the `JoinStorageSessionAsViewer` API.

   ```
   await kinesisVideoWebRTCStorageClient
       .joinStorageSessionAsViewer({
           channelArn: channelARN,
           clientId: "ExampleViewerClientID",
       })
       .promise();
   ```

   The live web page with this code sample is available on [GitHub](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html). Input your region, AWS credentials, and the name of your signaling channel. Expand the **WebRTC Ingestion and Storage** node, and uncheck **Automatically determine ingestion mode**. 

   Switch the manual override to **ON** and select **Show button to manually call JoinStorageSession API** and/or **Show button to manually call JoinStorageSessionAsViewer API**. 

   When you select **Start Master** or **Start Viewer**, after the application connects to signaling via `ConnectAsMaster` or `ConnectAsViewer`, a button will appear to have the storage session initiate the WebRTC connection with the peer instead of the application calling the API immediately after connecting to signaling.

------

# Troubleshoot issues connecting with the storage session
<a name="troubleshoot-establish-storage"></a>

This section provides guidance on troubleshooting issues related to setting up and configuring storage for recording video streams.

**Topics**
+ [Controlling and controlled peers](#troubleshoot-control-peers)
+ [Review supported codecs](#troubleshoot-review-codecs)
+ [If channel is not mapped to a stream, will also throw 400 InvalidArgumentException](#troubleshoot-channel-mapping)

## Controlling and controlled peers
<a name="troubleshoot-control-peers"></a>

In WebRTC, the controlling peer initiates the connection to the controlled peer by sending an SDP offer. For peer-to-peer sessions, the viewer participant initiates the connection by sending an offer to the master participant through Signaling. When connecting to the storage session for WebRTC ingestion, the storage session is the controlling peer. For master participants, they still remain the controlled participant. However, viewer participants switch from controlling to controlled.

Upon calling [JoinStorageSession](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSession.html) or [JoinStorageSessionAsViewer](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSessionAsViewer.html), all participants must respond with an SDP answer and exchange ICE candidates with the storage session.

For a sequence diagram, see Understanding WebRTC ingestion and storage.

**Important**  
Signaling messages received from the storage session do not have a senderClientId field in the JSON, which differs from the peer-to-peer master, which always receives senderClientId field with the SDP offer and ICE candidates.

## Review supported codecs
<a name="troubleshoot-review-codecs"></a>

When [sending an SDP answer](https://docs.aws.amazon.com//kinesisvideostreams-webrtc-dg/latest/devguide/SendSdpAnswer.html) and [exchanging ICE candidates](https://docs.aws.amazon.com//kinesisvideostreams-webrtc-dg/latest/devguide/SendIceCandidate.html) with the storage session, we recommend including a `correlationId` in the messages. Including a `correlationId` in the messages allows the storage session to return `statusResponse` messages. These messages will contain the `correlationId` of the input message, allowing you to track which message the `statusResponse` belongs to. This allows you to receive immediate feedback about why your SDP answers was rejected. 

For more information about `correlationId` and `statusResponse`, see [Asynchronous message reception](async-message-reception-api.md). 

One common reason the storage session might reject the SDP answer is that the storage session wasn't able to accept codecs specified in the answer. A sample `statusResponse` may look like the following: 

```
{
  "correlationId": "1700186220273",
  "errorType": "InvalidArgumentException",
  "statusCode": "400",
  "success": false
}
```

As you review the SDP answer contents, review the lines starting with `a=rtpmap` and verify that the codecs match the storage session's supported codecs. Below is a snippet of a sample SDP answer containing opus audio and VP8 video.

```
...
a=rtpmap:111 opus/48000/2
...
a=rtpmap:120 VP8/90000
...
```

See [JoinStorageSession](https://docs.aws.amazon.com//kinesisvideostreams/latest/dg/API_webrtc_JoinStorageSession.html) for a list of supported codecs.

## If channel is not mapped to a stream, will also throw 400 InvalidArgumentException
<a name="troubleshoot-channel-mapping"></a>

### Review transceiver directions
<a name="troubleshoot-transceiver-directions"></a>

In the SDP answer, review the directionality of the video and audio transceivers. The lines in the SDP look like this:

```
a=sendrecv
a=recvonly
```

For master participants, the following requirements are in place:
+ H.264 video: sendonly
+ Opus audio: sendonly or sendrecv

For viewer participants, the following requirements are in place:
+ H.264 video: recvonly
+ Opus audio: recvonly or sendrecv

If the service requirements are not met, a statusResponse with 400 IllegalArgumentException will be returned if the correlationId is provided when the answer was sent.

When using the KVS-provided WebRTC ingestion sample applications:
+ Master participants: Ensure the "send video" and "send audio" settings are both enabled
+ Viewer participants: Ensure "send video" setting is disabled

### Review ICE candidate conversion
<a name="troubleshoot-ice-candidate-conversion"></a>

When receiving ICE candidates from the KVS Signaling SDK, the application may need to convert the string into the ICE candidate object.

ICE candidates received from the storage session do not contain an SDPMID property, and do not come with a senderClientId.

Review your application logic for adding the ICE candidates received from remote into your application's RTCPeerConnection object.

### Review ICE candidate queuing logic
<a name="troubleshoot-ice-candidate-queuing"></a>

All ICE candidates received from the storage session need to be added to the RTCPeerConnection via the addIceCandidate API.

Even though the storage session sends the SDP offer before the ICE candidates, due to the asynchronous nature of the Signaling message delivery, the application may receive the ICE candidates before receiving the offer.

In this case, you will need to implement a temporary buffer to hold the ICE candidates.

The logic implemented in the KVS sample applications is as follows:

1. The samples maintain a map of the senderClientId to its RTCPeerConnection.

1. The samples maintain another map of the senderClientId to a list of pending Ice Candidates.

1. When an ICE candidate is received, check the PeerConnection map. If the PeerConnection map does not have a connection yet, add it to the pending list. Otherwise, add the ICE candidate to the PeerConnection.

1. When the offer is received, it creates the RTCPeerConnection and add it to the PeerConnection map. Then, add all ICE candidates from the pending queue to this PeerConnection.