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

如何在React+Node通话Web应用中无需会议实现Twilio呼叫保持并播放音乐

实现无会议依赖的呼叫保持功能方案

React 前端实现

核心思路是利用 WebRTC 的媒体轨道替换能力,将本地麦克风流切换为音乐流,同时在恢复时切回原流。

  • 保持/恢复呼叫的核心代码:
// 存储原始媒体流和音乐流
let originalAudioStream;
let holdMusicStream;

// 触发呼叫保持
const initiateHold = async () => {
  // 保存当前麦克风流并禁用轨道
  originalAudioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
  originalAudioStream.getAudioTracks().forEach(track => track.enabled = false);

  // 创建音乐播放元素并捕获其流
  const holdMusic = new Audio('/assets/hold-music.mp3');
  holdMusic.loop = true;
  holdMusicStream = holdMusic.captureStream();

  // 替换 PeerConnection 的音频发送轨道
  peerConnection.getSenders().forEach(sender => {
    if (sender.track?.kind === 'audio') {
      sender.replaceTrack(holdMusicStream.getAudioTracks()[0]);
    }
  });

  await holdMusic.play();
};

// 恢复呼叫
const resumeCall = () => {
  // 停止音乐并释放流资源
  const holdMusic = document.querySelector('audio[src="/assets/hold-music.mp3"]');
  if (holdMusic) {
    holdMusic.pause();
    holdMusicStream.getAudioTracks().forEach(track => track.stop());
  }

  // 恢复原始麦克风轨道并替换回 PeerConnection
  originalAudioStream.getAudioTracks().forEach(track => track.enabled = true);
  peerConnection.getSenders().forEach(sender => {
    if (sender.track?.kind === 'audio') {
      sender.replaceTrack(originalAudioStream.getAudioTracks()[0]);
    }
  });
};
  • 注意事项:确保音乐文件配置了正确的 CORS 规则;替换轨道前需确认 PeerConnection 处于稳定连接状态;可在对端监听轨道变化,更新 UI 提示“呼叫已被保持”。

Node 后端实现

后端主要负责转发保持/恢复的信令,无需处理媒体流(基于 P2P 架构):

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3001 });

// 存储用户连接映射
const userConnections = new Map();

wss.on('connection', (ws) => {
  ws.on('message', (data) => {
    const msg = JSON.parse(data);
    // 转发保持/恢复信令到目标用户
    if (['hold', 'resume'].includes(msg.type)) {
      const targetConn = userConnections.get(msg.targetUserId);
      if (targetConn) {
        targetConn.send(JSON.stringify(msg));
      }
    }
    // 处理其他信令(offer/answer/iceCandidate)
  });

  // 用户上线时记录连接
  ws.on('open', () => {
    userConnections.set(ws.userId, ws);
  });
});

关键技术要点

  • RTCRtpSender.replaceTrack():无需重新协商 SDP,即可动态替换发送的媒体轨道,是实现无会议保持的核心 API。
  • MediaElement.captureStream():将音频元素的输出捕获为 MediaStream,用于替代麦克风流发送给对端。
  • 信令同步:前端需通过后端向对端发送状态通知,确保两端 UI 和流状态一致。

内容的提问来源于stack exchange,提问作者Chetan Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:45:39