You need to enable JavaScript to run this app.
文档中心
实时音视频

实时音视频

复制全文
下载 pdf
开发指南
跨房间转发媒体流
复制全文
下载 pdf
跨房间转发媒体流

跨房间转发媒体流,指可见用户的媒体流可以同时转发到多个 RTC 房间。转发目标房间的数量在 RTC 侧没有限制。
使用转发媒体流功能并不会产生额外的费用,与其他音视频通话遵循相同的计费原则,详见音视频通话计费

适用场景

本功能适用于以下场景,观众在原来的房间中就能够接收到来自其他房间主播的媒体流。

  • 主播连麦 PK:接受连麦邀请后,主播 A 的音视频流可以转发到主播 B 所在的房间,同时,B 的音视频流也可以转发到 A 房间。观众和主播均无需离开原有房间,即可观赏到两位主播连麦 PK 的音视频内容。
  • 子母直播间:母直播间的音视频为集团总部统一制作,可以同时转发到多个子直播间。子直播间的主播们直接转播母直播间内容,边与用户进行互动,也可以合入自己的个性化内容后进行直播。

前提条件

你已经集成 RTC SDK,实现了基本的音视频通话。
支持跨房间转发功能的 SDK 详见API 及回调

名词解释

转推流:跨房间转发的媒体流
目标房间:转推流到达的房间

功能实现

以下时序图以 Android SDK 中的 API 名称为例。不同端的 SDK 中 API 或回调名称可能略有不同,以 API 及回调为准。

Image

1. 加入房间

创建引擎实例并加入房间,本地用户默认对他人可见。

const list = [
  {
    "lang": "typescript",
    "text": `import VERTC, { ForwardStreamState } from '@volcengine/rtc';
// 创建引擎实例
const engine = VERTC.createEngine('appid');
// 加入房间
await engine.joinRoom('roomId_token', 'roomId', { userId: 'userid' });`,
    "selected": true,
  },
  {
    "lang": "java",
    "text": `// 创建引擎
    EngineConfig config = new EngineConfig();
    config.appID = appId;
    config.context = applicationContext;
    rtcEngine = RTCEngine.createRTCEngine(config, engineEventHandler);`, 


    // 加入房间
    private void joinRoom(String roomId) {
        rtcRoom = rtcEngine.createRTCRoom(roomId);
        rtcRoom.setRTCRoomEventHandler(roomEventHandler);
        String token = requestRoomToken(roomId);
        // 用户信息
        UserInfo userInfo = new UserInfo(localUid, "");
        // 设置房间配置
        boolean isAutoPublishAudio = true;
        boolean isAutoPublishVideo = true;
        boolean isAutoSubscribeAudio = true;
        boolean isAutoSubscribeVideo = true;
        RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_LIVE, isAutoPublishAudio, isAutoPublishVideo, isAutoSubscribeAudio, isAutoSubscribeVideo);
        // 加入房间
        rtcRoom.joinRoom(token, userInfo, true, roomConfig);
    }`, 
  },
  {
    "lang": "swift",
    "text": `//创建引擎
    let engineCfg = ByteRTCEngineConfig.init()
    engineCfg.appID = appId
    //私有参数,可以填空
    engineCfg.parameters = [:]
    //delegate: 用于接收 ByteRTCEngine 回调的接口实例
    self.rtcEngine = ByteRTCEngine.createRTCEngine(engineCfg, delegate: self)`,  

    //创建房间
    self.rtcRoom = self.rtcEngine?.createRTCRoom(roomId)
    self.rtcRoom?.delegate = self
    
    //加入房间
    let userInfo = ByteRTCUserInfo.init()
    userInfo.userId = userId
    
    let roomCfg = ByteRTCRoomConfig.init()
    roomCfg.isPublishAudio = true
    roomCfg.isPublishVideo = true
    roomCfg.isAutoSubscribeAudio = true
    roomCfg.isAutoSubscribeVideo = true
    self.rtcRoom1?.joinRoom(token, userInfo: userInfo, userVisibility: true, roomConfig: roomCfg)`, 
  },
  {
    "lang": "cpp",
    "text": `//创建引擎
    bytertc::EngineConfig conf;
    conf.app_id = g_appid.c_str();
    engine = bytertc::IRTCEngine::createRTCEngine(conf, handler.get());
engine->startAudioCapture();
engine->startVideoCapture();

//创建房间
bytertc::IRTCRoom *room = engine->createRTCRoom(roomid);
room->setRTCRoomEventHandler(room_handler);

bytertc::UserInfo info;
bytertc::RTCRoomConfig config;
info.uid = str_uid.c_str();
config.is_publish_audio = true;
config.is_publish_video = true;
config.is_auto_subscribe_audio = true;
config.is_auto_subscribe_video = true;
int ret = room->joinRoom(token, userinfo, true, config);`, 
  },
]
return (<PreCodeTabs list={list} />);

参考 构建 RTC 应用 获取详细步骤。

2. 开启跨房间转发

  • startForwardStreamToRooms 中所传入的 token 是与目标房间相对应的 token,而非当前用户所在房间的 token。
  • 在调用 stopForwardStreamToRooms 前,仅可调用一次 startForwardStreamToRooms
  • 向开启音频选路的房间转发媒体流,该媒体流可能无法被播放。
// 管理目标房间列表
const targetRoomList: string[] = [];

// 开启跨房间转发媒体流
const startResult = await engine.startForwardStreamToRooms([
  { roomId: 'targetRoomIdA', token: 'targetRoomIdA_token' },
  // 可以同时指定多个目标房间
  { roomId: 'targetRoomIdB', token: 'targetRoomIdB_token' }
]);

// 处理调用结果
startResult.forEach(item => {
  if (item.state === ForwardStreamState.FORWARD_STREAM_STATE_SUCCESS) {
    // 保存成功的目标房间
    targetRoomList.push(item.roomId);
  } else {
    // 根据错误码进行对应处理
    console.error(item.error);
  }
});

3. 更新转发配置

更新跨房间媒体流转发请求。
如果调用 updateForwardStreamToRooms 时不传入任何参数或者传空值,会停止所有正在转发的目标房间流。此时仍需要调用 stopForwardStreamToRooms 后才可以再次调用 startForwardStreamToRooms

// 更新跨房间转发媒体流的目标房间列表
const updateResult = await engine.updateForwardStreamToRooms([
  // 列表中不包含 targetRoomIdA,会停止该房间的转发媒体流
  // targetRoomIdB 在之前的目标房间列表中,会更新对应的 token。
  // 在暂停状态下调用更新无法对 token 进行校验。在调用恢复 resumeForwardStreamToAllRooms  后才会进行 token 校验。
  { roomId: 'targetRoomIdB', token: 'targetRoomIdB_new_token' },
  // targetRoomIdC 不在之前的目标房间列表中,会开启向该房间转发媒体流
  { roomId: 'targetRoomIdC', token: 'targetRoomIdC_token' }
]);

// 处理调用结果
// 停止转发的目标房间也会在 updateForwardStreamToRooms 的返回结果中。
updateResult.forEach(item => {
  if (item.state === ForwardStreamState.FORWARD_STREAM_STATE_SUCCESS) {
    if (!['targetRoomIdB', 'targetRoomIdC'].includes(item.roomId)) {
      // 不在请求列表中,但在返回结果中的应当删除
      targetRoomList.splice(targetRoomList.indexOf(item.roomId), 1);
    } else if (!targetRoomList.includes(item.roomId)) {
      // 不在已有房间中,需要新增
      targetRoomList.push(item.roomId);
    }
  } else {
    // 根据错误码进行对应处理
    console.error(item.error);
  }
});

4. 暂停和恢复转发

暂停与恢复向所有目标房间转发媒体流。
在调用 resumeForwardStreamToAllRooms 恢复媒体流转发前,仅可调用一次 pauseForwardStreamToAllRooms

// 暂停跨房间转发媒体流的目标房间列表
await engine.pauseForwardStreamToAllRooms();

// 恢复跨房间转发媒体流的目标房间列表
const result = await engine.resumeForwardStreamToAllRooms();

// 处理调用结果
result.forEach(item => {
  if (item.state !== ForwardStreamState.FORWARD_STREAM_STATE_SUCCESS) {
    // 根据错误码进行对应处理
    console.error(item.error);
  }
});

5. 停止转发

停止向所有目标房间转发媒体流。

await engine.stopForwardStreamToRooms();

6. 回调

监听 onForwardStreamStateChanged,感知跨房间转发媒体流状态。

  • 转发媒体流至目标房间和进入目标房间,将分别触发一次以下回调: onUserJoinonUserLeaveonUserPublishStream / onUserPublishScreenonUserUnpublishStream / onUserUnpublishScreen

注: 方法 onUserPublishStream 已被拆分为 onUserPublishStreamAudioonUserPublishStreamVideo,两个新方法都增加了 (BOOL)isPublish 参数用于控制是 publish 流还是 unpublish 流。方法 onUserUnpublishStreamonUserUnpublishScreen 已被废弃。在 RTCRoom 业务场景下,方法 onUserPublishScreen 已被废弃。

  • 如果媒体流转发过程中,用户切换为不可见,媒体流转发将停止。
function onForwardError(info) {
  console.error(info);
}

engine.on(EngineEventsTypes.onForwardStreamError, onForwardError);

示例项目

API 及回调

以下客户端 SDK 均支持跨房间转发媒体流功能。你可以根据上文中的描述和实例,使用不同的 SDK,在不同的端上实现这个功能。

说明:表格中的 macOS API 接口为 Objective-C,而示例项目中的 macOS 项目使用的是 Windows SDK 中的 API 接口。

平台

Android

iOS

macOS

Windows

Linux

Web

Electron

开启跨房间转发媒体流

startForwardStreamToRooms

startForwardStreamToRooms:

startForwardStreamToRooms:

startForwardStreamToRooms

startForwardStreamToRooms

startForwardStreamToRooms

startForwardStreamToRooms

更新跨房间转发媒体流

updateForwardStreamToRooms

updateForwardStreamToRooms:

updateForwardStreamToRooms:

updateForwardStreamToRooms

updateForwardStreamToRooms

updateForwardStreamToRooms

updateForwardStreamToRooms

恢复跨房间转发媒体流

resumeForwardStreamToAllRooms

resumeForwardStreamToAllRooms

resumeForwardStreamToAllRooms

resumeForwardStreamToAllRooms

resumeForwardStreamToAllRooms

resumeForwardStreamToAllRooms

resumeForwardStreamToAllRooms

暂停跨房间转发媒体流

pauseForwardStreamToAllRooms

pauseForwardStreamToAllRooms

pauseForwardStreamToAllRooms

pauseForwardStreamToAllRooms

pauseForwardStreamToAllRooms

pauseForwardStreamToAllRooms

pauseForwardStreamToAllRooms

停止跨房间转发媒体流

stopForwardStreamToRooms

stopForwardStreamToRooms

stopForwardStreamToRooms

stopForwardStreamToRooms

stopForwardStreamToRooms

stopForwardStreamToRooms

stopForwardStreamToRooms

状态和错误回调

onForwardStreamStateChanged

rtcRoom:onForwardStreamStateChanged:

rtcRoom:onForwardStreamStateChanged:

onForwardStreamStateChanged

onForwardStreamStateChanged

onForwardStreamError

onForwardStreamStateChanged

事件回调

onForwardStreamEvent

rtcRoom:onForwardStreamEvent:

rtcRoom:onForwardStreamEvent:

onForwardStreamEvent

onForwardStreamEvent

onForwardStreamEvent

功能变更日志

  1. 自 Native SDK v3.34 起,本功能在 Native 端可用。
  2. 自 Web SDK v4.54 起,本功能在 Web 端可用。
最近更新时间:2026.06.15 21:16:51
这个页面对您有帮助吗?
有用
有用
无用
无用