videocalling
静音/取消静音(Mute / Unmute)

静音/取消静音(Mute / Unmute)

功能

允许用户在通话期间禁用音频或视频传输的功能

什么是静音/取消静音?

静音和取消静音是视频通话应用中的基本控制,允许用户在通话期间禁用(静音)或启用(取消静音)他们的音频或视频流。静音时,用户的麦克风或摄像头停止向其他参与者传输有意义的数据,要么发送静音/黑屏帧,要么完全停止传输。

静音是视频会议中使用最频繁的功能之一,帮助用户保持隐私、减少背景噪音并管理他们在会议中的存在感。

静音/取消静音的工作原理

音频静音

当用户静音他们的音频时,他们的麦克风停止传输语音数据。根据实现方式,这可以通过几种方法实现:

  • 静音传输:音频轨道继续发送数据,但所有采样都设置为零(静音)
  • 轨道禁用:音频轨道在本地禁用,防止有意义的音频捕获
  • 硬静音:音频轨道完全从对等连接中移除,停止所有传输

视频静音

视频静音(有时称为"停止视频"或"关闭摄像头")工作方式类似:

  • 黑屏帧:视频轨道发送黑屏帧而不是摄像头内容
  • 轨道禁用:摄像头被禁用,摄像头指示灯通常会关闭
  • 硬静音:视频轨道完全移除,停止带宽消耗

实现方法

1. MediaStreamTrack.enabled 属性(标准方法)

最常见和推荐的方法使用 MediaStreamTrack 的 enabled 属性:

// 从本地流获取音频轨道\nconst audioTrack = localStream.getAudioTracks()[0];\n\n// 静音音频\naudioTrack.enabled = false; // 生成静音\n\n// 取消静音音频\naudioTrack.enabled = true; // 恢复音频传输\n\n// 视频静音工作方式相同\nconst videoTrack = localStream.getVideoTracks()[0];\nvideoTrack.enabled = false; // 生成黑屏帧\nvideoTrack.enabled = true; // 恢复视频

特性:

  • 行为:禁用时,音频轨道生成静音(所有采样 = 0),视频轨道生成黑屏帧
  • 带宽:继续向远程对等方发送数据,尽管是高度压缩的零内容帧
  • 摄像头指示灯:对于视频,当 enabled = false 时,摄像头指示灯通常会关闭
  • 远程感知:远程端的轨道保持"启用"——需要额外的信令来通知远程参与者静音状态
  • 最适合:大多数标准实现,在静音/取消静音状态之间快速切换

2. RTCRtpSender.replaceTrack(null)(硬静音)

这种方法完全停止媒体传输:

// 获取音频轨道的发送器\nconst audioSender = peerConnection.getSenders()\n  .find(sender => sender.track?.kind === 'audio');\n\n// 硬静音 - 完全停止发送\nawait audioSender.replaceTrack(null);\n\n// 取消静音 - 使用原始轨道恢复\nawait audioSender.replaceTrack(originalAudioTrack);

特性:

  • 行为:当轨道为 null 时完全停止媒体传输
  • 带宽:节省带宽,因为不发送数据
  • 重新协商:在某些实现中可能触发重新协商
  • 最适合:长时间静音期间,带宽节省很重要

3. RTCRtpSender.setParameters(高级控制)

控制单个编码层:

const sender = peerConnection.getSenders()\n  .find(s => s.track?.kind === 'audio');\n\nconst params = sender.getParameters();\n\n// 通过禁用所有编码来静音\nparams.encodings.forEach(encoding => {\n  encoding.active = false;\n});\n\nawait sender.setParameters(params);\n\n// 通过重新启用编码来取消静音\nparams.encodings.forEach(encoding => {\n  encoding.active = true;\n});\n\nawait sender.setParameters(params);

特性:

  • 行为:防止编码被发送
  • 远程轨道:远程轨道更改为静音状态
  • 无本地影响:本地轨道保持启用
  • 最适合:对联播层或特定编码配置的精细控制

4. Transceiver Direction API(基于 SDP 的控制)

通过 SDP 协商控制媒体方向:

// 获取音频的收发器\nconst transceiver = peerConnection.getTransceivers()\n  .find(t => t.sender.track?.kind === 'audio');\n\n// 静音 - 将方向更改为仅接收\ntransceiver.direction = 'recvonly';\n\n// 取消静音 - 恢复双向通信\ntransceiver.direction = 'sendrecv';

特性:

  • 行为:更改 SDP 方向,远程对等方通过信令感知
  • 带宽:当方向为"recvonly"时不发送媒体
  • 重新协商:需要 SDP 重新协商
  • 最适合:当重新协商可接受且需要通过 SDP 进行远程感知时

2025 年最佳实践

推荐方法

对于大多数应用,使用 MediaStreamTrack.enabled 结合信令:

// 本地静音实现\nfunction toggleAudioMute() {\n  const audioTrack = localStream.getAudioTracks()[0];\n  const isMuted = !audioTrack.enabled;\n  \n  // 更新本地轨道状态\n  audioTrack.enabled = !audioTrack.enabled;\n  \n  // 发送信令消息通知远程对等方\n  sendSignalingMessage({\n    type: 'mute-status',\n    audio: isMuted,\n    userId: currentUserId\n  });\n  \n  // 更新 UI\n  updateMuteButtonUI(isMuted);\n  \n  return isMuted;\n}

信令静音状态

由于 enabled 不会自动通知远程对等方,发送显式信令消息:

  • 静音更改时:向所有参与者广播静音状态
  • 加入时:在加入消息中包含当前静音状态
  • 定期同步:定期同步静音状态以处理消息丢失

用户界面考虑

  1. 清晰的视觉反馈
    • 静音麦克风:红色图标或麦克风上的斜线
    • 取消静音麦克风:绿色或蓝色麦克风图标
    • 视频关闭:带斜线的摄像头图标,或头像/首字母占位符
  2. 键盘快捷键
    • 空格键用于按键说话(按住取消静音)
    • Ctrl/Cmd + D 用于音频静音切换
    • Ctrl/Cmd + E 用于视频切换
  3. 持久指示器
    • 在参与者列表中显示静音状态
    • 当用户尝试在静音时说话时显示横幅
    • 在显眼位置显示"您已静音"通知
  4. 音频电平指示器
    • 即使在本地静音时也继续显示音频电平表
    • 这有助于用户在取消静音之前验证麦克风是否工作

加入时静音

许多应用在加入大型会议时默认静音参与者:

// 对于超过 N 个参与者的会议,默认静音\nif (meetingParticipantCount > 10) {\n  localStream.getAudioTracks().forEach(track => {\n    track.enabled = false;\n  });\n  showNotification('您已被静音。点击取消静音。');\n}

音频 vs 视频静音

音频静音

  • 更常见:音频静音在整个通话过程中频繁使用以减少背景噪音
  • 快速切换:用户期望即时静音/取消静音响应
  • 背景噪音:对于消除键盘打字、宠物、儿童、交通等噪音至关重要
  • 大型会议:对于防止大型会议中的反馈环路和噪音至关重要

视频静音

  • 带宽节省:关闭视频可以显著减少带宽使用(节省 1-3 Mbps)
  • 隐私:用户在不想被看到时禁用视频(进餐、光线不好、非正式场合)
  • 性能:有助于提高低端设备的性能
  • CPU 节省:停止摄像头捕获和编码,减少 CPU 负载

远程静音

主持人控制

会议主持人通常能够远程静音参与者:

  • 实现:主持人发送信令消息请求参与者静音
  • 用户同意:浏览器可能需要用户交互才能静音本地轨道
  • 最佳实践:向用户显示通知,解释为什么他们被静音,并提供简单的取消静音选项
// 接收远程静音请求\nsocket.on('mute-request', ({ requestedBy, reason }) => {\n  // 向用户显示通知\n  showNotification(`${requestedBy} 已请求您静音。${reason}`);\n  \n  // 可选地自动静音并获得用户确认\n  if (autoAcceptMuteRequests) {\n    localStream.getAudioTracks()[0].enabled = false;\n    updateMuteButtonUI(true);\n  }\n});

常见用例

  • 降噪:不说话时静音以消除背景噪音
  • 隐私:防止意外传输私人对话
  • 大型会议:对于网络研讨会、市政厅和大型会议至关重要
  • 带宽管理:在连接较差时关闭视频
  • 专注模式:在演示或屏幕共享期间禁用视频以节省资源
  • 按键说话:游戏和战术通信使用按住取消静音模式

高级功能

智能音频检测

一些应用实现智能音频静音:

  • 语音活动检测(VAD):自动检测用户何时说话
  • 背景噪音抑制:现代浏览器支持噪音抑制约束
  • 回声消除:AEC 无需静音即可消除回声
const constraints = {\n  audio: {\n    echoCancellation: true,\n    noiseSuppression: true,\n    autoGainControl: true\n  },\n  video: true\n};

静音提醒

检测用户在静音时尝试说话:

  • 即使轨道被禁用也监控音频电平
  • 如果在静音时音频电平激增,显示视觉通知
  • 在通知中提供快速取消静音按钮

平台示例

  • Zoom:空格键用于按键说话,主持人可以全部静音,大型会议的入场静音
  • Google Meet:Ctrl+D 静音,超过 25 人的会议自动静音
  • Microsoft Teams:Ctrl+Shift+M 静音,在静音时说话时举手通知
  • Discord:按键说话模式,服务器范围静音,语音活动检测

参考资料