WebRTC - Web

WebRTC Frontend를 만들어 봅시다

작성자

홍세민

홍세민

MarcusHong

Web

WebRTC API를 사용해 화상채팅을 시작해보자.

index.html

  • 브라우저 호환을 위해 adapter를 추가함.
  • socket.io사용을 위해 socket.io를 추가함.
<!DOCTYPE html>
<html>

<head>
  <title>Realtime communication</title>
</head>

<body>
<h1>Realtime communication</h1>

<div class="video" id="localVideo"></div>
<div class="video" id="remoteVideo"></div>

<div>
  <input id="roomName" placeholder="room name"/>
  <button id="startButton">Start</button>
  <button id="callButton">Call</button>
  <button id="hangupButton">Hang Up</button>
</div>

<script src="/socket.io/socket.io.js"></script>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="js/main.js"></script>
<script>

</script>
</body>
</html>

main.js

  • startButton: Start 버튼을 누르면 mediaDevice를 가져온 후 socket을 초기화 시킨다.
  • callButton: Call 버튼을 누르면 google ice 서버로 RTCPeerConnection를 생성한 후 offer를 서버로 보낸다.
  • 상대편에서 offer를 받고 answer를 보냈으면, LocalDescription에 해당 answer를 설정한 후 answer를 보낸다.
  • candidate에서 서로간에 네트워크 정보가 주고받아지면 실시간 화상채팅이 시작된다.
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');

const roomName = document.getElementById('roomName');

const startButton = document.getElementById('startButton');
startButton.addEventListener('click', initRTC, false);

const callButton = document.getElementById('callButton');
callButton.addEventListener('click', startCall, false);

const hangupButton = document.getElementById('hangupButton');
hangupButton.addEventListener('click', hangupCall, false);

function initRTC() {
  const socket = io();
  const roomName = options.roomName
  socket.on('connect', () => {
    navigator.mediaDevices.getUserMedia({
      video: {
        width: 640,
        height: 480,
        facingMode: 'user'
      },
      audio: true
    })
      .then(mediaStream => {
        localVideo.srcObject = mediaStream
        localVideo.volume = 0
        localStream = mediaStream
      });

    socket.emit('join', roomName.value, (err) => {
      if (err) alert(err);
      else {
        socket.on('offer', offer => {
          createAnswer(offer);
        });
        socket.on('candidate', (candidate) => {
          if (peerConnection) peerConnection.addIceCandidate(candidate);
        });
        socket.on('answer', onAnswer);
      }
    });
  });

  function startCall () {
    const iceServers = [ {
      'urls': 'stun:stun.l.google.com:19302'
    }];
    peerConnection = new RTCPeerConnection({iceServers: iceServers});
    peerConnection.addEventListener('icecandidate', handleConnection);
    peerConnection.addEventListener('addstream', gotRemoteMediaStream);
    peerConnection.addStream(localStream);
    createOffer();
  }

  function hangupCall() {
    if (peerConnection) {
      peerConnection.close()
      peerConnection = null
    }
  }

  function onAnswer(answer) {
    peerConnection.setRemoteDescription(answer)
      .catch(e => console.log(e));
  };

  function createOffer() {
    peerConnection.createOffer()
      .then(offer => {
        peerConnection.setLocalDescription(offer)
        return offer
      })
      .then(offer => socket.emit('offer', {room: roomName, offer}));
  };

  function createAnswer(description) {
    peerConnection.setRemoteDescription(description)
      .then(() => peerConnection.createAnswer())
      .then((answer) => {
        peerConnection.setLocalDescription(answer)
        return answer;
      })
      .then((answer) => socket.emit('answer', {room: roomName, answer}))
      .catch(e => console.log(e));
  };

  function gotRemoteMediaStream(event) {
    const mediaStream = event.stream;
    remoteVideo.srcObject = mediaStream;
    remoteStream = mediaStream;
  };

  function handleConnection(event) {
    const iceCandidate = event.candidate;
    socket.emit('candidate', {room: roomName, candidate: iceCandidate});
  };
};

정리

socket 통신만으로 peer to peer 실시간 화상채팅이 가능한 예제를 만들어 보았다. RTCDataChannel를 사용하면 데이터까지 주고 받을 수 있지만, MS계열 브라우저에서는 사용이 불가능하다.

Tags : webrtc 

comments powered by Disqus