背景

用户摄像头、麦克风损害,或者是用户禁止使用麦克风、摄像头,会出现本地流创建失败的情况,原因是因为创建本地流的时候,声音和视频都设置的true,在初始化的时候,就会找不到可用设备而走error回调,导致只走了catch方法


分析

创建本地流方法,默认设置的都是true,导致腾讯云去取摄像头和麦克风的时候没取到,走了error回调

  1. this.localStream = TRTC.createStream({
  2. audio: true, // 采集麦克风
  3. video: true, // 采集摄像头
  4. userId: this.localUserID
  5. });

解决

需要知道本地的麦克风或者摄像头是否可以使用,如果可以的话,设置成true,如果不能使用,则设置成false

navigator.mediaDevices.enumerateDevices() 获取媒体设备

MediaDevices 的方法 enumerateDevices() 请求一个可用的媒体输入和输出设备的列表,例如麦克风,摄像机,耳机设备等。 返回的 Promise 完成时,会带有一个描述设备的 MediaDeviceInfo 的数组
所以根据返回的数据数组是否大于0,就知道是否有可用的设备

  1. let list = await navigator.mediaDevices.enumerateDevices();
  2. if (list.length > 0) {}

如果小于0,则不用继续,提醒用户没有可用设备即可,如果有可用设备,则需要判断一下,可用的是哪些设备,如果可用设备中有摄像头,则初始化video:true,如果有麦克风可用,则audio:true,反之则为false,这样就能确保初始化是正常的

  1. // 检查音频设备方法
  2. checkAudio() {
  3. let p = new Promise((resolve, reject) => {
  4. navigator.mediaDevices.getUserMedia({
  5. audio: true
  6. }).then(() => {
  7. resolve(true);
  8. }).catch(error => {
  9. console.log(error);
  10. reject(new Error('audio'));
  11. });
  12. });
  13. return p;
  14. }
  15. // 调用检查可用设备方法的另外一个方法中
  16. try {
  17. let audioPromise = await this.checkAudio();
  18. audioFlag = 'canUse';
  19. } catch (error) {
  20. console.log(error);
  21. audioFlag = 'noUse';
  22. }

摄像头设备检查如上相同
具体代码如下:

  1. async createLocalStream() {
  2. // 检查设备
  3. let audioFlag = '-1';
  4. let videoFlag = '-1';
  5. let list = await navigator.mediaDevices.enumerateDevices();
  6. if (list.length > 0) {
  7. try {
  8. let audioPromise = await this.checkAudio();
  9. audioFlag = 'canUse';
  10. } catch (error) {
  11. console.log(error);
  12. audioFlag = 'noUse';
  13. }
  14. try {
  15. let videoPromise = await this.checkVideo();
  16. videoFlag = 'canUse';
  17. } catch (error) {
  18. console.log(error);
  19. videoFlag = 'noUse';
  20. }
  21. console.warn(audioFlag, videoFlag)
  22. if (audioFlag === '-1' && videoFlag === '-1') {
  23. // 一直pending
  24. this.$message.error("请授权摄像头/麦克风访问权限,否则无法进行音视频通话");
  25. } else if (videoFlag === 'canUse' || audioFlag === 'canUse') {
  26. let auFlag = (audioFlag === 'canUse');
  27. let viFlag = (videoFlag === 'canUse');
  28. this.createLocalStreamMethod(auFlag, viFlag);
  29. } else {
  30. this.$message.error("没有找到可用摄像头/麦克风");
  31. }
  32. } else {
  33. this.$message.error("没有找到可用摄像头/麦克风");
  34. }
  35. },