[WebRTC] 3. 카메라 오디오 전환하기

2022. 12. 14. 15:43·개발/Projects

이제 영상 카메라와 오디오 기기를 변경하는 옵션을 추가해보도록 하겠습니다. 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
'개발/Projects' 카테고리의 다른 글
  • [WebRTC] 5. 라이브 스트리밍 구현 (1) offer & answer
  • [WebRTC] 4. 채팅방 기능 구현하기
  • [WebRTC] 2. 영상 및 음성 켜고 끄기
  • [WebRTC] 1. 영상 채팅 화면과 소리 출력하기
휘Hwi
휘Hwi
여행, 사진, 개발, 책 이야기를 기록하는 여행자 휘의 블로그 𓂍
Klook.com
  • 휘Hwi
    휘: 끝나지 않은 이야기
    휘Hwi
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 기록
        • 일상 에세이
        • 인사이트
        • 투자와 재테크
        • 코인 이야기
        • 아카이빙
        • 집무실 레터
        • 사랑에 대하여
        • 번역 이야기(完)
        • 프리랜서 일지(完)
      • 여행
        • 🌎 세계 여행기 S1 (完)
        • 🌊 삼삼한 여행기 (完)
        • 🚶 온더로드
        • 🇯🇵 일본
        • 🏝️ 발리
        • 🇻🇳 베트남
        • 🇱🇰 스리랑카
        • 🇮🇳 인도
        • 🇹🇭 태국
        • 🇸🇬 싱가포르
        • 🇦🇺 호주
        • 🇭🇰 홍콩
        • 🇰🇷 한국
        • 🍚 여행자의 한 끼
        • ℹ️ 여행 정보
      • 사진
        • 사진가
        • 사진 이론과 생각
        • 사진 관련 정보
      • 영상
        • 파이널컷 모션 공부
        • 고프로 GoPro
        • 영상 관련 정보
      • 책
        • 책 읽고 쓰기
      • 개발
        • 티스토리
        • Internet
        • HTML
        • CSS
        • JavaScript
        • Typescript
        • React
        • Node.js
        • Express
        • NestJS
        • Python
        • Django
        • MySQL
        • MongoDB
        • AWS
        • Deployment
        • Terminal
        • Git
        • Glossaries
        • Articles
        • Projects
        • TIL;
      • 미분류
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
휘Hwi
[WebRTC] 3. 카메라 오디오 전환하기
상단으로

티스토리툴바