* 맨 하단 샘플코드있음.
WebRTC
An open framework for the web that enables Real-Time Communications (RTC) capabilities in the browser.
webrtc.org
😀 WebRTC
- 실시간 통신 기능의 애플리케이션 기능
- 동영상, 음악, 데이터 앱 간 전송 가능
- 음성/영상 솔루션 구축
- 모든 브라우저에서 JS API 제공
- Android, ios 라이브러리 제공
- 오픈소스
😀 WebRTC API
1. 미디어 캡처 기기
동영상 카메라, 마이크, 화면 캡처 기기 포함된다.
카메라, 마이크 경우 navigator.mediaDevices.getUserMedia() 를 사용하여 MediaStreams를 캡처한다.
화면 녹화에는 navigator.mediaDevies.getDisplayMedia() 를 사용.
2. P2P 연결
RTCPeerConnection 인터페이스에서 처리한다.
(WebRTC에서 두 피어 간의 연결을 설정하고 제어하는 중심)
* Peer-to-Peer(P2P)
: 컴퓨터 네트워크에서 사용되며 중앙서버를 경유하지 않고 컴퓨터나 장치 간 직접 통신 하는 방식을 의미
중앙서버가 필요하지 않고 각각의 디바이스가 동등한 지위를 가지는 네트워크 모델을 나타낸다
P2P 네트워크에서 각 디바이스는 Peer라고 불리며, 서로 데이터를 공유하거나 통신 가능하다.
😀 미디어 캡처 및 스트림 API
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices
MediaDevices - Web APIs | MDN
The MediaDevices interface provides access to connected media input devices like cameras and microphones, as well as screen sharing. In essence, it lets you obtain access to any hardware source of media data.
developer.mozilla.org
MediaDevices
enumerateDevices()
: 시스템에서 사용할 수 있는 미디어 입력 및 출력 장치에 대한 일련의 정보를 가져옵니다.
getSupportedConstraints()
: MediaTrackSupportedConstraints 인터페이스 에서 지원되는 제한 가능한 속성을 나타내는 것을 준수하는 객체를 반환합니다
getDisplayMedia()
: MediaStream공유 또는 녹음 목적으로 캡처할 디스플레이 또는 디스플레이의 일부(예: 창)를 선택하라는 메시지를 사용자에게 표시합니다 .
getUserMedia()
: 프롬프트를 통해 사용자의 허가를 받아 시스템의 카메라 및/또는 마이크를 켜고
MediaStream비디오 트랙 및/또는 오디오 트랙이 포함된 입력을 제공합니다.
selectAudioOutput()
: 사용자에게 특정 오디오 출력 장치를 선택하라는 메시지를 표시합니다.
EVENT
devicechange
: 미디어 입력 또는 출력 장치가 사용자 컴퓨터에 연결되거나 제거될 때 시작됩니다.
//ICE 서버
var configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };
var peerConnection = new RTCPeerConnection(configuration);
https://brunch.co.kr/@linecard/156
https://andonekwon.tistory.com/59
WebRTC란? (STUN과 TURN 서버의 이해) (2)
이전 글 복습 중간에 방화벽이 존재하거나 NAT 환경에 놓여 있는 경우에는 각 Peer에 대한 직접적인 시그널링이 불가능하다고 이야기하였다. 그렇기 떄문에 시그널링을 하고 연결을 하기 위해서
andonekwon.tistory.com
😀 Sample Code
어떠한 언어를 하기 전 샘플코드를 먼저 해보는것이 정보를 습득하는데 도움이 되기때문에
Chat GPT를 이용한 샘플코드를 생성해서 테스트를 진행해봤다.
디바이스에 캠, 마이크가 가능한 상태여야지만 가능하다.
크롬 브라우저에서만 가능하다고 하는거같은데,
local.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>로컬 WebRTC 테스트 - 로컬</title>
</head>
<body>
<h1>로컬 WebRTC 테스트 - 로컬</h1>
<video id="localVideo" autoplay></video>
<video id="remoteVideo" autoplay></video>
<script>
// 로컬 웹캠 스트림 가져오기
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(function (stream) {
var localVideo = document.getElementById('localVideo');
localVideo.srcObject = stream;
// ICE 서버 설정
var configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };
var peerConnection = new RTCPeerConnection(configuration);
// 로컬 스트림 트랙 추가
stream.getTracks().forEach(function (track) {
peerConnection.addTrack(track, stream);
});
// 원격 비디오 요소
var remoteVideo = document.getElementById('remoteVideo');
// 원격 스트림 트랙을 받아 원격 비디오에 연결
peerConnection.ontrack = function (event) {
remoteVideo.srcObject = event.streams[0];
};
// SDP offer 생성 후 로컬 설명 설정
peerConnection.createOffer()
.then(function (offer) {
return peerConnection.setLocalDescription(offer);
})
.then(function () {
// SDP offer를 원격 피어로 전송 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
sendOfferToRemote(peerConnection.localDescription);
})
.catch(function (error) {
console.error('Error creating and sending offer:', error);
});
// 원격 피어로부터 SDP answer 및 ICE 후보 처리 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
function handleRemoteAnswerAndIce(answer, iceCandidate) {
peerConnection.setRemoteDescription(new RTCSessionDescription(answer))
.then(function () {
return peerConnection.addIceCandidate(new RTCIceCandidate(iceCandidate));
})
.catch(function (error) {
console.error('Error setting remote description or adding ice candidate:', error);
});
}
// SDP answer 및 ICE 후보를 원격 피어로 전송 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
function sendAnswerAndIceToRemote(answer, iceCandidate) {
// answer와 iceCandidate를 원격 피어로 전송 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
}
})
.catch(function (error) {
console.error('Error accessing media devices:', error);
});
</script>
</body>
</html>
remote.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>로컬 WebRTC 테스트 - 원격</title>
</head>
<body>
<h1>로컬 WebRTC 테스트 - 원격</h1>
<video id="localVideo" autoplay></video>
<video id="remoteVideo" autoplay></video>
<script>
// 로컬 웹캠 스트림 가져오기 (원격에서 사용하지 않음)
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(function (stream) {
var localVideo = document.getElementById('localVideo');
localVideo.srcObject = stream;
})
.catch(function (error) {
console.error('Error accessing media devices:', error);
});
// ICE 서버 설정
var configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };
var peerConnection = new RTCPeerConnection(configuration);
// 원격 비디오 요소
var remoteVideo = document.getElementById('remoteVideo');
// 원격 스트림 트랙을 받아 원격 비디오에 연결
peerConnection.ontrack = function (event) {
remoteVideo.srcObject = event.streams[0];
};
// 원격 피어로부터 SDP offer 및 ICE 후보 처리 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
function handleRemoteOfferAndIce(offer, iceCandidate) {
peerConnection.setRemoteDescription(new RTCSessionDescription(offer))
.then(function () {
return peerConnection.createAnswer();
})
.then(function (answer) {
return peerConnection.setLocalDescription(answer);
})
.then(function () {
// SDP answer를 원격 피어로 전송 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
sendAnswerToRemote(peerConnection.localDescription);
})
.catch(function (error) {
console.error('Error creating and sending answer:', error);
});
// ICE 후보를 추가 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
peerConnection.addIceCandidate(new RTCIceCandidate(iceCandidate))
.catch(function (error) {
console.error('Error adding ice candidate:', error);
});
}
// SDP answer를 원격 피어로 전송 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
function sendAnswerToRemote(answer) {
// answer를 원격 피어로 전송 (시그널링 서버 또는 다른 통신 메커니즘을 사용)
}
</script>
</body>
</html>