이제 영상 카메라와 오디오 기기를 변경하는 옵션을 추가해보도록 하겠습니다. home.pug에서 select
옵션 태그를 추가해줍니다.
// home.pug
div#video
h2 Video Chat
video#myFace(autoplay, playsinline, width="400", height="400")
select#cameras // 카메라 선택 옵션
select#audios // 오디오 선택 옵션
button#audioMute Mute
button#cameraOff Camera Off
이제 사용할 수 있는 기기 정보들을 얻어보도록 하겠습니다. enumrateDevice()
메소드를 사용하면 연결된 기기 정보를 모두 불러올 수 있습니다. 다음으로 kind
키를 통해 videoinput
과 audioinput
을 구분할 수 있는데요.
각 기기는 고유한 deviceId
를 갖고 있습니다. 이를 통해 선택 옵션 option
의 값 deviceId
와 이름 label
을 설정합니다. 최종적으로 기기 정보를 받아오는 getDevices()
함수는 다음과 같이 작성할 수 있습니다.
// app.js
const audios = document.getElementById("audios");
const cameras = document.getElementById("cameras");
async function getDevices() {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
const videoInputs = devices.filter(
(device) => device.kind === "videoinput"
);
const audioInputs = devices.filter(
(device) => device.kind === "audioinput"
);
const cameraOptions = videoInputs.forEach((camera) => {
const option = document.createElement("option");
option.value = camera.deviceId;
option.innerHTML = camera.label;
cameras.appendChild(option);
});
const audioOptions = audioInputs.forEach((audio) => {
const option = document.createElement("option");
option.value = audio.deviceId;
option.innerHTML = audio.label;
audios.appendChild(option);
});
} catch (e) {
console.log(e);
}
}
getDevices();
이렇게 하면 브라우저 화면에서 선택 가능한 기기들을 선택할 수 있는 옵션들이 출력됩니다.
이제 해당 옵션을 선택하면 기기가 전환되도록 해보겠습니다. 기기는 getMedia
함수를 통해 출력하고 있으므로 해당 함수를 업데이트해야 합니다.
그 전에 먼저 option
의 input
에 이벤트 리스너를 달아주고 이를 처리할 핸들러를 구현해줍니다. 각 핸들러는 선택 값에서 전달되는 deviceId
를 받아 이를 getMedia
에 넘겨줄 것입니다.
// app.js
async function handleAudioName() {
await getMedia(undefined, audios.value);
}
async function handleCameraName() {
await getMedia(cameras.value, undefined);
}
audios.addEventListener("input", handleAudioName);
cameras.addEventListener("input", handleCameraName);
이제 getMedia
함수를 아래와 같이 업데이트해줍니다. initialConstrains
는 아무런 옵션이 선택되지 않았을 때의 초기 설정입니다. cameraId
나 audioId
가 존재하는 경우 userSeletConstrains
가 선택되어 해당하는 카메라 및 오디오 기기가 출력되도록 삼항 연산자를 통해 구현할 수 있습니다.
// app.js
async function getMedia(cameraId, audioId) {
const initialConstrains = {
audio: true,
video: { facingMode: "user" }, // 스마트폰인 경우 전면 셀피 카메라 켜기
};
const userSeletConstrains = {
audio: { deviceId: { exact: audioId } },
video: { deviceId: { exact: cameraId } },
};
try {
myStream = await navigator.mediaDevices.getUserMedia(
cameraId || audioId ? userSeletConstrains : initialConstrains // 카메라 또는 오디오 선택에 따라 바꿔주기
);
myFace.srcObject = myStream;
} catch (e) {
console.log(e);
}
}
getMedia();
이제 서버를 실행하고 각 옵션을 선택하여 카메라 및 오디오 기기를 전환할 수 있습니다!
현재까지의 app.js 전체 코드는 다음과 같습니다.
// app.js
const socket = io();
const myFace = document.getElementById("myFace");
const audioMuteButton = document.getElementById("audioMute");
const audios = document.getElementById("audios");
const cameraOffButton = document.getElementById("cameraOff");
const cameras = document.getElementById("cameras");
let myStream;
let audioOn = true;
let cameraOn = true;
async function getMedia(audioId, cameraId) {
const initialConstrains = {
audio: true,
video: { facingMode: "user" },
};
const userSelectConstrains = {
audio: { deviceId: { exact: audioId } },
video: { deviceId: { exact: cameraId } },
};
try {
myStream = await navigator.mediaDevices.getUserMedia(
audioId || cameraId ? userSelectConstrains : initialConstrains
);0
myFace.srcObject = myStream;
} catch (e) {
console.log(e);
}
}
getMedia();
async function getDevices() {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
const videoInputs = devices.filter(
(device) => device.kind === "videoinput"
);
const audioInputs = devices.filter(
(device) => device.kind === "audioinput"
);
const cameraOptions = videoInputs.forEach((camera) => {
const option = document.createElement("option");
option.value = camera.deviceId;
option.innerHTML = camera.label;
cameras.appendChild(option);
});
const audiOptions = audioInputs.forEach((audio) => {
const option = document.createElement("option");
option.value = audio.deviceId;
option.innerText = audio.label;
audios.appendChild(option);
});
} catch (e) {
console.log(e);
}
}
getDevices();
function handleAudioMute() {
myStream
.getAudioTracks()
.forEach((track) => (track.enabled = !track.enabled));
if (!audioOn) {
audioMuteButton.innerText = "Mute";
audioOn = true;
} else {
audioMuteButton.innerText = "Unmute";
audioOn = false;
}
}
function handleCameraOff() {
myStream
.getVideoTracks()
.forEach((track) => (track.enabled = !track.enabled));
if (!cameraOn) {
cameraOffButton.innerText = "Camera Off";
cameraOn = true;
} else {
cameraOffButton.innerText = "Camera On";
cameraOn = false;
}
}
function handleAudioName() {
getMedia(audios.value, undefined);
}
function handleCameraName() {
getMedia(undefined, cameras.value);
}
audioMuteButton.addEventListener("click", handleAudioMute);
cameraOffButton.addEventListener("click", handleCameraOff);
audios.addEventListener("input", handleAudioName);
cameras.addEventListener("input", handleCameraName);
'개발 > Projects' 카테고리의 다른 글
[WebRTC] 4. 채팅방 기능 구현하기 (0) | 2022.12.15 |
---|---|
[WebRTC] 2. 영상 및 음성 켜고 끄기 (0) | 2022.12.14 |
[WebRTC] 1. 영상 채팅 화면과 소리 출력하기 (0) | 2022.12.14 |