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

Node.js客户端-服务端WebRTC P2P模式下媒体流传输实现咨询

实现客户端-服务端WebRTC媒体流传输方案

以下方案基于你当前使用的simple-peer对等连接库、Node端wrtcWebRTC适配包实现,包含流上传、合流、下发全流程逻辑:


一、服务端(backend/server.js)改造

首先需要完成客户端流接收、多路音频合流、混合流下发三个核心逻辑,修改后代码如下:

const Peer = require('simple-peer');
const wrtc = require('wrtc');
const AudioMixer = require('audio-mixer'); // 需提前npm安装,用于多音频流合并

// 全局存储所有客户端连接实例、音频轨道
const allConnectedPeers = new Map();
const clientAudioTracks = new Map();

// 每个新客户端接入时初始化对应peer实例
function createClientPeer(clientId) {
  const clientPeer = new Peer({ initiator: true, wrtc });
  
  clientPeer.on('connect', () => {
    allConnectedPeers.set(clientId, clientPeer);
    console.log('客户端连接成功:', clientId);
  });

  // 监听客户端上传的音频流
  clientPeer.on('stream', (clientStream) => {
    const audioTrack = clientStream.getAudioTracks()[0];
    clientAudioTracks.set(clientId, audioTrack);
    // 触发合流后推送给所有在线客户端
    broadcastMixedStream();
  });

  // 客户端断开时清理资源
  clientPeer.on('close', () => {
    allConnectedPeers.delete(clientId);
    clientAudioTracks.delete(clientId);
    broadcastMixedStream();
  });

  clientPeer.on('error', (err) => console.error('连接错误:', err));
  return clientPeer;
}

// 多路音频合并为单流+全量下发
function broadcastMixedStream() {
  const trackList = Array.from(clientAudioTracks.values());
  if (trackList.length === 0) return;

  // 初始化混音器,输出单路音频流
  const mixer = new AudioMixer({
    channels: 2,
    sampleRate: 48000,
    bitDepth: 16
  });

  trackList.forEach(track => {
    const input = mixer.input();
    // 将音频轨道数据写入混音器输入
    track.on('data', (chunk) => input.write(chunk));
  });

  // 生成混合后的单路音频流
  const mixedStream = new wrtc.MediaStream();
  const mixedTrack = mixer.output().createTrack();
  mixedStream.addTrack(mixedTrack);

  // 推送给所有在线客户端
  allConnectedPeers.forEach(peer => {
    // 先移除旧的混合流避免重复
    if (peer._streams.length) peer.removeStream(peer._streams[0]);
    peer.addStream(mixedStream);
  });
}

注意:如果不需要专业混音效果,也可以直接把所有音频轨加入同一个MediaStream下发,但客户端会同时解码多轨,性能消耗更高。


二、客户端(frontend/index.js)改造

需要补充本地音频采集、流上传、信令交互三个逻辑,修改后代码如下:

import Peer from 'simple-peer';

// 初始化信令WebSocket(需自行搭建简单WebSocket服务交换SDP/ICE候选)
const ws = new WebSocket('ws://你的服务端地址/ws');

// 获取本地麦克风音频流
async function getLocalAudio() {
  return await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
}

// 初始化与服务端的WebRTC连接
async function initRTCConnection() {
  const localStream = await getLocalAudio();
  const serverPeer = new Peer({ initiator: false });

  // 把本地音频流推送给服务端
  serverPeer.addStream(localStream);

  // 信令交换:本地生成SDP/ICE时发送给服务端
  serverPeer.on('signal', (data) => {
    ws.send(JSON.stringify({ type: 'signal', payload: data }));
  });

  // 信令交换:接收服务端发过来的SDP/ICE完成握手
  ws.onmessage = (msg) => {
    const { type, payload } = JSON.parse(msg.data);
    if (type === 'signal') serverPeer.signal(payload);
  };

  // 接收服务端下发的混合流并播放
  serverPeer.on('stream', async (stream) => {
    const audioEl = document.createElement('audio');
    audioEl.autoplay = true;
    if ('srcObject' in audioEl) {
      audioEl.srcObject = stream;
    } else {
      audioEl.src = window.URL.createObjectURL(stream);
    }
    document.body.appendChild(audioEl);
    // 兼容浏览器自动播放限制,建议在用户点击事件回调中执行该初始化逻辑
    try {
      await audioEl.play();
    } catch (e) {
      console.warn('自动播放失败,请点击页面任意位置触发播放', e);
    }
  });

  serverPeer.on('connect', () => console.log('与服务端RTC连接成功'));
  serverPeer.on('error', (err) => console.error('连接错误:', err));
}

三、必填补充说明

  • 信令服务是WebRTC连接的前置条件,必须通过WebSocket/HTTP传递两端的signal事件数据,否则无法完成握手建立连接
  • 若需要支持多人语音,混音逻辑建议做回声消除、噪声抑制处理,可引入webrtc-audio-processing类库实现
  • 服务端部署时需要开放UDP端口,或者配置STUN/TURN服务器解决跨网穿透问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:30:00