Не удалось выполнить getUserMedia для MediaDevices: необходимо запросить как минимум одно аудио и видео - PullRequest
0 голосов
/ 11 октября 2019

Я использую AudioContext, программно, с Typescript.

Вот мой код:

/**
 * Checks for getUserMedia
 *
 * @params: none
 * @returns: any
 */
public hasGetUserMedia(): any {
  const mediaservices = !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
  console.log('Media Services: ', navigator.mediaDevices);
  return mediaservices;
}

/**
 * A function to get the return value of hasGetUserMedia
 *
 * @params: none
 * @return: none
 */
public isUserMediaGood(micstatus: boolean) {
  const self = this;
  if (this.hasGetUserMedia()) {
    // Good to go!
    self.isUserMediaThere = true;
    console.log('We have User Media Houston!');

    // Now accessInputDevice
    this.accessInputDevice(micstatus);
  } else {
    // Oops!
    self.isUserMediaThere = false;
    console.log('WARNING: getUserMedia() is not supported by your browser');

  }
}

public accessInputDevice(micstatus: boolean) {
  window.AudioContext = window.AudioContext;

  const context = new AudioContext();
  const constraints = {
    audio: micstatus,
    video: false
  }

  // initialization
  if (localStorage.getItem('microphone') === null) {
    // just assume it is prompt
    localStorage.setItem('microphone', 'prompt');
  }

  // Then somewhere
  navigator.getUserMedia({audio: true}, function (e) {
    // http://stackoverflow.com/q/15993581/1008999
    //
    // In chrome, If your app is running from SSL (https://),
    // this permission will be persistent.
    // That is, users won't have to grant/deny access every time.
    localStorage.setItem("voice_access", "granted");

  }, function (err) {
    if (err.name === 'PermissionDismissedError') {
      localStorage.setItem('voice_access', 'prompt')
    }
    if (err.name === 'PermissionDeniedError') {
      localStorage.setItem('voice_access', 'denied');
    }
  })

  navigator.mediaDevices.getUserMedia(constraints)
    .then((stream) => {
      const microphone = context.createMediaStreamSource(stream);
      const filter = context.createBiquadFilter();

      // microphone -> filter -> destination
      console.log('Mic: ', microphone);

      microphone.connect(filter);
      filter.connect(context.destination);
    });
}

public gotDevices(deviceInfos: any) {

  for (let i = 0; i !== deviceInfos.length; ++i) {
    const deviceInfo = deviceInfos[i];
    const option = document.createElement('option');
    option.value = deviceInfo.deviceId;
    if (deviceInfo.kind === 'audioinput') {
      option.text = deviceInfo.label || 'microphone ';
      // this.microphone.appendChild(option);

      console.log('Found device: ', deviceInfo);

      //    } else if (deviceInfo.kind === 'videoinput') {
      //      option.text = deviceInfo.label || 'camera ' +
      //        (videoSelect.length + 1);
      //      videoSelect.appendChild(option);
    } else {
      console.log('Found another kind of device: ', deviceInfo);
    }
  }
}

public getStream() {
  const self = this;
  const constraints = {
    audio: {
      audio: false,
      deviceId: {exact: self.microphone.id}
    },
    //      video: {
    //        deviceId: {exact: videoSelect.value}
    //      }
  };

  navigator.mediaDevices.getUserMedia(constraints).
    then(self.gotStream).catch(self.handleError);
}

public gotStream(stream: any) {
  const self = this;
  window.AudioContext = stream; // make stream available to console
  self.microphone = stream;

}

public handleError(error: any) {


  // log to console first
  console.error('Error: ', error); /* handle the error */
  if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {
    // required track is missing
  } else if (error.name === 'NotReadableError' || error.name === 'TrackStartError') {
    // webcam or mic are already in use
  } else if (error.name === 'OverconstrainedError' || error.name === 'ConstraintNotSatisfiedError') {
    // constraints can not be satisfied by avb. devices
  } else if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
    // permission denied in browser
  } else if (error.name === 'TypeError' || error.name === 'TypeError') {
    // empty constraints object
  } else {
    // other errors
  }

}

Моя проблема заключается в том, что я получаю ошибку: Uncaught (в обещании): TypeError: Failedвыполнить 'getUserMedia' на 'MediaDevices': должен быть запрошен хотя бы один из аудио и видео

TypeError : не удалось выполнить 'getUserMedia' на 'MediaDevices': хотя бы один из аудиои видео должно быть запрошено.

Ошибка возникает здесь:

navigator.mediaDevices.getUserMedia(constraints)
  .then((stream) => {
    const microphone = context.createMediaStreamSource(stream);
    const filter = context.createBiquadFilter();

    // microphone -> filter -> destination
    console.log('Mic: ', microphone);

    microphone.connect(filter);
    filter.connect(context.destination);
  });

Я хотел бы знать, почему это происходит?

ОБНОВЛЕНИЕ:

Итак, я реализовал это решение отсюда:

https://medium.com/@barzik/the-new-html5-video-audio-api-has-privacy-issues-on-desktop-chrome-5832c99c7659

Затем я перехожу по этой ссылке:

https://blog.addpipe.com/getusermedia-video-constraints/

Затем обнаружил, что «ОШИБКА ТИПА:» выбрасывается, когда и АУДИО: ложно, и ВИДЕО: ложно.

Мне нужно ПРОДОЛЖИТЬ видео: ЛОЖЬ. Почему? Мне не интересно включать видео и «пугать» пользователя, который думает, что наше программное обеспечение шпионит. Это проблема конфиденциальности. https://blog.addpipe.com/common-getusermedia-errors/

Это код, который я реализовал:

ПРИМЕЧАНИЕ: micstatus передается, когда пользователь нажимает на значок микрофона. Когда пользователь щелкает, он передает «OFF» или «FALSE». Когда пользователь нажимает снова, он передает «ON» или «TRUE». Но, если ВИДЕО остается «ЛОЖЬ», то срабатывает ОШИБКА ТИПА. Это моя проблема. CHROME не позволяет FALSE, FALSE передаваться в метод getUserMedia (). Последняя ошибка уволена. Вот что мне нужно, чтобы обойти: ПРОДОЛЖИТЬ ВИДЕО и включить или выключить АУДИО, таким образом, НЕ выбрасывая ОШИБКУ ТИПА.

var constraints = {
  video: false,
  audio: micstatus
}

navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
  /* do stuff */
  this.success(success,stream);
}).catch(function (err) {
  // log to console first 
  console.log(err); /* handle the error */
  if (err.name == "NotFoundError" || err.name == "DevicesNotFoundError") {
    // required track is missing
    console.log('Required track is missing');
  } else if (err.name == "NotReadableError" || err.name == "TrackStartError") {
    // webcam or mic are already in use
    console.log('Webcam or mic are already in use');
  } else if (err.name == "OverconstrainedError" || err.name == "ConstraintNotSatisfiedError") {
    // constraints can not be satisfied by avb. devices
    console.log('Constraints can not be satisfied by available devices');
  } else if (err.name == "NotAllowedError" || err.name == "PermissionDeniedError") {
    // permission denied in browser
    console.log('Permission Denied.');
  } else if (err.name == "TypeError" || err.name == "TypeError") {
    // empty constraints object
    console.log('Both audio and video are FALSE');
  } else {
    // other errors
    console.log('Sorry! Another error occurred.');
  }
});


// SUCCESS FUNCTION
public success(status: any, stream: any): void {
   // Success!!!
   console.log('Success with the Audio Context', status);
   console.log('Audio Context', stream);
}
...