WebRTC - JavaScript를 사용한 간단한 비디오 채팅(2부)

이 게시물은 비디오 채팅에 대한 WebRTC 구현의 두 번째 부분입니다. 이전 게시물에서는 화상 대화 구현을 제시했으며 이 부분에서는 채팅 구현을 제시합니다.

이전글이 안보이시면 클릭하세요.

RTCDataChannel



RTCDataChannel은 임의 데이터의 양방향 P2P 전송에 사용할 수 있는 채널을 제공하는 WebRTC 리소스의 인터페이스입니다. 채널은 RTCPeerConnection과 연결됩니다.

RTCDataChannel을 사용하여 연결된 사용자 간에 문자 메시지를 보낼 것입니다.

RTCDataChannel 생성



첫 번째 단계는 createDataChannel을 사용하여 채널을 만드는 것입니다. RTCPeerConnection을 시작하는 사람은 RTCDataChannel도 시작해야 합니다. 우리의 경우 RTCDataChannel은 로컬 연결이 시작될 때 시작됩니다.

완전한 시작 RTCPeerConnection은 다음과 같이 유지되었습니다.

// Start a RTCPeerConnection to each client
socket.on('other-users', (otherUsers) => {
    // Ignore when not exists other users connected
    if (!otherUsers || !otherUsers.length) return;

    const socketId = otherUsers[0];

    // Ininit peer connection
    localConnection = new RTCPeerConnection();

    // Add all tracks from stream to peer connection
    stream.getTracks().forEach(track => localConnection.addTrack(track, stream));

    // Send Candidtates to establish a channel communication to send stream and data
    localConnection.onicecandidate = ({ candidate }) => {
      candidate && socket.emit('candidate', socketId, candidate);
    };

    // Receive stream from remote client and add to remote video area
    localConnection.ontrack = ({ streams: [ stream ] }) => {
      remoteVideo.srcObject = stream;
    };

    // Start the channel to chat
    localChannel = localConnection.createDataChannel('chat_channel');

    // Function Called When Receive Message in Channel
    localChannel.onmessage = (event) => console.log(`Receive: ${event.data}`);
    // Function Called When Channel is Opened
    localChannel.onopen = (event) => console.log(`Channel Changed: ${event.type}`);
    // Function Called When Channel is Closed
    localChannel.onclose = (event) => console.log(`Channel Changed: ${event.type}`);

    // Create Offer, Set Local Description and Send Offer to other users connected
    localConnection
      .createOffer()
      .then(offer => localConnection.setLocalDescription(offer))
      .then(() => {
        socket.emit('offer', socketId, localConnection.localDescription);
      });
  });


RTCDataChannel을 생성하기 위해 새 줄에 초점을 맞춥니다.

// Start the channel to chat
localChannel = localConnection.createDataChannel('chat_channel');

// Function Called When Receive Message in Channel
localChannel.onmessage = (event) => console.log(`Receive: ${event.data}`);
// Function Called When Channel is Opened
localChannel.onopen = (event) => console.log(`Channel Changed: ${event.type}`);
// Function Called When Channel is Closed
localChannel.onclose = (event) => console.log(`Channel Changed: ${event.type}`);


또한 생성된 채널을 저장하기 위해 initConnection 함수를 시작할 때 localChannel 및 remoteChannel 변수로 선언합니다.

그 후 RTCDataChannel은 ondatachannel 함수를 통해 원격 연결로 수신됩니다. 원격 연결에 대한 전체 코드는 다음과 같습니다.

// Receive Offer From Other Client
socket.on('offer', (socketId, description) => {
    // Ininit peer connection
    remoteConnection = new RTCPeerConnection();

    // Add all tracks from stream to peer connection
    stream.getTracks().forEach(track => remoteConnection.addTrack(track, stream));

    // Send Candidtates to establish a channel communication to send stream and data
    remoteConnection.onicecandidate = ({ candidate }) => {
      candidate && socket.emit('candidate', socketId, candidate);
    };

    // Receive stream from remote client and add to remote video area
    remoteConnection.ontrack = ({ streams: [ stream ] }) => {
      remoteVideo.srcObject = stream;
    };

    // Chanel Received
    remoteConnection.ondatachannel = ({ channel }) => {
      // Store Channel
      remoteChannel = channel;

      // Function Called When Receive Message in Channel
      remoteChannel.onmessage = (event) => console.log(`Receive: ${event.data}`);
      // Function Called When Channel is Opened
      remoteChannel.onopen = (event) => console.log(`Channel Changed: ${event.type}`);
      // Function Called When Channel is Closed
      remoteChannel.onclose = (event) => console.log(`Channel Changed: ${event.type}`);
    }

    // Set Local And Remote description and create answer
    remoteConnection
      .setRemoteDescription(description)
      .then(() => remoteConnection.createAnswer())
      .then(answer => remoteConnection.setLocalDescription(answer))
      .then(() => {
        socket.emit('answer', socketId, remoteConnection.localDescription);
      });
  });


RTCDataChannel을 수신하기 위해 새 줄에 초점을 맞춥니다.

// Chanel Received
remoteConnection.ondatachannel = ({ channel }) => {
      // Store Channel
      remoteChannel = channel;

      // Function Called When Receive Message in Channel
      remoteChannel.onmessage = (event) => console.log(`Receive: ${event.data}`);
      // Function Called When Channel is Opened
      remoteChannel.onopen = (event) => console.log(`Channel Changed: ${event.type}`);
      // Function Called When Channel is Closed
      remoteChannel.onclose = (event) => console.log(`Channel Changed: ${event.type}`);
    }


로그 메시지



이전 게시물에서 우리는 채팅 메시지를 표시하기 위해 div를 만들었습니다. 이 영역을 사용하여 수신 및 전송된 모든 메시지를 기록합니다.

먼저 다음과 같이 logMessage 함수를 생성합니다.

const logMessage = (message) => {
  const newMessage = document.createElement('div');
  newMessage.innerText = message;
  messagesEl.appendChild(newMessage);
};


그런 다음 다음과 같이 console.log 기능을 logMessage 기능으로 변경하는 채널 기능을 변경하십시오.

// Function Called When Receive Message in Channel
localChannel.onmessage = (event) => logMessage(`Receive: ${event.data}`);
    // Function Called When Channel is Opened
    localChannel.onopen = (event) => logMessage(`Channel Changed: ${event.type}`);
    // Function Called When Channel is Closed
    localChannel.onclose = (event) => logMessage(`Channel Changed: ${event.type}`);


remoteChannel과 동일하게 만듭니다.

마지막으로 메시지를 보낼 보내기 버튼을 클릭하는 기능을 만들었습니다.

// Map the 'message-button' click
sendButton.addEventListener('click', () => {
    // GET message from input
    const message = messageInput.value;
    // Clean input
    messageInput.value = '';
    // Log Message Like Sended
    logMessage(`Send: ${message}`);

    // GET the channel (can be local or remote)
    const channel = localChannel || remoteChannel;
// Send message. The other client will receive this message in 'onmessage' function from channel
    channel.send(message);
  });


최종 결과는 다음과 같습니다.



참조



WebRTC API

WebRTC in real world

다음 단계



GitHub에서 모든 코드를 볼 수 있습니다.

읽어주셔서 감사합니다. 기여와 함께 의견을 남겨주세요.

좋은 웹페이지 즐겨찾기