Я использую 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);
}