You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于SIP.JS的Electron+React通话应用如何实现无额外服务的电话会议

SIP.js纯客户端电话会议实现方案(无额外服务依赖)

核心实现思路

不依赖服务端会议桥,基于现有多会话管理能力,在本地通过WebRTC AudioContext完成多路音频混流,实现多端通话的会议效果,全程不需要修改现有SIP服务端配置,也不需要新增第三方服务。

具体改造步骤

1. 新增会议全局状态

在现有状态管理库中新增会议相关字段:

// 原有sessionInfo等状态保留,新增以下字段
conferenceState: {
  isActive: false, // 当前是否处于会议中
  sessionIds: [], // 会议内的所有通话会话ID列表
  audioContext: null, // 混流专用AudioContext实例
  mixedStreamDestination: null // 混流输出目标实例
}

2. 新增混流初始化方法

const initConferenceMixer = () => {
  if (conferenceState.audioContext) return
  const audioCtx = new AudioContext()
  const destination = audioCtx.createMediaStreamDestination()
  // 混流统一输出到全局会议音频元素
  const conferenceAudio = document.getElementById('conference-audio')
  conferenceAudio.srcObject = destination.stream
  conferenceAudio.play()
  // 更新全局会议状态
  dispatch({
    type: UPDATE_CONFERENCE_STATE,
    payload: {
      isActive: true,
      audioContext: audioCtx,
      mixedStreamDestination: destination
    }
  })
}

3. 改造现有会话的媒体处理逻辑

修改呼出逻辑dilaerFun和呼入接通逻辑中Established状态的媒体处理部分:

case 'Established':
  setMissedStatus(null);
  console.log('established outgoing....');
  const remoteStream = new MediaStream();
  session.sessionDescriptionHandler.peerConnection
    .getReceivers()
    .forEach((receiver) => {
      if (receiver.track) {
        remoteStream.addTrack(receiver.track);
      }
    });
  // 新增会议场景逻辑
  if (conferenceState.isActive) {
    // 新通话的远程流加入混流器
    const source = conferenceState.audioContext.createMediaStreamSource(remoteStream)
    source.connect(conferenceState.mixedStreamDestination)
    // 会话ID加入会议列表
    dispatch({
      type: UPDATE_CONFERENCE_STATE,
      payload: {
        sessionIds: [...conferenceState.sessionIds, session._id]
      }
    })
  } else {
    // 普通单聊场景保留原有逻辑
    const mediaElement = document.getElementById(`mediaElement${session._id}`);
    mediaElement.srcObject = remoteStream;
    mediaElement.play();
  }
  break;

4. 实现会议操作接口

4.1 从已有通话创建会议

const createConference = (activeSessionId) => {
  // 初始化混流器
  initConferenceMixer()
  // 把当前正在进行的通话加入会议
  const targetSession = sessionInfo.find(item => item._id === activeSessionId)
  const remoteStream = new MediaStream()
  targetSession.sessionDescriptionHandler.peerConnection
    .getReceivers()
    .forEach(receiver => {
      if (receiver.track) remoteStream.addTrack(receiver.track)
    })
  const source = conferenceState.audioContext.createMediaStreamSource(remoteStream)
  source.connect(conferenceState.mixedStreamDestination)
  dispatch({
    type: UPDATE_CONFERENCE_STATE,
    payload: {
      sessionIds: [activeSessionId]
    }
  })
}

4.2 添加参会人

直接调用现有dilaerFun拨打新号码即可,新通话接通后会自动加入正在进行的会议。

4.3 移除参会人

const removeParticipant = (sessionId) => {
  // 挂断对应通话
  const targetSession = sessionInfo.find(item => item._id === sessionId)
  targetSession?.bye()
  // 从会议列表移除会话
  const newSessionIds = conferenceState.sessionIds.filter(id => id !== sessionId)
  dispatch({
    type: UPDATE_CONFERENCE_STATE,
    payload: {
      sessionIds: newSessionIds
    }
  })
  // 所有参会人退出后销毁混流实例,恢复普通通话模式
  if (newSessionIds.length === 0) {
    conferenceState.audioContext.close()
    dispatch({
      type: UPDATE_CONFERENCE_STATE,
      payload: {
        isActive: false,
        audioContext: null,
        mixedStreamDestination: null,
        sessionIds: []
      }
    })
  }
}

注意事项

  • 该方案为纯客户端实现,参会人数建议控制在5人以内,避免本地CPU负载过高导致卡顿
  • 原有静音、保持功能可直接复用:本地静音关闭麦克风轨道后所有参会人都会听不到;单独保持某个参会人只需要将对应会话的流从混流器中断开即可
  • 不需要修改原有SIP注册、呼叫逻辑,完全基于现有能力扩展即可

内容的提问来源于stack exchange,提问作者tanmay agarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 02:57:02