日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

分組討論

介紹如何通過音頻分組接口實現分組討論的應用場景。

典型場景

一個課堂,有老師,助教和學生。在討論某個題目的時候,老師可以將學生分成若干個討論組,每個討論組中的學生只能在本組中討論問題,他聽不見其他組里面的聲音。而老師和助教可以隨意加入某個或者多個討論組,和組內學生語音交流。

引入音頻分組,大廳的概念

音頻分組(group):允許頻道內的成員建立工作組。User加入一個group后,有權向這個group發言,也可以收聽這個group內的音頻。

大廳(hall):如果一個user當前不在任何一個group中,那么他就留在大廳中。大廳是一個特殊的group,通過離開/加入一個group間接的達到加入/離開大廳的效果。和group類似,如果user在大廳中,那么他有權對大廳中的人發言,也可以訂閱大廳內的音頻。

權限約束:user無權對不在其中的group (含hall)發言,或者收聽音頻。

音頻訂閱約束:user不可以同時訂閱多個group (含hall)的音頻,這個是為了應對一個user出現在多個group中,以及過量的多路音頻(比如6路音頻)混音后造成理解困難的問題。

注意:音頻分組不影響視頻的publish和subscribe,即使2個user不在同一個group,也可以看見對方。

代碼實現

下面用分組接口來實現分組討論。以c++代碼為例,其他平臺接口是一致的。

老師側,通過業務層,通知每個學生加入到指定的分組,比如張三加入group1, 李四加入group2, 王五加入group1, 趙六加入group2

1. 老師側程序

// 老師加入所有的分組
void discuss_begin()
{
  engine.JoinGroup("group1", "");
  engine.JoinGroup("group2", "");

  // 通知學生加入 -
  // 張三加入group1, 李四加入group2, 王五加入group1, 趙六加入group2

  // 此時老師和學生都還在JoinGroup過程中,
  // 等所有的JoinGroup都成功(OnAudioGroupJoinResult)后,可以和任意
  // 分組中的學生交流了(discuss_group())。
}

// 當所有人加入分組完成后,老師和任意group中的學生交流
void discuss_group(string group, bool private_talk)
{
  // 老師一開始已經提前加入了所有group,無需再次加入group,
  // 只需要向這個group推流和拉流

    // sdk支持同時向多個group推流,如果老師不想其他group的
  // 學生聽到,那么private_talk為true
  if (private_talk) {
    // 取消其他group的語音推流
    for (all_groups) {
      engine.MixAudioToGroup(true, ith_group);
    }
  }
  // 和指定的group雙向交流
  engine.MixAudioToGroup(true, group);  
  engine.SwitchSubscriptionToGroup(group);
}

// 停止討論
void discuss_end()
{
  // 解散所有分組,老師和所有學生都回到大廳
  engine.DismissGroup("group1");
  engine.DismissGroup("group2");

  // 注意:監控到自己回到大廳后,設置音頻推流和拉流的目標為大廳
  //(在OnAudioGroupHallMembers中實現)
}

// 當老師回到大廳后,改變音頻推流和拉流目標為大廳
void MyEngineEventListerner::OnAudioGroupHallMembers(ding::rtc::RtcEngineAudioGroupMember *hallMembers,
  int hallMemberCount)
{
  bool iAmInHall = false;
  for(int i = 0; i < memberCount; i++) {
    if (members[i].usrId 是我自己) {
      iAmInHall = true;
      break;
    }
  }
  // 如果在大廳
  if (iAmInHall) {
    // 音頻推流到大廳
    engine.MixAudioToGroup(true, ding::rtc::RtcEngine::HallID);
    // 音頻大廳拉流
    engine.SwitchSubscriptionToGroup(ding::rtc::RtcEngine::HallID);
  }
}

2. 學生側程序

// 學生側程序,業務層通知,加入某個分組
void on_teacher_notice_join_group(string group)
{
  // 加入指定的分組
  engine.JoinGroup(group, "");
  // 注意:音頻推流和拉流的設置,等到OnAudioGroupJoinResult成功后
  // 再執行
}

// 當學生加入某個分組后,更新音頻推流和拉流目標為該分組
void OnAudioGroupJoinResult(int result, const ding::rtc::String& errMsg,
  const ding::rtc::String& group,
  RtcEngineAudioGroupMember *members,
  int memberCount)
{
  if (result == 0) { // 0表示加入分組成功
    // 音頻推流 (假定學生一開始已經推音頻流了)
    engine.MixAudioToGroup(true, group);
    // 音頻拉流
    engine.SwitchSubscriptionToGroup(group);
  }
  else {
    // 加入分組失敗
  }
}

// 當學生回到大廳后,改變音頻推流和拉流目標為大廳
void MyEngineEventListerner::OnAudioGroupHallMembers(ding::rtc::RtcEngineAudioGroupMember *hallMembers,
  int hallMemberCount)
{
  bool iAmInHall = false;
  for(int i = 0; i < memberCount; i++) {
    if (members[i].usrId 是我自己) {
      iAmInHall = true;
      break;
    }
  }
  // 如果在大廳
  if (iAmInHall) {
    // 音頻推流到大廳
    engine.MixAudioToGroup(true, ding::rtc::RtcEngine::HallID);
    // 音頻大廳拉流
    engine.SwitchSubscriptionToGroup(ding::rtc::RtcEngine::HallID);
  }
}