Tutorial: 检测设备插拔行为

检测设备插拔行为

功能描述

自 v4.6.2 版本开始,SDK 会基于 浏览器原生 devicechange 事件 检测摄像头、麦克风的插拔行为,并在恰当时机,自动恢复采集推流。具体逻辑如下:

  1. 若当前正在推流的摄像头/麦克风被拔出,SDK 会尝试使用剩余可用的媒体设备,恢复采集并推流。
  2. 若摄像头/麦克风被拔出后,没有可用的媒体设备。SDK 会检测设备插入行为,若插入了新的可用的媒体设备,SDK 会尝试使用新插入的媒体设备,恢复采集并推流。
  3. 若恢复失败,则会抛出错误 DEVICE_AUTO_RECOVER_FAILED

本文主要介绍如何基于 浏览器原生 devicechange 事件 检测设备插拔行为,并在恰当时机提醒用户检查设备。

实现流程

  1. 使用 TRTC.getDevices 获取设备列表。
  2. 监听浏览器原生事件 devicechange,该事件用于监听媒体设备变更。
  3. 当 devicechange 事件触发时,重新使用 TRTC.getDevices 获取一次设备列表,并与第一步获取的设备列表进行比对,即可感知设备的新增与移除。
  4. 使用 LocalStream.getVideoTrackMediaStreamTrack.getSettings() 可获取当前正在使用的摄像头 deviceId,将 deviceId 与第三步新增/移除的设备列表进行比对,即可判断是否当前使用的摄像头被移除。

代码示例

获取新增、移除的设备列表

当设备发生变更时,会触发 devicechange 事件。通过比对 devicechange 事件触发前后的设备列表,可以检测出设备新增和设备移除。

// 1. 保存一份设备列表
let prevDevices = await TRTC.getDevices();
// 2. 监听设备变更事件
navigator.mediaDevices.addEventListener('devicechange', async () => {
  // 3. 设备变更时,获取变更后的设备列表,用于和 prevDevices 比对
  const devices = await TRTC.getDevices();
  // 4. 新增的设备列表
  const devicesAdded = devices.filter(device => prevDevices.findIndex(({ deviceId }) => device.deviceId === deviceId) < 0);
  // 5. 移除的设备列表
  const devicesRemoved = prevDevices.filter(prevDevice => devices.findIndex(({ deviceId }) => prevDevice.deviceId === deviceId) < 0);
  if (devicesAdded.length > 0) {
    handleDevicesAdded(devicesAdded);
  }
  if (devicesRemoved.length > 0) {
    handleDevicesRemoved(devicesRemoved);
  }
  prevDevices = devices;
});

处理设备新增、移除的设备列表

function handleDevicesAdded(devicesAdded) {
  devicesAdded.forEach(device => {
    if (device.kind === 'audioinput') {
      // 提示用户检测到新麦克风插入。若用户需要切换到新设备,可以调用 localStream.switchDevice 接口切换设备
    } else if (device.kind === 'videoinput') {
      // 提示用户检测到新摄像头插入。若用户需要切换到新设备,可以调用 localStream.switchDevice 接口切换设备
    }
  });
}
function handleDevicesRemoved(devicesRemoved) {
  devicesRemoved.forEach(device => {
    if (device.kind === 'audioinput') {
      // 提示用户检测到麦克风拔出。
      if (isCurrentMicrophoneRemoved(device.deviceId)) {
        // 当前正在使用的麦克风被拔出
      }
    } else if (device.kind === 'videoinput') {
      // 提示用户检测到摄像头拔出。
      if (isCurrentCameraRemoved(device.deviceId)) {
        // 当前正在使用的摄像头被拔出
      }
    }
  });
}

判断是否当前正在使用的设备被拔出

通过 MediaStreamTrack.getSettings() 方法,获取当前 LocalStream 正在使用的 deviceId,将其与 devicesRemoved 列表中的 deviceId 比对,可以检测出是否当前正在使用的设备被拔出。

// 检测是否当前正在使用的麦克风设备被拔出
// microphoneIdRemoved 是被移除的麦克风 deviceId
function isCurrentMicrophoneRemoved(microphoneIdRemoved) {
  const audioTrack = localStream.getAudioTrack();
  if (audioTrack && audioTrack.getSettings().deviceId === microphoneIdRemoved) {
    return true;
  } else {
    return false;
  }
}
// 检测是否当前正在使用的摄像头设备被拔出
// cameraIdRemoved 是被移除的摄像头 deviceId
function isCurrentCameraRemoved(cameraIdRemoved) {
  const videoTrack = localStream.getVideoTrack();
  if (videoTrack && videoTrack.getSettings().deviceId === cameraIdRemoved) {
    return true;
  } else {
    return false;
  }
}