스피킹 기능 작업중 마이크가 내장되어 있는 휴대 기기는 괜찮지만, PC의 경우 중간에 마이크가 연결 해제되어도 에러처리 없이 스피킹 자체가 중단되고 있는 상황이라 따로 에러처리가 필요하다는 생각이 들었다.
먼저, 기기 연결 상태를 getUserMedia를 이용해서 하고 있었는데
기존 코드는 다음과 같다.
const setUserMedia = async () => {
if (is_set.current) return;
try {
getusermedia.current = await window.navigator.mediaDevices
.getUserMedia({ audio: true })
.then((stream: any) => {
if (audio_context.current == undefined) return;
isMicUnConnected.current = false;
// ... 오디오 장치 있을때 실행할 코드
.catch((e: DOMException) => {
if (e.message === 'Requested device not found' || e.name === 'NotFoundError') {
isMicUnConnected.current = true;
}
window.console.error(e);
return false;
});
} catch (e) {
permission.current = false;
alert('webkitGetUserMedia threw exception:' + e);
return false;
}
기기를 연결 / 연결 해제를 반복하며 테스트해본 결과, catch 절에서 Requested device not found
라는 에러문구와 함께 실행되지 않는것을 알 수 있었는데,
문제는 실시간 으로 스피킹 도중에 마이크 연결 해제가 되었을 경우 바로 인식해서 스피킹 시도시 에러 문구를 띄워주어야 했기 때문에
특정 state를 만들어서 실시간으로 인식하기엔, 해당 함수가 콜백이었기 때문에 적합하지 않았고 state 또한 ref
를 사용해서 업데이트 시키고자 했다.
참고로 navigator.getUserMedia는 사파리 브라우저에서도 지원하지 않는다.
참고 : MDN - Navigator.getUserMedia
위의 navigator.getUserMedia
와 달리 navigator.mediaDevices.getUserMedia
는 Promise를 반환하므로 동기적으로 처리가 가능하게 된다.
즉 setUserMedia 함수를 동기적으로 실행해서 확실하게 함수 return값을 받은 뒤 (마이크 연결상태 체크) 그에 맞는 성공 / 에러 처리가 가능해진다는 것이다.
검색해보니 더 간편하게 미디어 장치 리스트를 받아올수 있는 메서드도 존재해서, audioinput 만 따로 이렇게 분기처리해서 사용할수 있었다.
async function checkMicrophoneExists() {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
const microphones = devices.filter(device => device.kind === 'audioinput');
if (microphones.length > 0) {
console.log("마이크가 존재합니다.");
return true;
} else {
console.log("마이크가 없습니다.");
return false;
}
} catch (error) {
console.error("장치를 확인하는 중 오류가 발생했습니다.", error);
return false;
}
}
당연하겠지만, api 사용 전에 크로스 브라우징을 위해 지원하는 브라우저 확인이 필요한 것 같다.
speechRecognition
의 경우 파이어폭스는 지원하지 않고 있어서 우리 서비스의 경우 파이어폭스 브라우저로 실행했을때 크롬을 이용하게끔 안내문구와 함께 리다이렉트 시키고 있는데,
최근 마이크 연결상태 인식해서 에러를 띄우는 작업 진행후 브라우저별로 테스트해보니 웨일 브라우저에서도 스피킹이 안되는 이슈가 있었다.
웨일, 파이어폭스 브라우저로 진입시 크롬 다운로드 페이지로 리다이렉트시키는 로직을 추가했고, 브라우저별 테스트의 중요성을 다시금 깨닫게 되었다! :)