设置和切换前后摄像头(H5)

更新时间: 2024/09/18 16:26:13

在 HTML5 竖屏应用上设置或者切换前/后置摄像头时,部分设备或者机型可能会产生一些不符合预期的问题,如摄像头切换失败、黑屏等。

本文介绍在移动端 H5 应用上如何正确的使用相关接口设置,保障摄像头设置或切换可以正常操作。

实现步骤

H5 的前/后置摄像头通过 facingMode 配置。

  1. 在调用 createStream 创建本地流时,可以通过设置 facingMode 参数来指定视频采集的前/后置摄像头。在部分设备中'environment'会默认选中异常设备,建议此处传入'user',如需使用后置摄像头,请参考最后的示例代码,传入设备 ID 实现。

    JavaScript// 创建 localStream
    localStream = NERTC.createStream({
      audio: true,
      video: true,
      uid: 123,
      facingMode: 'user' // 'user' 为前置摄像头,'environment' 为后置摄像头
    });
    
  2. 如果是 iOS 设备,在调用 open 开启视频采集设备时,可以通过设置 facingMode 参数来指定视频采集前/后置摄像头。

    JavaScript//当前有可能没有开启摄像头,不过执行 close 也不影响什么
    await rtc.localStream.close({
      type: 'video'
    })
    // 开启摄像头
    rtc.localStream.open({type:'video',deviceId:'xxxx',facingMode:'user'}).then(async ()=>{
        console.log('打开成功')
        // 本地播放
      }).catch(err =>{
        console.log('打开失败: ', err)
      })
    
  3. 如果是安卓设备,在切到前置时,仍可以使用 facingMode:'user' 参数实现,如果是前置切到后置,使用 facingMode:'environment' 参数会导致偶现黑屏,视频画面放大等问题,此时建议使用 deviceId 完成切换。

    JavaScript//当前有可能没有开启摄像头,不过执行 close 也不影响什么
      await rtc.localStream.close({
        type: 'video'
      })
          //安卓手机利用 deviceId 来指定单一的后置摄像头
      const cameraList = await NERTC.getCameras()
      //NERTC.getCameras 经根据排列组合,帮您处理好每个厂商暴露出来给网易云信使用的设备序列。部分设备(例如华为)会把闪光灯也包括在内,并暴露多个前后置给您使用,后置网易云信取最后一个设备。
      const cameraDevice = cameraList[cameraList.length - 1]
      if (cameraDevice && cameraDevice.label && cameraDevice.label.includes('back')) {
        console.log('摄像头列表中的最后一位确认是后置摄像头,且当前已经有了摄像头权限')
      } else {
        console.warn(
          '当前环境不是 H5,或者当前环境还没有摄像头权限, 打印 cameraDevice: ',
          JSON.stringify(cameraDevice, null, '')
        )
      }
      try {
        await rtc.localStream.open({
          type: 'video',
          deviceId: cameraDevice.deviceId //使用 deviceId 指定后置摄像头
        })
        console.log('打开摄像头 sucess')
        await rtc.localStream.play(document.getElementById('local-container'))
        rtc.localStream.setLocalRenderMode(globalConfig.localViewConfig)
      } catch (e) {
        console.error('H5 使用 facingMode 参数开启摄像头失败', e.message)
        if (e.message.includes('NotReadableError')) {
        }
      }
    

完整示例代码

JavaScriptif (!rtc.localStream) {
  console.warn('当前没有初始化 localStream')
  return
}
//当前有可能没有开启摄像头,不过执行 close 也不影响什么。
await rtc.localStream.close({
  type: 'video'
})
const USER_AGENT = (window.navigator && window.navigator.userAgent) || ''
const IS_IPAD = /iPad/i.test(USER_AGENT)
const IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD
const IS_IPOD = /iPod/i.test(USER_AGENT)
const IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD
if (IS_IOS) {
  //苹果手机直接遵守 facingMode 的设置,所以直接利用该属性完成切换,无需处理 deviceId。
  try {
    await rtc.localStream.open({
      type: 'video',
      facingMode
    })
    console.log('打开摄像头 sucess')
    await rtc.localStream.play(document.getElementById('local-container'))
    rtc.localStream.setLocalRenderMode(globalConfig.localViewConfig)
  } catch (e) {
    console.error('IOS 端 H5 使用 facingMode 参数开启摄像头失败', e.message)
    if (e.message.includes('NotReadableError')) {
    }
  }
} else {
  //facingMode 参数目前实际测试看,安卓手机前置支持情况还可以,后置表现却是各有千秋,表现诸如选错摄像头、黑屏等问题。
  if (facingMode === 'user') {
    try {
      await rtc.localStream.open({
        type: 'video',
        facingMode
      })
      console.log('打开摄像头 sucess')
      await rtc.localStream.play(document.getElementById('local-container'))
      rtc.localStream.setLocalRenderMode(globalConfig.localViewConfig)
    } catch (e) {
      console.error('安卓端 H5 使用 facingMode 参数开启摄像头失败', e.message)
      if (e.message.includes('NotReadableError')) {
      }
    }
  } else {
    //安卓手机利用 deviceId 来指定单一的后置摄像头。
    const cameraList = await NERTC.getCameras()
    //NERTC.getCameras 经根据排列组合,帮您处理好每个厂商暴露出来给网易云信使用的设备序列。部分设备(例如华为)会把闪光灯也包括在内,并暴露多个前后置给您使用,后置网易云信取最后一个设备。
    const cameraDevice = cameraList[cameraList.length - 1]
    if (cameraDevice && cameraDevice.label && cameraDevice.label.includes('back')) {
      console.log('摄像头列表中的最后一位确认是后置摄像头,且当前已经有了摄像头权限')
    } else {
      console.warn(
        '当前环境不是 H5,或者当前环境还没有摄像头权限, 打印 cameraDevice: ',
        JSON.stringify(cameraDevice, null, '')
      )
    }
    try {
      await rtc.localStream.open({
        type: 'video',
        deviceId: cameraDevice.deviceId //使用 deviceId 指定后置摄像头
      })
      console.log('打开摄像头 sucess')
      await rtc.localStream.play(document.getElementById('local-container'))
      rtc.localStream.setLocalRenderMode(globalConfig.localViewConfig)
    } catch (e) {
      console.error('H5 使用 facingMode 参数开启摄像头失败', e.message)
      if (e.message.includes('NotReadableError')) {
      }
    }
  }
}
此文档是否对你有帮助?
有帮助
去反馈
  • 实现步骤
  • 完整示例代码