본문 바로가기

Computer science/WebRTC

WebRTC - other parts

Remote streams

RTCPeerConnection이 다른 동료와 연결될 때, 비디오나 오디오를 송출하는 것이 가능해 진다. 바로 이 때가 getUserMedia()로 받은 송출 흐름(stream)을 RTCPeerConnection에 연결할 때이다. 다른 동료에게 media를 전송할 때, 최소 한 개 이상의 media track으로 구성된 media stream을 개별적으로 RTCPeerConnection에 추가한다. 

const localStream = await getUserMedia({vide: true, audio: true});
const peerConnection = new RTCPeerConnection(iceConfig);
localStream.getTracks().forEach(track => {
    peerConnection.addTrack(track, localStream);
});

트랙이 다른 동료와 연결되기 전에도 RTCPeerConnection에 추가할 수 있기 때문에, 이 연결 작업을 최대한 빨리 하는 게 좋다.

 

Adding remote tracks

RTCPeerConnectiontrack 이벤트 리스너를 설정함으로써 다른 동료가 추가한 트랙들에 대한 정보를 받을 수 있다. 

재생은 MediaStream 오브젝트에서 실행된다. 따라서, empty instance를 먼저 생성하고 트랙을 다른 동료로부터 받는 대로 empty instance에 채워 넣으면 된다.

const remoteStream = MediaStream();
const remoteVideo = document.querySelector('#remoteVideo');
remoteVideo.srcObject = remoteStream;

peerConenction.addEventListener('track', async (event) => {
    remoteStream.addTrack(event.track, remoteStream);
});

 

Data channels

WebRTC표준은 RTCPeerConnection을 이용해 arbitrary data를 보내는 API도 포함한다. RTCPeerConnection 오브젝트의 createDataChannel()함수를 호출하면 되고, 이 함수는 RTCDataChannel 오브젝트를 반환한다.

const peerConnection = new RTCPeerConnection(configuration);
const dataChannel = peerConnection.createDataChannel();

다른 동료는 RTCPeerConnection 오브젝트의 datachannel 이벤트를 이용해 data channels를 수신할 수 있다. 수신된 이벤트는 RTCDataChannelEvent 타입이고 동료들간 연결된 RTCDataChannel을 나타내는 channel 프로퍼티를 포함한다. 

 

const peerConnection = new RTCPeerConnection(configuration);
peerConnection.addEventListener('datachannel', event => {
    const dataChannel = event.channel;
});

 

Open and close events

data channel을 이용해 데이터를 보내기 전에 data channel이 열렸는지부터 확인을 해야 한다.

open 이벤트를 이용해 data channel이 열렸는지 확인할 수 있고, 마찬가지로 close 이벤트를 이용해 data channel이 닫혔는지 확인할 수 있다.

const messageBox = document.querySelector('#messageBox');
const sendButton = document.querySelector('#sendButton');
const peerConnection = new RTCPeerConnection(configuration);
const dataChannel = peerConnection.createDataChannel();

// Enable textarea and button when opened
dataChannel.addEventListener('open', event => {
    messageBox.disabled = false;
    messageBox.focus();
    sendButton.disabled = false;
})

// Disabled input when closed
dataChannel.addEventListener('close', event => {
    messageBox.disabled = false;
    sendButton.disabled = false;
});

 

Messages

메세지를 보내려면 RTCDataChannelsend()함수를 호출하면 된다. data 파라미터로는 string, Blob, ArrayBuffer, ArrayBufferView가 있다. 

const messageBox = document.querySelector('#messageBox');
const sendButton = document.querySelector('#sendButton');

// Send a simply text message when we click the button
sendButton.addEventListener('click', event => {
    const message = messageBox.textContent;
    dataChannel.send(message);
})

반대편의 동료는 message 이벤트를 이용해 RTCDataChannel로 전송된 메세지를 받아볼 수 있다.

const incomingMessages = document.querySelector('#incomingMessages');

const peerConnection = new RTCPeerConnection(configuration);
const dataChannel = peerConnection.createDataChannel();

// Append new messages to the box of incoming messages
dataChannel.addEventListener('message', event => {
    const message = event.data;
    incomingMessages.textContent += message + '\n';
});

 

 

Turn server

동료들이 같은 local network에 있지 않는 이상 direct socket을 사용하는 것은 불가능할 수도 있다. 따라서 서버 기능을 위한 WebRTC 애플리케이션을 만들기 위해선 연결된 동료들간의 traffic을 중계(relaying)할 필요가 있다. 이 때 가장 많이 사용하는 방법은 TURN(Traversal Using Relay NAT) 서버를 이용하는 것이다. TURN은 network traffic을 중계하기 위한 규약이다. 

 

온라인엔 TURN서버를 사용하기 위한 몇 가지 선택지들이 있다. COTURN project(open-soruce) 같은 self-hosted 애플리케이션도 있고 cloud provided services도 있다.

 

TURN 서버가 준비됐으면 이제 올바른 RTCConfiguration만 있으면 된다. 

아래 코드 스니펫은 TURN 서버에 연결할 때 필요한 RTCPeerConnection을 위한 구성의 예시이다. 

TURN 서버의 hostname은 my-turn-server.mycompany.com이고, 19403포트를 이용한다. 

서버에 안전히 접근하기 위해 usernamecredentials 프로퍼티를 사용할 수 있다.

const iceConfiguration = {
    iceServers: [
        {
            urls: 'turn:my-turn-server.mycompany.com:19403',
            username: 'optional-username',
            credentials: 'auth-token'
        }
    ]
}

const peerConnection = new RTCPeerConnection(iceConfiguration);

COUTRN project: https://github.com/coturn/coturn

 

Testing

자동으로 WebRTC를 테스트하기 위한 코드를 작성할 때 유용한 구성들이 있다. 

 

Chrome

  • --allow-file-access-from-files - Allows API access for file:// URLs
  • --disable-translate - Disables the translation popup
  • --use-fake-ui-for-media-stream - Provide fake media streams. Useful when running on CI servers.
  • --use-file-for-fake-audio-capture=<filename> - Provide a file to use when capturing audio.
  • --use-file-for-fake-video-capture=<filename> - Provide a file to use when capturing video.
  • --headless - Run in headless mode. Useful when running on CI servers.
  • --mute-audio - Mute audio output.

 

Unified Plan transition guide

구글은 Chrome의 WebRTC 구현을 바꾸려고 계획 중이다. 

현재 "Plan B"라고 불리는 SDP format을 사용하고 있지만 앞으로는 "Unified Plan"이라고 불리는 conformant format을 사용할 것이다. 이 계획에는 4개의 phases와 1개의 일시적인(transient) API를 포함한다.

 

Who will be affected

하나의 PeerConnection을 이용해 다수의 비디오나 오디오 트랙을 이용할 사람들은 Unified Plan을 이용해 제품을 테스트 해야 할 것이다.

크롬이 아닌 브라우저에서 크롬을 호출하는 경우에 offer의 형태가 달라질 수 있다.

구체적인 SDP parsing을 이용하고 msid attributes를 신경쓰는 사람들은 parsing 코드가 새로운 format을 잘 반영하는지 점검해야 한다.

이번 변화에 의해 영향을 받을 앱에 대한 기준은 없다. 하지만, 하나의 RTCPeerCoonection에 하나의 비디오나 오디오만 쓰는 애플리케이션은 영향을 받지 않을 가능성이 높다.

 

더 자세한 내용은 https://webrtc.org/getting-started/unified-plan-transition-guide에서 확인하자.

 

본 게시글은 www.webRTC.org 의 guide 부분을 번역한 글입니다.

'Computer science > WebRTC' 카테고리의 다른 글

WebRTC 참고 자료 모음  (0) 2020.07.10
webRTC 용어 정리  (0) 2020.07.10
WebRTC - peer connections  (0) 2020.07.02
WebRTC - Media capture and constraints  (0) 2020.07.02
WebRTC - Media devices  (0) 2020.07.02