# Cross-channel media stream relay (/en/realtime-media/interactive-live-streaming/build/connect-across-channels/cross-channel-media-relay/unity)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Some special use-cases require cross-channel media stream forwarding functionality. Video SDK enables you to relay the media stream of a host, from a source channel, to multiple target channels simultaneously. This functionality allows you to realize the following interactions:

* The hosts publish and receive each other's audio and video streams while engaging in *cross-channel* real-time interaction.

* The audience receive all audio and video streams from hosts and watch multiple hosts interact at the same time.

Due to its real-time and interactive nature, this feature enriches live broadcasts and game-play, It is especially suitable for live scenes such as co-hosting PK and online choir. It provides the audience with a better viewing experience, while bringing more traffic and revenue to the hosts.

      
  
      
  
      
  
      
  
      
  
      
  
      
  
      
  
      
<CalloutContainer type="info">
  <CalloutDescription>
    Cross-channel media stream relay is included in Agora's policy of [10,000 free minutes](/en/api-reference/faq/account/billing_free) every month. For usage beyond the free quota, please refer to [Pricing](/en/realtime-media/interactive-live-streaming/reference/pricing).
  </CalloutDescription>
</CalloutContainer>

## Prerequisites

* Ensure that you have implemented the [SDK quickstart](../../quickstart.mdx) in your project.
* Contact [technical support](https://agora-ticket.agora.io/) to activate the cross-channel media stream relay feature.

## Implement cross-channel media stream relay

The following figure shows the workflow you implement to facilitate cross-channel media stream relay:

![CrossChannelMediaStreamForwarding](https://assets-docs.agora.io/images/video-sdk/cross-channel-forwarding.svg)

To implement cross-channel media stream relay in your game, take the following steps:

1. Start cross-channel media stream relay

After joining the channel, call `StartOrUpdateChannelMediaRelay` to configure the source and target channel information and start forwarding a media stream.

```csharp
private void OnStartButtonClick()
{
  ChannelMediaRelayConfiguration config = new ChannelMediaRelayConfiguration();

  // Configure source channel
  config.srcInfo = new ChannelMediaInfo
  {
    channelName = this._appIdInput.channelName,
    uid = 0, // Let the SDK assign a random UID
    token = this._appIdInput.token // Regenerate token for source channel with UID 0
  };

  // Configure target channel (up to 6 supported)
  config.destInfos = new ChannelMediaInfo[1];
  config.destInfos[0] = new ChannelMediaInfo
  {
    channelName = this._appIdInput.channelName + "_2",
    uid = 0, // Random UID or specify a unique one
    token = this._appIdInput.token
  };
  config.destCount = 1;

  // Start media stream forwarding
  var nRet = RtcEngine.StartOrUpdateChannelMediaRelay(config);
  this.Log.UpdateLog(`StartOrUpdateChannelMediaRelay nRet: ${nRet}, New Channel: ${this._appIdInput.channelName}_2`);
}
```

2. Update media stream relay channels

To forward the stream to multiple target channels or exit the current forwarding channel after staring channel media relay, call `StartOrUpdateChannelMediaRelay` again to add or remove target channels for forwarding.

<CalloutContainer type="info">
  <CalloutDescription>
    The updated configuration completely **replaces** the previous configuration.
  </CalloutDescription>
</CalloutContainer>

3. Pause or resume media stream relay

To pause forwarding the media stream to all target channels, call `PauseAllChannelMediaRelay`.

```csharp
private void onPauseAllButtonClick()
{
  var nRet = RtcEngine.PauseAllChannelMediaRelay();
  this.Log.UpdateLog(`onPauseAllButtonClick nRet: ${nRet}`);
}
```

To resume forwarding the media stream to all target channels, call `ResumeAllChannelMediaRelay`:

```csharp
private void OnResumeAllButtonClick()
{
  var nRet = RtcEngine.ResumeAllChannelMediaRelay();
  this.Log.UpdateLog(`OnResumeAllButtonClick nRet: ${nRet}`);
}
```

4. Stop cross-channel media stream relay

To stop forwarding the media stream, call `StopChannelMediaRelay`. When forwarding stops, the host exits all target channels.

```csharp
private void OnStopButtonClick()
{
  var nRet = RtcEngine.StopChannelMediaRelay();
  this.Log.UpdateLog(`OnStopButtonClick nRet: ${nRet}`);
}
```

<CalloutContainer type="info">
  <CalloutDescription>
    If this method fails, call `LeaveChannel` to leave the channel and stop cross-channel media stream relay.
  </CalloutDescription>
</CalloutContainer>

5. Monitor cross-channel media stream status

During cross-channel media stream relay, the SDK reports changes in the status of media stream relay through the `OnChannelMediaRelayStateChanged` callback. Implement the relevant business logic based on the [status codes](#status-codes).

```csharp
public override void OnChannelMediaRelayStateChanged(int state, int code)
{
  _channelMediaRelay.Log.UpdateLog(`OnChannelMediaRelayStateChanged state: ${state}, code: ${code}`);
}
```

### Development considerations

* In a live broadcast use-case, only hosts can call `StartOrUpdateChannelMediaRelay`.
* `StartOrUpdateChannelMediaRelay` must be called after successfully joining the channel, otherwise an error is reported.
* Multiple hosts can forward media streams in a channel. Each host can forward media streams to up to 6 target channels.
* This function does not support `String` `uid`s. Additionally, to use the cross-channel microphone function, use the `Int` type in the normal microphone function `uid`.

## Reference

This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.

### Status codes

To understand and respond to changes in the media relay state, refer to the [`CHANNEL_MEDIA_RELAY_STATE`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/enum_channelmediarelaystate.html) and [`CHANNEL_MEDIA_RELAY_ERROR`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/enum_channelmediarelayerror.html) enums in the API reference.

### Sample project

Agora provides an open-source [ChannelMediaRelay](https://github.com/AgoraIO-Extensions/Agora-Unity-Quickstart/blob/main/API-Example-Unity/Assets/API-Example/Examples/Advanced/ChannelMediaRelay/ChannelMediaRelay.cs) sample project for your reference. Download the project or view the source code for a more detailed example.

### API reference

* [`StartOrUpdateChannelMediaRelay`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/class_irtcengine.html#api_irtcengine_startorupdatechannelmediarelay)
* [`StopChannelMediaRelay`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/class_irtcengine.html#api_irtcengine_stopchannelmediarelay)
* [`PauseAllChannelMediaRelay`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/class_irtcengine.html#api_irtcengine_pauseallchannelmediarelay)
* [`ResumeAllChannelMediaRelay`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/class_irtcengine.html#api_irtcengine_resumeallchannelmediarelay)
* [`OnChannelMediaRelayStateChanged`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/class_irtcengineeventhandler.html#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
* [`ChannelMediaRelayConfiguration`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/class_channelmediarelayconfiguration.html)
* [`ChannelMediaInfo`](https://api-ref.agora.io/en/video-sdk/unity/4.x/API/class_channelmediainfo.html)

    
  
