[TIL] WebRtc를 사용한 P2P 통신 (1/2) 23.08.23

이상훈·2023년 8월 24일
0

[내일배움캠프]

목록 보기
57/68
  • Socket.io를 사용하여 webRtc 기반 음성/영상통화 기능을 구현 목적
// 음성 통화 시작
function startVoiceCall(element) {
  const receiverId = element.getAttribute('id');
  const receiverName = element.getAttribute('name');
  console.log('Starting voice call...');
  voiceCall(`/call?callerName=${userName}&receiverName=${receiverName}`, '음성 통화', receiverId, receiverName);
}

async function voiceCall(url, callType, receiverId, receiverName) {
  const width = 800;
  const height = 900;
  const left = (window.screen.width - width) / 2;
  const top = (window.screen.height - height) / 2;
  window.open(url, callType, `width=${width},height=${height},left=${left},top=${top}`);
  socket.emit('invite', { callerName: userName, callerId, receiverId, receiverName });
}

function startVideoCall(element) {
  const receiverId = element.getAttribute('id');
  const receiverName = element.getAttribute('name');
  console.log('Starting video call...');
  videoCall(`/call?callerName=${userName}&receiverName=${receiverName}`, '영상 통화', receiverId, receiverName);
}

async function videoCall(url, callType, receiverId, receiverName) {
  const width = 800;
  const height = 900;
  const left = (window.screen.width - width) / 2;
  const top = (window.screen.height - height) / 2;
  window.open(url, callType, `width=${width},height=${height},left=${left},top=${top}`);
  socket.emit('invite', { callerName: userName, callerId, receiverId, receiverName });
}
  • 송신자가 먼저 음성/영상 통화를 걸고 수신자가 수락을 하면 통화가 시작되는 구조로 코드를 구성하였음
  @SubscribeMessage('invite')
  handleInvite(client: Socket, data: any): void {
    let user = [];
    for (let key in this.connectedClients) {
      if (this.connectedClients[key] === data.receiverId / 1) user.push(key);
    }
    user.forEach((sock) => {
      this.server.to(sock).emit('response', {
        callerId: client.id,
        callerName: data.callerName,
        receiverId: data.receiverId,
        receiverName: data.receiverName,
      });
    });
  }

invite를 보낼때 receiverId의 socket.id값을 추출하여 response를 보냄

socket.on('response', (data) => {
  responseAlert(data.callerName, data.receiverName);
});

function responseAlert(callerName, receiverName) {
  const messageHtml = `${callerName}님이 대화에 초대했습니다. <br />
  <button type="button" class="accept" data-dismiss="alert" aria-label="accpet">수락</button>
  <button type="button" class="refuse" data-dismiss="alert" aria-label="refuse">거절</button>
  <span aria-hidden="true"></span>`;

  const alt = document.getElementById('customerAlert');
  if (alt) {
    alt.innerHTML = messageHtml;
  } else {
    const htmlTemp = `<div class="alert alert-sparta alert-dismissible show fade" role="alert" id="customerAlert">${messageHtml}</div>`;
    document.body.insertAdjacentHTML('beforeend', htmlTemp);
  }

  const acceptBtn = document.querySelector('.accept');
  const refuseBtn = document.querySelector('.refuse');

  acceptBtn.addEventListener('click', () => {
    acceptCall(callerName, receiverName);
    acceptBtn.style.display = 'none';
    refuseBtn.style.display = 'none';
  });

  refuseBtn.addEventListener('click', () => {
    refuseBtn.style.display = 'none';
    acceptBtn.style.display = 'none';
  });

  setTimeout(() => {
    refuseBtn.style.display = 'none';
    acceptBtn.style.display = 'none';
  }, 60000);
}

// 응답 버튼을 누를 때 호출되는 함수
function acceptCall(callerName, receiverName) {
  const width = 800;
  const height = 900;
  const left = (window.screen.width - width) / 2;
  const top = (window.screen.height - height) / 2;

  // 새 창을 열어서 WebRTC 연결을 설정
  const callWindow = window.open(
    `/call?callerName=${callerName}&receiverName=${receiverName}`,
    `width=${width},height=${height},left=${left},top=${top}`
  );
  callWindow.onload = () => {};
}
const params = new URLSearchParams(window.location.search);
let callerName = params.get('callerName');
let receiverName = params.get('receiverName');

socket.on('connect', async () => {
  await initCall();
  socket.emit('joinRoom', { callerName, receiverName });
  console.log('Web-RTC 소켓 연결');
});
  • 새 창을 열 때 파라미터로 송수신자의 이름을 넣어주었고 해당 값을 추출하여 수신자가 수락을 누르면 양쪽 다 room에 입장

수락 창을 누르면 좌측과 같은 창이 오픈되며 setTimeout을 설정하여 60초이내 수락 또는 거절을 하지않으면 사라지게 구성

profile
코린이

0개의 댓글