WebRTC媒体API是实时通信起点,核心环节为捕获(getUserMedia获取MediaStream)、处理(enumerateDevices选设备、track.enabled控制开关)、注入(addTrack/addTransceiver塞入RTCPeerConnection);需兼顾用户授权、设备兼容性及状态同步。

媒体API是WebRTC实现实时通信的起点,它负责把摄像头、麦克风的数据变成可传输的流;没有它,后续的连接、传输都无从谈起。关键在于捕获、处理、注入三个环节必须连贯,且需配合用户授权和设备兼容性处理。
媒体捕获:从 getUserMedia 到可用 MediaStream
调用 navigator.mediaDevices.getUserMedia() 是第一步,传入 { audio: true, video: true } 即可请求音视频权限。现代浏览器会弹出明确授权提示,但要注意:iOS Safari 需在 HTTPS 环境下运行,部分 Android WebView 可能不支持高分辨率视频。
- 捕获失败常见原因包括用户拒绝权限、设备被占用、或配置参数超出硬件能力(如指定 4K 但摄像头仅支持 1080p)
- 建议先用 navigator.mediaDevices.enumerateDevices() 获取可用设备列表,让用户手动选择摄像头或麦克风,提升体验
- 成功后返回一个 MediaStream 对象,它包含多个 MediaStreamTrack(如一个视频轨、一个音频轨),可单独启用/禁用或添加到连接中
媒体流注入:addTrack 与 addTransceiver 的区别
拿到 MediaStream 后,需要把它“塞进” RTCPeerConnection 才能参与传输。主流做法是调用 addTrack(),例如 pc.addTrack(videoTrack, stream)。它会自动创建发送端的 transceiver,并触发 SDP 协商。
- addTrack 更直观,适合大多数场景,尤其当媒体流已就绪时
- addTransceiver 更灵活,允许提前声明要发送或接收的媒体类型(如只发视频、不收音频),适合需要精细控制编解码或方向(sendrecv/sendonly/recvonly)的场景
- 注意:多次调用 addTrack 同一轨道会报错;若需动态开关,应使用 track.enabled = false 而非反复增删
媒体控制与状态同步
实时通信中,用户常需要静音、关闭摄像头、切换设备等操作。这些不是靠重连实现的,而是直接操作 MediaStreamTrack。
- 静音:设置 audioTrack.enabled = false,远端会立刻停止收到音频数据,且不触发重协商
- 关闭摄像头:同理,videoTrack.enabled = false,画面变黑但连接保持,带宽自动下降
- 切换摄像头:重新调用 getUserMedia 获取新流,再用 replaceTrack() 替换原有视频轨(需确保 transceiver 支持)
- 监听状态变化:可监听 track.onmute / onunmute / onended 事件,及时更新 UI
常见协同问题与应对
媒体API和RTCPeerConnection虽分工明确,但耦合紧密,出错常出现在交界处。
- “黑屏但有声音”:多因视频轨道未正确 addTrack,或 setLocalDescription 前未注入流
- “有画面没声音”:检查音频轨道是否被静音、是否被系统其他应用独占、或 getUserMedia 时 audio 设为 false
- “本地预览正常,远端看不到”:确认 addTrack 后是否触发了 createOffer/setLocalDescription 流程,且 offer 中包含对应 m=video/audio 行
- 移动端自动暂停媒体:Safari 和部分 Android 浏览器在页面切后台时会 suspend 媒体,需监听 visibilitychange 并手动恢复

















