# 跨频道媒体流转发 (/zh-CN/realtime-media/rtc/build/advanced-channel/media-relay)

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

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
在实时互动场景下，跨频道媒体流转发功能可实现主播角色的媒体流从源频道同时转发进多个目标频道，其中：

- 所有主播发布并接收彼此的音视频流，进行跨频道实时互动
- 观众可以接收到所有主播的音视频流，同时观看多位主播互动

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件]

在开始前，请确保满足以下条件：

- 在你的项目中实现基本的实时音视频功能，详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- [联系技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤]

参考如下流程图实现相关代码逻辑：

<DocsImage alt="实现流程" src="https://web-cdn.agora.io/docs-portal/img/rtc/media-relay.svg" displayWidth="70%" />

### 1. 开始跨频道媒体流转发 [#1-开始跨频道媒体流转发]

加入频道后，调用 `startOrUpdateChannelMediaRelay` 配置源频道和目标频道信息，开始转发媒体流。示例代码如下：

```java
// 配置源频道信息
// 推荐将源频道的 uid 设为 0，由 SDK 随机分配一个 uid
// 注意 Token 与用户加入源频道时的 Token 不同，需要用源频道名和 uid = 0 重新生成
ChannelMediaInfo srcChannelInfo = new ChannelMediaInfo(et_channel.getText().toString(), null, myUid);
ChannelMediaRelayConfiguration mediaRelayConfiguration = new ChannelMediaRelayConfiguration();
mediaRelayConfiguration.setSrcChannelInfo(srcChannelInfo);
// 配置目标频道信息
// 你可以将 uid 设为 0，由 SDK 随机分配一个 uid，或自行指定 uid，并确保其与目标频道中的所有 uid 不同
ChannelMediaInfo destChannelInfo = new ChannelMediaInfo(destChannelName, null, myUid);
mediaRelayConfiguration.setDestChannelInfo(destChannelName, destChannelInfo);
// 开始跨频道媒体流转发
engine.startOrUpdateChannelMediaRelay(mediaRelayConfiguration);
```

### 2. 更新媒体流转发频道 [#2-更新媒体流转发频道]

成功调用 `startOrUpdateChannelMediaRelay` 后，如需将流转发到多个目标频道，或退出当前的转发频道，可以再次调用该方法添加或移除转发的目标频道。

:::info[信息]
更新后的配置会**全量替换**掉之前的配置。
:::

### 3. 暂停/恢复转发媒体流 [#3-暂停恢复转发媒体流]

开始跨频道转发媒体流后，调用 `pauseAllChannelMediaRelay` 可以暂停向所有目标频道转发媒体流。示例代码如下：

```java
engine.pauseAllChannelMediaRelay();
isPaused = true;
pause.setText(R.string.resume);
```

暂停跨频道媒体流转发后，调用 `resumeAllChannelMediaRelay` 即可恢复向所有目标频道转发媒体流。示例代码如下：

```java
engine.resumeAllChannelMediaRelay();
isPaused = false;
pause.setText(R.string.pause);
```

### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发]

成功开始跨频道媒体流转发后，可以调用 `stopChannelMediaRelay` 停止转发媒体流，一经停止，主播会退出所有目标频道。示例代码如下：

```java
engine.stopChannelMediaRelay();
et_channel_ex.setEnabled(true);
pause.setEnabled(false);
join_ex.setText(getString(R.string.join));
mediaRelaying = false;
```

:::info[信息]
如果该方法调用失败，可以调用 `leaveChannel` 离开频道，跨频道媒体流转发会自动停止。
:::

### 5. 监听跨频道媒体流状态 [#5-监听跨频道媒体流状态]

在跨频道媒体流转发过程中，SDK 会通过 `onChannelMediaRelayStateChanged` 回调报告媒体流转发的状态，你可以参考状态码的含义实现相关的业务逻辑。示例代码如下：

```java
public void onChannelMediaRelayStateChanged(int state, int code) {
    switch (state) {
        case RELAY_STATE_CONNECTING:
            mediaRelaying = true;
            handler.post(() -> {
                et_channel_ex.setEnabled(false);
                join_ex.setEnabled(true);
                join_ex.setText(getText(R.string.stop));
                showLongToast("channel media Relay connected.");
            });
            break;
        case RELAY_STATE_FAILURE:
            mediaRelaying = false;
            handler.post(() -> {
                showLongToast(String.format("channel media Relay failed at error code: %d", code));
            });
        default:
            break;
    }
}
```

主要的状态码、错误码及其对应的媒体流转发状态如下：

| 媒体流转发状态 | 状态码和错误码 |
| ---------------- | ---------------- |
| 源频道开始向目标频道传输数据。  | `RELAY_STATE_RUNNING`(2) 和 `RELAY_OK`(0)     |
| 跨频道媒体流转发出现异常。可根据[错误码](/zh-CN/api-reference/rtc/android/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)进行排查。    | `RELAY_STATE_FAILURE`(3)   |
| 已停止媒体流转发。     | `RELAY_STATE_IDLE`(0) 和 `RELAY_OK`(0)      |

## 参考信息 [#参考信息]

### 开发注意事项 [#开发注意事项]

- 在直播场景中，只有角色为主播的用户才能调用 `startOrUpdateChannelMediaRelay` 开始跨频道媒体流转发。
- `startOrUpdateChannelMediaRelay` 必须在成功加入频道后调用，否则会报错。
- 一个频道内可以有多个主播转发媒体流，一个主播最多可以将媒体流转发至 6 个目标频道。
- 该功能不支持 String 型 `uid`，如需使用跨频道连麦功能，则要在普通连麦中也使用 Int 型 `uid`，否则跨频道连麦功能无法正常使用。

### 示例项目 [#示例项目]

声网提供了开源的跨频道媒体流转发示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">HostAcrossChannel</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/API-Examples/blob/main/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/HostAcrossChannel.java" />
  <Card title={<RepositoryCardTitle provider="github">HostAcrossChannel</RepositoryCardTitle>} href="https://github.com/Shengwang-Community/API-Examples/blob/main/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/HostAcrossChannel.java" />
</Cards>

### API 参考 [#api-参考]

- [`startOrUpdateChannelMediaRelay`](/zh-CN/api-reference/rtc/android/cloud-media-relay/channel-media-relay#startorupdatechannelmediarelay)
- [`stopChannelMediaRelay`](/zh-CN/api-reference/rtc/android/cloud-media-relay/channel-media-relay#api_irtcengine_stopchannelmediarelay)
- [`pauseAllChannelMediaRelay`](/zh-CN/api-reference/rtc/android/cloud-media-relay/channel-media-relay#api_irtcengine_pauseallchannelmediarelay)
- [`resumeAllChannelMediaRelay`](/zh-CN/api-reference/rtc/android/cloud-media-relay/channel-media-relay#api_irtcengine_resumeallchannelmediarelay)
- [`onChannelMediaRelayStateChanged`](/zh-CN/api-reference/rtc/android/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
- [`ChannelMediaRelayConfiguration`](/zh-CN/api-reference/rtc/android/class-channelmediarelayconfiguration)
- [`ChannelMediaInfo`](/zh-CN/api-reference/rtc/android/class-channelmediainfo)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
在实时互动场景下，跨频道媒体流转发功能可实现主播角色的媒体流从源频道同时转发进多个目标频道，其中：

- 所有主播发布并接收彼此的音视频流，进行跨频道实时互动
- 观众可以接收到所有主播的音视频流，同时观看多位主播互动

该功能因其实时性和互动性，能够丰富直播玩法，尤其适用于连麦 PK、在线合唱等直播场景，为观众带来更好的观看体验的同时，也为主播带来更多的流量和收益。

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件-1]

在开始前，请确保满足以下条件：

- 在你的项目中实现基本的实时音视频功能，详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- [联系技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤-1]

参考如下流程图实现相关代码逻辑：

<DocsImage alt="实现流程" src="https://web-cdn.agora.io/docs-portal/img/rtc/media-relay.svg" displayWidth="70%" />

### 1. 开始跨频道媒体流转发 [#1-开始跨频道媒体流转发-1]

加入频道后，调用 `startOrUpdateChannelMediaRelay` 配置源频道和目标频道信息，开始转发媒体流。示例代码如下：

```swift
// 配置源频道信息
// 推荐将源频道的 uid 设为 0，由 SDK 随机分配一个 uid
// 注意 Token 与用户加入源频道时的 Token 不同，需要用源频道名和 uid = 0 重新生成
let config = AgoraChannelMediaRelayConfiguration()
config.sourceInfo = AgoraChannelMediaRelayInfo(token: nil)

// 配置目标频道信息
// 你可以将 uid 设为 0，由 SDK 随机分配一个 uid，或自行指定 uid，并确保其与目标频道中的所有 uid 不同
let destinationInfo = AgoraChannelMediaRelayInfo(token: nil)
config.setDestinationInfo(destinationInfo, forChannelName: destinationChannelName)
// 开始跨频道媒体流转发
agoraKit.startOrUpdateChannelMediaRelay(config)
```

### 2. 更新媒体流转发频道 [#2-更新媒体流转发频道-1]

成功调用 `startOrUpdateChannelMediaRelay` 后，如需将流转发到多个目标频道，或退出当前的转发频道，可以再次调用该方法添加或移除转发的目标频道。

:::info[信息]
更新后的配置会**全量替换**掉之前的配置。
:::

### 3. 暂停/恢复转发媒体流 [#3-暂停恢复转发媒体流-1]

开始跨频道转发媒体流后，调用 `pauseAllChannelMediaRelay` 可以暂停向所有目标频道转发媒体流。示例代码如下：

```swift
agoraKit.pauseAllChannelMediaRelay()
```

暂停跨频道媒体流转发后，调用 `resumeAllChannelMediaRelay` 即可恢复向所有目标频道转发媒体流。示例代码如下：

```swift
agoraKit.resumeAllChannelMediaRelay()
```

### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发-1]

成功开始跨频道媒体流转发后，可以调用 `stopChannelMediaRelay` 停止转发媒体流，一经停止，主播会退出所有目标频道。示例代码如下：

```swift
agoraKit.stopChannelMediaRelay()
```

:::info[信息]
如果该方法调用失败，可以调用 `leaveChannel` 离开频道，跨频道媒体流转发会自动停止。
:::

### 5. 监听跨频道媒体流状态 [#5-监听跨频道媒体流状态-1]

在跨频道媒体流转发过程中，SDK 会通过 `channelMediaRelayStateDidChange` 回调报告媒体流转发的状态，你可以参考状态码的含义实现相关的业务逻辑。示例代码如下：

```swift
func rtcEngine(_ engine: AgoraRtcEngineKit,
               channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState,
               error: AgoraChannelMediaRelayError)
{
    LogUtils.log(message: "channelMediaRelayStateDidChange: \(state.rawValue) error \(error.rawValue)", level: .info)

    switch state {
    case .running:
        isRelaying = true

    case .failure:
        showAlert(message: "Media Relay Failed: \(error.rawValue)")
        isRelaying = false

    case .idle:
        isRelaying = false

    default: break
    }
}
```

主要的状态码、错误码及其对应的媒体流转发状态如下：

| 媒体流转发状态 | 状态码和错误码 |
| ---------------- | ---------------- |
| 源频道开始向目标频道传输数据。  | `AgoraChannelMediaRelayStateRunning`(2) 和 `AgoraChannelMediaRelayErrorNone`(0)     |
| 跨频道媒体流转发出现异常。可根据[错误码](/zh-CN/api-reference/rtc/ios/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)进行排查。   |  `AgoraChannelMediaRelayStateFailure`(3) |
| 已停止媒体流转发。  | `AgoraChannelMediaRelayStateIdle`(0) 和 `AgoraChannelMediaRelayErrorNone`(0)   |

## 参考信息 [#参考信息-1]

### 开发注意事项 [#开发注意事项-1]

- 在直播场景中，只有角色为主播的用户才能调用 `startOrUpdateChannelMediaRelay` 开始跨频道媒体流转发。
- `startOrUpdateChannelMediaRelay` 必须在成功加入频道后调用，否则会报错。
- 一个频道内可以有多个主播转发媒体流，一个主播最多可以将媒体流转发至 6 个目标频道。
- 该功能不支持 String 型 `uid`，如需使用跨频道连麦功能，则要在普通连麦中也使用 Int 型 `uid`，否则跨频道连麦功能无法正常使用。

### 示例项目 [#示例项目-1]

声网提供了开源的跨频道媒体流转发示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">MediaChannelRelay</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/API-Examples/blob/main/iOS/APIExample/APIExample/Examples/Advanced/MediaChannelRelay/MediaChannelRelay.swift" />
  <Card title={<RepositoryCardTitle provider="github">MediaChannelRelay</RepositoryCardTitle>} href="https://github.com/Shengwang-Community/API-Examples/blob/main/iOS/APIExample/APIExample/Examples/Advanced/MediaChannelRelay/MediaChannelRelay.swift" />
</Cards>

### API 参考 [#api-参考-1]

- [`startOrUpdateChannelMediaRelay`](/zh-CN/api-reference/rtc/ios/cloud-media-relay/channel-media-relay#startorupdatechannelmediarelay)
- [`stopChannelMediaRelay`](/zh-CN/api-reference/rtc/ios/cloud-media-relay/channel-media-relay#api_irtcengine_stopchannelmediarelay)
- [`pauseAllChannelMediaRelay`](/zh-CN/api-reference/rtc/ios/cloud-media-relay/channel-media-relay#api_irtcengine_pauseallchannelmediarelay)
- [`resumeAllChannelMediaRelay`](/zh-CN/api-reference/rtc/ios/cloud-media-relay/channel-media-relay#api_irtcengine_resumeallchannelmediarelay)
- [`channelMediaRelayStateDidChange`](/zh-CN/api-reference/rtc/ios/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
- [`AgoraChannelMediaRelayConfiguration`](/zh-CN/api-reference/rtc/ios/class-channelmediarelayconfiguration)
- [`AgoraChannelMediaRelayInfo`](/zh-CN/api-reference/rtc/ios/class-channelmediainfo)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="macos" />
在实时互动场景下，跨频道媒体流转发功能可实现主播角色的媒体流从源频道同时转发进多个目标频道，其中：

- 所有主播发布并接收彼此的音视频流，进行跨频道实时互动
- 观众可以接收到所有主播的音视频流，同时观看多位主播互动

该功能因其实时性和互动性，能够丰富直播玩法，尤其适用于连麦 PK、在线合唱等直播场景，为观众带来更好的观看体验的同时，也为主播带来更多的流量和收益。

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件-2]

在开始前，请确保满足以下条件：

- 在你的项目中实现基本的实时音视频功能，详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- [联系技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤-2]

参考如下流程图实现相关代码逻辑：

<DocsImage alt="实现流程" src="https://web-cdn.agora.io/docs-portal/img/rtc/media-relay.svg" displayWidth="70%" />

### 1. 开始跨频道媒体流转发 [#1-开始跨频道媒体流转发-2]

加入频道后，调用 `startOrUpdateChannelMediaRelay` 配置源频道和目标频道信息，开始转发媒体流。示例代码如下：

```swift
// 配置源频道信息
// 推荐将源频道的 uid 设为 0，由 SDK 随机分配一个 uid
// 注意 Token 与用户加入源频道时的 Token 不同，需要用源频道名和 uid = 0 重新生成
let config = AgoraChannelMediaRelayConfiguration()
config.sourceInfo = AgoraChannelMediaRelayInfo(token: nil)
isProcessing = true
// 配置目标频道信息
// 你可以将 uid 设为 0，由 SDK 随机分配一个 uid，或自行指定 uid，并确保其与目标频道中的所有 uid 不同
let destinationInfo = AgoraChannelMediaRelayInfo(token: nil)
config.setDestinationInfo(destinationInfo, forChannelName: destinationChannelName)
// 开始跨频道媒体流转发
agoraKit.startOrUpdateChannelMediaRelay(config)
```

### 2. 更新媒体流转发频道 [#2-更新媒体流转发频道-2]

成功调用 `startOrUpdateChannelMediaRelay` 后，如需将流转发到多个目标频道，或退出当前的转发频道，可以再次调用该方法添加或移除转发的目标频道。

:::info[信息]
更新后的配置会**全量替换**掉之前的配置。
:::

### 3. 暂停/恢复转发媒体流 [#3-暂停恢复转发媒体流-2]

开始跨频道转发媒体流后，调用 `pauseAllChannelMediaRelay` 可以暂停向所有目标频道转发媒体流。示例代码如下：

```swift
isPauseRelaying = true
agoraKit.pauseAllChannelMediaRelay()
```

暂停跨频道媒体流转发后，调用 `resumeAllChannelMediaRelay` 即可恢复向所有目标频道转发媒体流。示例代码如下：

```swift
isPauseRelaying = false
agoraKit.resumeAllChannelMediaRelay()
```

### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发-2]

成功开始跨频道媒体流转发后，可以调用 `stopChannelMediaRelay` 停止转发媒体流，一经停止，主播会退出所有目标频道。示例代码如下：

```swift
isProcessing = true
isPauseRelaying = false
agoraKit.stopChannelMediaRelay()
pauseRelayButton.isEnabled = false
```

:::info[信息]
如果该方法调用失败，可以调用 `leaveChannel` 离开频道，跨频道媒体流转发会自动停止。
:::

### 5. 监听跨频道媒体流状态 [#5-监听跨频道媒体流状态-2]

在跨频道媒体流转发过程中，SDK 会通过 `channelMediaRelayStateDidChange` 回调报告媒体流转发的状态，你可以参考状态码的含义实现相关的业务逻辑。示例代码如下：

```swift
func rtcEngine(_ engine: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) {
    LogUtils.log(message: "channelMediaRelayStateDidChange: \(state.rawValue) error \(error.rawValue)", level: .info)
    isProcessing = false
    switch state {
    case .running:
        isRelaying = true
    case .failure:
        showAlert(message: "Media Relay Failed: \(error.rawValue)")
        isRelaying = false
    case .idle:
        isRelaying = false
    default: break
    }
}
```

主要的状态码、错误码及其对应的媒体流转发状态如下：

| 媒体流转发状态 | 状态码和错误码 |
| ---------------- | ---------------- |
| 源频道开始向目标频道传输数据。  | `AgoraChannelMediaRelayStateRunning`(2) 和 `AgoraChannelMediaRelayErrorNone`(0)     |
| 跨频道媒体流转发出现异常。可根据[错误码](/zh-CN/api-reference/rtc/macos/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)进行排查。   |  `AgoraChannelMediaRelayStateFailure`(3) |
| 已停止媒体流转发。  | `AgoraChannelMediaRelayStateIdle`(0) 和 `AgoraChannelMediaRelayErrorNone`(0)  |

## 参考信息 [#参考信息-2]

### 开发注意事项 [#开发注意事项-2]

- 在直播场景中，只有角色为主播的用户才能调用 `startOrUpdateChannelMediaRelay` 开始跨频道媒体流转发。
- `startOrUpdateChannelMediaRelay` 必须在成功加入频道后调用，否则会报错。
- 一个频道内可以有多个主播转发媒体流，一个主播最多可以将媒体流转发至 6 个目标频道。
- 该功能不支持 String 型 `uid`，如需使用跨频道连麦功能，则要在普通连麦中也使用 Int 型 `uid`，否则跨频道连麦功能无法正常使用。

### 示例项目 [#示例项目-2]

声网提供了开源的跨频道媒体流转发示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">ChannelMediaRelay</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/API-Examples/blob/main/macOS/APIExample/Examples/Advanced/ChannelMediaRelay/ChannelMediaRelay.swift" />
  <Card title={<RepositoryCardTitle provider="github">ChannelMediaRelay</RepositoryCardTitle>} href="https://github.com/Shengwang-Community/API-Examples/blob/main/macOS/APIExample/Examples/Advanced/ChannelMediaRelay/ChannelMediaRelay.swift" />
</Cards>

### API 参考 [#api-参考-2]

- [`startOrUpdateChannelMediaRelay`](/zh-CN/api-reference/rtc/macos/cloud-media-relay/channel-media-relay#startorupdatechannelmediarelay)
- [`stopChannelMediaRelay`](/zh-CN/api-reference/rtc/macos/cloud-media-relay/channel-media-relay#api_irtcengine_stopchannelmediarelay)
- [`pauseAllChannelMediaRelay`](/zh-CN/api-reference/rtc/macos/cloud-media-relay/channel-media-relay#api_irtcengine_pauseallchannelmediarelay)
- [`resumeAllChannelMediaRelay`](/zh-CN/api-reference/rtc/macos/cloud-media-relay/channel-media-relay#api_irtcengine_resumeallchannelmediarelay)
- [`channelMediaRelayStateDidChange`](/zh-CN/api-reference/rtc/macos/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
- [`AgoraChannelMediaRelayConfiguration`](/zh-CN/api-reference/rtc/macos/class-channelmediarelayconfiguration)
- [`AgoraChannelMediaRelayInfo`](/zh-CN/api-reference/rtc/macos/class-channelmediainfo)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
跨频道媒体流转发，指 SDK 将源频道内主播的媒体流同时转发进多个目标频道，实现主播跨频道与其他主播进行实时互动的场景。其中：

- 频道中的所有主播可以看见彼此，并听到彼此的声音。
- 频道中的观众可以看到所有主播，并听到主播的声音。

该功能因其实时性和互动性，尤其适用于连麦 PK、在线合唱等直播场景，在增加直播趣味的同时，有效吸粉。

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件-3]

开始前，请确保你已满足以下条件：

- 参考[快速开始](/zh-CN/realtime-media/rtc/get-started/quick-start)在你的项目中实现基本的实时音视频功能。
- 联系[技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤-3]

你可以参考以下示例代码，其中的 `client` 是指通过 `AgoraRTC.createClient` 创建的本地客户端对象。

#### 1. 配置跨频道媒体流转发 [#1-配置跨频道媒体流转发]

调用 `createChannelMediaRelayConfiguration` 创建一个跨频道媒体流转发配置对象，并且设置源频道和目标频道的信息。

```javascript
const channelMediaConfig = AgoraRTC.createChannelMediaRelayConfiguration();
// 设置源频道信息
channelMediaConfig.setSrcChannelInfo({
  // 源频道名
  channelName: "srcChannel",
  // 源频道里需要转发的主播的 uid
  uid: <USER_UID>,
  // 需要用为 0 的 uid 和源频道名重新生成
  token: "yourSrcToken",
})
// 设置目标频道信息，可多次调用，最多设置 4 个目标频道
channelMediaConfig.addDestChannelInfo({
  // 目标频道名
  channelName: "destChannel1",
  // 用于标识目标频道中被转发的媒体流
  // uid 可为 0，也可自行设置，需确保与目标频道中的其他用户 ID 不同，防止造成互踢
  uid: 123,
  // 需要用 uid 和目标频道名生成
  token: "yourDestToken",
})
```

#### 2. 开始跨频道媒体流转发 [#2-开始跨频道媒体流转发]

在调用 `AgoraRTCClient.publish` 之后，调用 `startChannelMediaRelay` 开始跨频道媒体流转发。

```javascript
client.startChannelMediaRelay(channelMediaConfig).then(() => {
  console.log(`startChannelMediaRelay success`);
}).catch(e => {
  console.log(`startChannelMediaRelay failed`, e);
})
```

在跨频道媒体流转发过程中，SDK 会通过 `AgoraRTCClient.on("channel-media-relay-state")` 回调报告媒体流转发的状态码 `state` 和错误码 `code`， 通过 `AgoraRTCClient.on("channel-media-relay-event")` 回调报告媒体流转发的事件码。

#### 3. 更新媒体流转发频道 [#3-更新媒体流转发频道]

成功调用 `startChannelMediaRelay` 后，如需添加或移除目标频道，可以调用 `updateChannelMediaRelay` 更新目标频道。

```javascript
// 删除一个目标频道
channelMediaConfig.removeDestChannelInfo("destChannel1")
// 更新跨频道媒体流转发设置
client.updateChannelMediaRelay(channelMediaConfig).then(() => {
  console.log("updateChannelMediaRelay success");
}).catch(e => {
  console.log("updateChannelMediaRelay failed", e);
})
```

#### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发-3]

成功调用 `startChannelMediaRelay` 后，如需退出当前的转发状态，可以调用 `stopChannelMediaRelay`。

```javascript
client.stopChannelMediaRelay().then(() => {
  console.log("stop media relay success");
}).catch(e => {
  console.log("stop media relay failed", e);
})
```

## 参考信息 [#参考信息-3]

### 开发注意事项 [#开发注意事项-3]

- 该功能最多支持将媒体流转发至 4 个目标频道。转发过程中，如果想添加或删除目标频道，可以调用 `updateChannelMediaRelay` 方法。
- 该功能不支持 String 型用户名。
- 一个频道内可以有多个主播转发媒体流。哪个主播调用 `startChannelMediaRelay` 方法，SDK 就转发哪个主播的流。
- 在设置源频道信息 (`setSrcChannelInfo`) 时，`uid` 需要设置为主播的 UID；在设置目标频道信息 (`addDestChannelInfo`) 时，请确保 `uid` 设置与目标频道中主播的 UID 不同。我们建议将目标频道中的 `uid` 设置为 `0`，由服务器随机分配。
- 调用 `startChannelMediaRelay` 或 `updateChannelMediaRelay` 成功转发媒体流后，目标频道的用户会收到 `AgoraRTCClient.on("user-published")` 回调；媒体流转发过程中，如果目标频道的主播掉线或离开频道，源频道的主播会收到 `AgoraRTCClient.on("user-left")` 回调。
- 在成功调用 `startChannelMediaRelay` 方法后，如果想再次调用该方法，必须先调用 `stopChannelMediaRelay` 方法退出当前的转发状态。

### API 参考 [#api-参考-3]

- [`startChannelMediaRelay`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#startchannelmediarelay)
- [`updateChannelMediaRelay`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#updatechannelmediarelay)
- [`stopChannelMediaRelay`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#stopchannelmediarelay)
- [`AgoraRTCClient.on("channel-media-relay-state")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_channel_media_relay_state)
- [`AgoraRTCClient.on("channel-media-relay-event")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_channel_media_relay_event)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="windows" />
在实时互动场景下，跨频道媒体流转发功能可实现将主播角色的媒体流从源频道同时转发到多个目标频道，具体如下：

- 所有主播发布并接收彼此的音视频流，进行跨频道实时互动。
- 观众可以接收到所有主播的音视频流，同时观看多位主播互动。

该功能因其实时性和互动性，能够丰富直播玩法，尤其适用于连麦 PK、在线合唱等直播场景，为观众带来更好的观看体验的同时，也为主播带来更多的流量和收益。

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件-4]

在开始前，请确保满足以下条件：

- 在你的项目中实现基本的实时音视频功能，详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- [联系技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤-4]

参考如下流程图实现相关代码逻辑：

<DocsImage alt="实现流程" src="https://web-cdn.agora.io/docs-portal/img/rtc/media-relay.svg" displayWidth="70%" />

### 1. 开始跨频道媒体流转发 [#1-开始跨频道媒体流转发-3]

加入频道后，调用 `startOrUpdateChannelMediaRelay` 配置源频道和目标频道信息，开始转发媒体流。示例代码如下：

```cpp
// 配置源频道信息
ChannelMediaInfo *m_srcInfo = new ChannelMediaInfo;
m_srcInfo->channelName = new char[szChannelId.size() + 1];
strcpy_s(const_cast<char *>(m_srcInfo->channelName), szChannelId.size() + 1,
         szChannelId.data());
// 注意 Token 与用户加入源频道时的 Token 不同，需要用源频道名和 uid = 0 重新生成
m_srcInfo->token = APP_TOKEN;
// 推荐将源频道的 uid 设为 0，由 SDK 随机分配一个 uid
m_srcInfo->uid = 0;

// 配置目标频道信息
int nDestCount = m_vecChannelMedias.size();
ChannelMediaInfo *lpDestInfos = new ChannelMediaInfo[nDestCount];
for (int nIndex = 0; nIndex < nDestCount; nIndex++) {
    lpDestInfos[nIndex].channelName = m_vecChannelMedias[nIndex].channelName;
    lpDestInfos[nIndex].token = m_vecChannelMedias[nIndex].token;
    // 你可以将 uid 设为 0，由 SDK 随机分配一个 uid，或自行指定
    // uid，并确保其与目标频道中的所有 uid 不同
    lpDestInfos[nIndex].uid = m_vecChannelMedias[nIndex].uid;
}

ChannelMediaRelayConfiguration cmrc;
cmrc.srcInfo = m_srcInfo;
cmrc.destInfos = lpDestInfos;
cmrc.destCount = nDestCount;
int ret = 0;
// 开始跨频道媒体流转发
ret = m_rtcEngine->startOrUpdateChannelMediaRelay(cmrc);
```

### 2. 更新媒体流转发的频道 [#2-更新媒体流转发的频道]

成功调用 `startOrUpdateChannelMediaRelay` 后，如需将流转发到多个目标频道，或退出当前的转发频道，可以再次调用该方法添加或移除转发的目标频道。

:::info[信息]
更新后的配置会**全量替换**掉之前的配置。
:::

### 3. 暂停/恢复转发媒体流 [#3-暂停恢复转发媒体流-3]

开始跨频道转发媒体流后，调用 `pauseAllChannelMediaRelay` 可以暂停向所有目标频道转发媒体流。示例代码如下：

```cpp
m_rtcEngine->pauseAllChannelMediaRelay();
```

暂停跨频道媒体流转发后，调用 `resumeAllChannelMediaRelay` 即可恢复向所有目标频道转发媒体流。示例代码如下：

```cpp
m_rtcEngine->resumeAllChannelMediaRelay();
```

### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发-4]

成功开始跨频道媒体流转发后，可以调用 `stopChannelMediaRelay` 停止转发媒体流，一经停止，主播会退出所有目标频道。示例代码如下：

```cpp
m_rtcEngine->stopChannelMediaRelay();
m_lstInfo.AddString(_T("stopChannelMediaRelay"));
m_btnStartMediaRelay.SetWindowText(CrossChannelStartMediaRelay);
```

:::info[信息]
如果该方法调用失败，可以调用 `leaveChannel` 离开频道，跨频道媒体流转发会自动停止。
:::

### 5. 监听跨频道媒体流状态 [#5-监听跨频道媒体流状态-3]

在跨频道媒体流转发过程中，SDK 会通过 `onChannelMediaRelayStateChanged` 回调报告媒体流转发的状态，你可以参考状态码的含义实现相关的业务逻辑。示例代码如下：

```cpp
class CAgoraCrossChannelEventHandler : public IRtcEngineEventHandler {
    virtual void onChannelMediaRelayStateChanged(
        CHANNEL_MEDIA_RELAY_STATE state,
        CHANNEL_MEDIA_RELAY_ERROR code) override {
        if (m_hMsgHanlder)
            ::PostMessage(m_hMsgHanlder,
                          WM_MSGID(EID_CHANNEL_MEDIA_RELAY_STATE_CHNAGENED),
                          state, code);
    }
};
```

主要的状态码、错误码及其对应的媒体流转发状态如下：

| 媒体流转发状态 | 状态码和错误码 |
| ---------------- | ---------------- |
| 源频道开始向目标频道传输数据。  | `RELAY_STATE_RUNNING`(2) 和 `RELAY_OK`(0)     |
| 跨频道媒体流转发出现异常。可根据[错误码](/zh-CN/api-reference/rtc/cpp-all-platforms/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)进行排查。    | `RELAY_STATE_FAILURE`(3)    |
| 已停止媒体流转发。     | `RELAY_STATE_IDLE`(0) 和 `RELAY_OK`(0)      |

## 参考信息 [#参考信息-4]

### 开发注意事项 [#开发注意事项-4]

- 在直播场景中，只有角色为主播的用户才能调用 `startOrUpdateChannelMediaRelay` 开始跨频道媒体流转发。
- `startOrUpdateChannelMediaRelay` 必须在成功加入频道后调用，否则会报错。
- 一个频道内可以有多个主播转发媒体流，一个主播最多可以将媒体流转发至 6 个目标频道。
- 该功能不支持 `String` 型 `uid`，如需使用跨频道连麦功能，则要在普通连麦中也使用 `Int` 型 `uid`，否则跨频道连麦功能无法正常使用。

### API 参考 [#api-参考-4]

- [`startOrUpdateChannelMediaRelay`](/zh-CN/api-reference/rtc/cpp-all-platforms/cloud-media-relay/channel-media-relay#startorupdatechannelmediarelay)
- [`stopChannelMediaRelay`](/zh-CN/api-reference/rtc/cpp-all-platforms/cloud-media-relay/channel-media-relay#api_irtcengine_stopchannelmediarelay)
- [`pauseAllChannelMediaRelay`](/zh-CN/api-reference/rtc/cpp-all-platforms/cloud-media-relay/channel-media-relay#api_irtcengine_pauseallchannelmediarelay)
- [`resumeAllChannelMediaRelay`](/zh-CN/api-reference/rtc/cpp-all-platforms/cloud-media-relay/channel-media-relay#api_irtcengine_resumeallchannelmediarelay)
- [`onChannelMediaRelayStateChanged`](/zh-CN/api-reference/rtc/cpp-all-platforms/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
- [`ChannelMediaRelayConfiguration`](/zh-CN/api-reference/rtc/cpp-all-platforms/class-channelmediarelayconfiguration)
- [`ChannelMediaInfo`](/zh-CN/api-reference/rtc/cpp-all-platforms/class-channelmediainfo)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="electron" />
在实时互动场景下，跨频道媒体流转发功能可实现主播角色的媒体流从源频道同时转发进多个目标频道，其中：

- 所有主播发布并接收彼此的音视频流，进行跨频道实时互动
- 观众可以接收到所有主播的音视频流，同时观看多位主播互动

该功能因其实时性和互动性，能够丰富直播玩法，尤其适用于连麦 PK、在线合唱等直播场景，为观众带来更好的观看体验的同时，也为主播带来更多的流量和收益。

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件-5]

在开始前，请确保满足以下条件：

- 在你的项目中实现基本的实时音视频功能，详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- [联系技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤-5]

参考如下流程图实现相关代码逻辑：

<DocsImage alt="实现流程" src="https://web-cdn.agora.io/docs-portal/img/rtc/media-relay.svg" displayWidth="70%" />

### 1. 开始跨频道媒体流转发 [#1-开始跨频道媒体流转发-4]

加入频道后，调用 `startOrUpdateChannelMediaRelay` 配置源频道和目标频道信息，开始转发媒体流。示例代码如下：

```typescript
const srcChannelId = "srcChannel";
const destChannelId = "destChannel";
const uid = 0;
const token = "insert-your-token";

// 开始跨频道媒体流转发
rtcEngine.startOrUpdateChannelMediaRelay({
  // 配置源频道信息 srcInfo
  srcInfo: {
    channelName: srcChannelId,
    uid: uid,
    token: token,
  },
  // 配置目标频道信息 destInfos
  destInfos: [
    {
      channelName: destChannelId,
      token: '', // 能加入目标频道的 token
      uid: 0, // SDK 随机分配 uid
    },
  ],
  // 目标频道数量
  destCount: 1,
});
```

### 2. 更新媒体流转发的频道 [#2-更新媒体流转发的频道-1]

成功调用 `startOrUpdateChannelMediaRelay` 后，如需将流转发到多个目标频道，或退出当前的转发频道，可以再次调用该方法添加或移除转发的目标频道。

:::info[信息]
更新后的配置会**全量替换**掉之前的配置。
:::

### 3. 暂停/恢复转发媒体流 [#3-暂停恢复转发媒体流-4]

开始跨频道转发媒体流后，调用 `pauseAllChannelMediaRelay` 可以暂停向所有目标频道转发媒体流。示例代码如下：

```typescript
rtcEngine.pauseAllChannelMediaRelay();
```

暂停跨频道媒体流转发后，调用 `resumeAllChannelMediaRelay` 即可恢复向所有目标频道转发媒体流。示例代码如下：

```typescript
rtcEngine.resumeAllChannelMediaRelay();
```

### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发-5]

成功开始跨频道媒体流转发后，可以调用 `stopChannelMediaRelay` 停止转发媒体流，一经停止，主播会退出所有目标频道。示例代码如下：

```typescript
rtcEngine.stopChannelMediaRelay();
```

:::info[信息]
如果该方法调用失败，可以调用 `leaveChannel` 离开频道，跨频道媒体流转发会自动停止。
:::

### 5. 监听跨频道媒体流状态 [#5-监听跨频道媒体流状态-4]

在跨频道媒体流转发过程中，SDK 会通过 `onChannelMediaRelayStateChanged` 回调报告媒体流转发的状态，你可以参考状态码的含义实现相关的业务逻辑。示例代码如下：

```typescript
// 注册事件回调
rtcEngine.registerEventHandler(
  onChannelMediaRelayStateChanged: (state: ChannelMediaRelayState, code: ChannelMediaRelayError) => {
    console.log(`跨频道媒体流转发状态：${state}，错误码：${code}`);
  },
);
```

主要的状态码及其对应的媒体流转发状态如下：

| 媒体流转发状态 | 状态码 |
| ---------------- | ---------------- |
| 源频道开始向目标频道传输数据。  | `RelayStateRunning`(2) 和 `RelayOk`(0)     |
| 跨频道媒体流转发出现异常。可根据[错误码](/zh-CN/api-reference/rtc/electron/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)进行排查。    | `RelayStateFailure`(3)    |
| 已停止媒体流转发。     | `RelayStateIdle`(0) 和 `RelayOk`(0)      |

## 参考信息 [#参考信息-5]

### 示例项目 [#示例项目-3]

声网提供了跨频道媒体流转发的示例项目供你参考。你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">ChannelMediaRelay</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/Electron-SDK/blob/main/example/src/renderer/examples/advanced/ChannelMediaRelay/ChannelMediaRelay.tsx" />
  <Card title={<RepositoryCardTitle provider="github">ChannelMediaRelay</RepositoryCardTitle>} href="https://github.com/AgoraIO-Extensions/Electron-SDK/blob/main/example/src/renderer/examples/advanced/ChannelMediaRelay/ChannelMediaRelay.tsx" />
</Cards>

### 开发注意事项 [#开发注意事项-5]

- 在直播场景中，只有角色为主播的用户才能调用 `startOrUpdateChannelMediaRelay` 开始跨频道媒体流转发。
- `startOrUpdateChannelMediaRelay` 必须在成功加入频道后调用，否则会报错。
- 一个频道内可以有多个主播转发媒体流，一个主播最多可以将媒体流转发至 6 个目标频道。
- 该功能不支持 String 型 `uid`，如需使用跨频道连麦功能，则要在普通连麦中也使用 Int 型 `uid`，否则跨频道连麦功能无法正常使用。

### API 参考 [#api-参考-5]

- [`startOrUpdateChannelMediaRelay`](/zh-CN/api-reference/rtc/electron/cloud-media-relay/channel-media-relay#startorupdatechannelmediarelay)
- [`stopChannelMediaRelay`](/zh-CN/api-reference/rtc/electron/cloud-media-relay/channel-media-relay#api_irtcengine_stopchannelmediarelay)
- [`pauseAllChannelMediaRelay`](/zh-CN/api-reference/rtc/electron/cloud-media-relay/channel-media-relay#api_irtcengine_pauseallchannelmediarelay)
- [`resumeAllChannelMediaRelay`](/zh-CN/api-reference/rtc/electron/cloud-media-relay/channel-media-relay#api_irtcengine_resumeallchannelmediarelay)
- [`onChannelMediaRelayStateChanged`](/zh-CN/api-reference/rtc/electron/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
- [`ChannelMediaRelayConfiguration`](/zh-CN/api-reference/rtc/electron/class-channelmediarelayconfiguration)
- [`ChannelMediaInfo`](/zh-CN/api-reference/rtc/electron/class-channelmediainfo)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
在实时互动场景下，跨频道媒体流转发功能可实现将主播角色的媒体流从源频道同时转发到多个目标频道，具体如下：

- 所有主播发布并接收彼此的音视频流，进行跨频道实时互动。
- 观众可以接收到所有主播的音视频流，同时观看多位主播互动。

该功能因其实时性和互动性，能够丰富直播玩法，尤其适用于连麦 PK、在线合唱等直播场景，为观众带来更好的观看体验的同时，也为主播带来更多的流量和收益。

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件-6]

在开始前，请确保满足以下条件：

- 在你的项目中实现基本的实时音视频功能，详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- [联系技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤-6]

参考如下流程图实现相关代码逻辑：

<DocsImage alt="实现流程" src="https://web-cdn.agora.io/docs-portal/img/rtc/media-relay.svg" displayWidth="70%" />

### 1. 开始跨频道媒体流转发 [#1-开始跨频道媒体流转发-5]

加入频道后，调用 `StartOrUpdateChannelMediaRelay` 配置源频道和目标频道信息，开始转发媒体流。示例代码如下：

```csharp
private void OnStartButtonClick()
{
    ChannelMediaRelayConfiguration config = new ChannelMediaRelayConfiguration();
    // 配置源频道信息
    config.srcInfo = new ChannelMediaInfo
    {
        channelName = this._appIdInput.channelName,
        // 推荐将源频道的 uid 设为 0，由 SDK 随机分配一个 uid
        uid = 0,
        // 注意 Token 与用户加入源频道时的 Token 不同，需要用源频道名和 uid = 0 重新生成
        token = this._appIdInput.token
    };

    // 配置目标频道信息，最多支持将媒体流转发至 6 个目标频道
    config.destInfos = new ChannelMediaInfo[1];
    config.destInfos[0] = new ChannelMediaInfo
    {
        channelName = this._appIdInput.channelName + "_2",
        // 你可以将 uid 设为 0，由 SDK 随机分配一个 uid，或自行指定 uid，并确保其与目标频道中的所有 uid 不同
        uid = 0,
        token = this._appIdInput.token
    };
    config.destCount = 1;

    // 开始跨频道媒体流转发
    var nRet = RtcEngine.StartOrUpdateChannelMediaRelay(config);
    this.Log.UpdateLog("StartOrUpdateChannelMediaRelay nRet:" + nRet + " new ChannelName: " + this._appIdInput.channelName + "_2");
}
```

### 2. 更新媒体流转发的频道 [#2-更新媒体流转发的频道-2]

成功调用 `StartOrUpdateChannelMediaRelay` 后，如需将流转发到多个目标频道，或退出当前的转发频道，可以再次调用该方法添加或移除转发的目标频道。

:::info[信息]
更新后的配置会**全量替换**掉之前的配置。
:::

### 3. 暂停/恢复转发媒体流 [#3-暂停恢复转发媒体流-5]

开始跨频道转发媒体流后，调用 `PauseAllChannelMediaRelay` 可以暂停向所有目标频道转发媒体流。示例代码如下：

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

暂停跨频道媒体流转发后，调用 `ResumeAllChannelMediaRelay` 即可恢复向所有目标频道转发媒体流。示例代码如下：

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

### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发-6]

成功开始跨频道媒体流转发后，可以调用 `StopChannelMediaRelay` 停止转发媒体流，一经停止，主播会退出所有目标频道。示例代码如下：

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

:::info[信息]
如果该方法调用失败，可以调用 `LeaveChannel` 离开频道，跨频道媒体流转发会自动停止。
:::

### 5. 监听跨频道媒体流状态 [#5-监听跨频道媒体流状态-5]

在跨频道媒体流转发过程中，SDK 会通过 `OnChannelMediaRelayStateChanged` 回调报告媒体流转发的状态，你可以参考状态码的含义实现相关的业务逻辑。示例代码如下：

```csharp
public override void OnChannelMediaRelayStateChanged(int state, int code)
{
    _channelMediaRelay.Log.UpdateLog(string.Format("OnChannelMediaRelayStateChanged state: {0}, code: {1}", state, code));
}
```

主要的状态码、错误码及其对应的媒体流转发状态如下：

| 媒体流转发状态 | 状态码和错误码 |
| ---------------- | ---------------- |
| 源频道开始向目标频道传输数据。  | `RELAY_STATE_RUNNING`(2) 和 `RELAY_OK`(0)     |
| 跨频道媒体流转发出现异常。可根据[错误码](/zh-CN/api-reference/rtc/unity/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)进行排查。    | `RELAY_STATE_FAILURE`(3)    |
| 已停止媒体流转发。     | `RELAY_STATE_IDLE`(0) 和 `RELAY_OK`(0)      |

## 参考信息 [#参考信息-6]

### 开发注意事项 [#开发注意事项-6]

- 在直播场景中，只有角色为主播的用户才能调用 `StartOrUpdateChannelMediaRelay` 开始跨频道媒体流转发。
- `StartOrUpdateChannelMediaRelay` 必须在成功加入频道后调用，否则会报错。
- 一个频道内可以有多个主播转发媒体流，一个主播最多可以将媒体流转发至 6 个目标频道。
- 该功能不支持 `String` 型 `uid`，如需使用跨频道连麦功能，则要在普通连麦中也使用 `Int` 型 `uid`，否则跨频道连麦功能无法正常使用。

### 示例项目 [#示例项目-4]

声网提供了开源的跨频道媒体流转发示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">ChannelMediaRelay</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/Agora-Unity-Quickstart/blob/main/API-Example-Unity/Assets/API-Example/Examples/Advanced/ChannelMediaRelay/ChannelMediaRelay.cs" />
  <Card title={<RepositoryCardTitle provider="github">ChannelMediaRelay</RepositoryCardTitle>} href="https://github.com/AgoraIO-Extensions/Agora-Unity-Quickstart/blob/main/API-Example-Unity/Assets/API-Example/Examples/Advanced/ChannelMediaRelay/ChannelMediaRelay.cs" />
</Cards>

### API 参考 [#api-参考-6]

- [`StartOrUpdateChannelMediaRelay`](/zh-CN/api-reference/rtc/unity/cloud-media-relay/channel-media-relay#startorupdatechannelmediarelay)
- [`StopChannelMediaRelay`](/zh-CN/api-reference/rtc/unity/cloud-media-relay/channel-media-relay#api_irtcengine_stopchannelmediarelay)
- [`PauseAllChannelMediaRelay`](/zh-CN/api-reference/rtc/unity/cloud-media-relay/channel-media-relay#api_irtcengine_pauseallchannelmediarelay)
- [`ResumeAllChannelMediaRelay`](/zh-CN/api-reference/rtc/unity/cloud-media-relay/channel-media-relay#api_irtcengine_resumeallchannelmediarelay)
- [`OnChannelMediaRelayStateChanged`](/zh-CN/api-reference/rtc/unity/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
- [`ChannelMediaRelayConfiguration`](/zh-CN/api-reference/rtc/unity/class-channelmediarelayconfiguration)
- [`ChannelMediaInfo`](/zh-CN/api-reference/rtc/unity/class-channelmediainfo)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="react-native" />
在实时互动场景下，跨频道媒体流转发功能可实现主播角色的媒体流从源频道同时转发进多个目标频道，其中：

- 所有主播发布并接收彼此的音视频流，进行跨频道实时互动
- 观众可以接收到所有主播的音视频流，同时观看多位主播互动

该功能因其实时性和互动性，能够丰富直播玩法，尤其适用于连麦 PK、在线合唱等直播场景，为观众带来更好的观看体验的同时，也为主播带来更多的流量和收益。

:::info[信息]
跨频道媒体流享受声网[每月一万分钟免费](/zh-CN/reference/faq/account/billing_free)政策。超出免费额度的部分，计费详情请参考[跨频道媒体流转发计费](/zh-CN/realtime-media/rtc/reference/billing-strategy#跨频道媒体流转发)。
:::

## 前提条件 [#前提条件-7]

在开始前，请确保满足以下条件：

- 在你的项目中实现基本的实时音视频功能，详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- [联系技术支持](https://ticket.shengwang.cn/)开通跨频道媒体流转发功能。

## 实现步骤 [#实现步骤-7]

参考如下流程图实现相关代码逻辑：

<DocsImage alt="实现流程" src="https://web-cdn.agora.io/docs-portal/img/rtc/media-relay.svg" displayWidth="70%" />

### 1. 开始跨频道媒体流转发 [#1-开始跨频道媒体流转发-6]

加入频道后，调用 `startOrUpdateChannelMediaRelay` 配置源频道和目标频道信息，开始转发媒体流。示例代码如下：

```typescript
const srcChannelId = "srcChannel";
const destChannelId = "destChannel";
const uid = 0;
const token = "insert-your-token";

// 开始跨频道媒体流转发
rtcEngine.startOrUpdateChannelMediaRelay({
  // 配置源频道信息 srcInfo
  srcInfo: {
    channelName: srcChannelId,
    uid: uid,
    token: token,
  },
  // 配置目标频道信息 destInfos
  destInfos: [
    {
      channelName: destChannelId,
      token: '', // 能加入目标频道的 token
      uid: 0, // SDK 随机分配 uid
    },
  ],
  // 目标频道数量
  destCount: 1,
});
```

### 2. 更新媒体流转发的频道 [#2-更新媒体流转发的频道-3]

成功调用 `startOrUpdateChannelMediaRelay` 后，如需将流转发到多个目标频道，或退出当前的转发频道，可以再次调用该方法添加或移除转发的目标频道。

:::info[信息]
更新后的配置会**全量替换**掉之前的配置。
:::

### 3. 暂停/恢复转发媒体流 [#3-暂停恢复转发媒体流-6]

开始跨频道转发媒体流后，调用 `pauseAllChannelMediaRelay` 可以暂停向所有目标频道转发媒体流。示例代码如下：

```typescript
rtcEngine.pauseAllChannelMediaRelay();
```

暂停跨频道媒体流转发后，调用 `resumeAllChannelMediaRelay` 即可恢复向所有目标频道转发媒体流。示例代码如下：

```typescript
rtcEngine.resumeAllChannelMediaRelay();
```

### 4. 停止跨频道媒体流转发 [#4-停止跨频道媒体流转发-7]

成功开始跨频道媒体流转发后，可以调用 `stopChannelMediaRelay` 停止转发媒体流，一经停止，主播会退出所有目标频道。示例代码如下：

```typescript
rtcEngine.stopChannelMediaRelay();
```

:::info[信息]
如果该方法调用失败，可以调用 `leaveChannel` 离开频道，跨频道媒体流转发会自动停止。
:::

### 5. 监听跨频道媒体流状态 [#5-监听跨频道媒体流状态-6]

在跨频道媒体流转发过程中，SDK 会通过 `onChannelMediaRelayStateChanged` 回调报告媒体流转发的状态，你可以参考状态码的含义实现相关的业务逻辑。示例代码如下：

```typescript
// 注册事件回调
rtcEngine.registerEventHandler(
  onChannelMediaRelayStateChanged: (state: ChannelMediaRelayState, code: ChannelMediaRelayError) => {
    console.log(`跨频道媒体流转发状态：${state}，错误码：${code}`);
  },
);
```

主要的状态码及其对应的媒体流转发状态如下：

| 媒体流转发状态 | 状态码 |
| ---------------- | ---------------- |
| 源频道开始向目标频道传输数据。  | `RelayStateRunning`(2) 和 `RelayOk`(0)     |
| 跨频道媒体流转发出现异常。可根据[错误码](/zh-CN/api-reference/rtc/react-native/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)进行排查。    | `RelayStateFailure`(3)    |
| 已停止媒体流转发。     | `RelayStateIdle`(0) 和 `RelayOk`(0)      |

## 参考信息 [#参考信息-7]

### 示例项目 [#示例项目-5]

声网提供了跨频道媒体流转发的示例项目供你参考。你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">ChannelMediaRelay</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/react-native-agora/tree/main/example/src/examples/advanced/ChannelMediaRelay/ChannelMediaRelay.tsx" />
  <Card title={<RepositoryCardTitle provider="github">ChannelMediaRelay</RepositoryCardTitle>} href="https://github.com/AgoraIO-Extensions/react-native-agora/blob/main/examples/legacy/src/examples/advanced/ChannelMediaRelay/ChannelMediaRelay.tsx" />
</Cards>

### 开发注意事项 [#开发注意事项-7]

- 在直播场景中，只有角色为主播的用户才能调用 `startOrUpdateChannelMediaRelay` 开始跨频道媒体流转发。
- `startOrUpdateChannelMediaRelay` 必须在成功加入频道后调用，否则会报错。
- 一个频道内可以有多个主播转发媒体流，一个主播最多可以将媒体流转发至 6 个目标频道。
- 该功能不支持 String 型 `uid`，如需使用跨频道连麦功能，则要在普通连麦中也使用 Int 型 `uid`，否则跨频道连麦功能无法正常使用。

### API 参考 [#api-参考-7]

- [`startOrUpdateChannelMediaRelay`](/zh-CN/api-reference/rtc/react-native/cloud-media-relay/channel-media-relay#startorupdatechannelmediarelay)
- [`stopChannelMediaRelay`](/zh-CN/api-reference/rtc/react-native/cloud-media-relay/channel-media-relay#api_irtcengine_stopchannelmediarelay)
- [`pauseAllChannelMediaRelay`](/zh-CN/api-reference/rtc/react-native/cloud-media-relay/channel-media-relay#api_irtcengine_pauseallchannelmediarelay)
- [`resumeAllChannelMediaRelay`](/zh-CN/api-reference/rtc/react-native/cloud-media-relay/channel-media-relay#api_irtcengine_resumeallchannelmediarelay)
- [`onChannelMediaRelayStateChanged`](/zh-CN/api-reference/rtc/react-native/cloud-media-relay/channel-media-relay#callback_irtcengineeventhandler_onchannelmediarelaystatechanged)
- [`ChannelMediaRelayConfiguration`](/zh-CN/api-reference/rtc/react-native/class-channelmediarelayconfiguration)
- [`ChannelMediaInfo`](/zh-CN/api-reference/rtc/react-native/class-channelmediainfo)
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
