WebRTC中采集设备支持的最高分辨率

思路:创建常用分辨率宽高参数选项,自动按最高档位采集,采集失败后自动降低一档进行采集,示例:


/**
 * 获取媒体约束
 * @param {*} audioIn
 * @param {*} videoIn
 * @param {*} resolution
 * @param {*} widthAudio
 * @returns
 */
async function generateOptions(
  audioIn = "",
  videoIn = "",
  resolution = { width: 1920, height: 1080 },
  widthAudio = true
) {
  return {
    audio: widthAudio
      ? {
          deviceId: audioIn ? { exact: audioIn } : undefined,
        }
      : false,
    video: {
      deviceId: videoIn ? { exact: videoIn } : undefined,
      width: { exact: resolution.width },
      height: { exact: resolution.height },
      frameRate: { min: 15, ideal: 30, max: 60 },
    },
  };
}

/**
 * 降低分辨率采集
 * @param {*} currentResolution
 * @returns
 */
async function getLowerResolution(
  currentResolution = { width: 1920, height: 1080 }
) {
  let lowerResolution = { width: 320, height: 180 };
  switch (currentResolution.height) {
    case 1080:
      lowerResolution = { width: 1280, height: 720 };
      break;
    case 720:
      lowerResolution = { width: 960, height: 540 };
      break;
    case 540:
      lowerResolution = { width: 640, height: 360 };
      break;
    case 360:
      lowerResolution = { width: 480, height: 270 };
      break;
    case 270:
      lowerResolution = { width: 320, height: 180 };
      break;
    default:
      lowerResolution = { width: 320, height: 180 };
      break;
  }
  return lowerResolution;
}

/**
 * 采集媒体
 * @param {*} audioDevice  音频ID
 * @param {*} videoDevice  视频ID
 * @param {*} resolution   最高分辨率
 * @param {*} callback     采集回调函数
 * @param {*} widthAudio   是否采集音频, 如果是视频采集卡, 这个参数可以传false
 * 摄像头示例: await captureCameraMediaStream('', '', {width: 1920, height: 1080}, mediaStream => console.log('摄像头采集成功', mediaStream))
 * 采集卡示例: await captureCameraMediaStream('', '39ba75a879131d2961548da0da7ef554c2e5a2cade827672945146ab3073f34d', {width: 1920, height: 1080}, mediaStream => console.log('采集卡采集成功', mediaStream), false)
 * @returns 
 */
export const captureCameraMediaStream = async (
  audioDevice = "",
  videoDevice = "",
  resolution = { width: 1920, height: 1080 },
  callback,
  widthAudio = true
) => {
  const options = await generateOptions(
    audioDevice,
    videoDevice,
    resolution,
    widthAudio
  );
  console.log("开始采集媒体: ", options);
  return await navigator.mediaDevices
    .getUserMedia(options)
    .then((mediaStream) => {
      return callback(mediaStream);
    })
    .catch(async (err) => {
      if (err.name.indexOf("OverconstrainedError") > -1) {
        console.warn("当前设备不支持", resolution, "的画面采集");
        if (resolution.height > 180) {
          //   console.info("降低一档分辨率采集");
          const lowerResolution = await getLowerResolution(resolution);
          return captureCameraMediaStream(audioDevice, videoDevice, lowerResolution, callback, widthAudio);
        } else {
          return console.error(
            "当前设备",
            options.video.deviceId,
            "不满足最低分辨率{width: 320, height: 180}采集需求"
          );
        }
      } else {
        console.error("采集失败, 未知错误: ", err);
      }
    });
};