본 포스트는, 글쓴이가 영상통화 웹사이트를 만들면서 개인적 정리/참고를 위해서 작성되었습니다. 앞으로도 놀지말고 빨리빨리 만들자 이말이야...💻
WebRTC(Web Real Time Communication)의 약자이다. WebRTC는 통신 표준으로, 웹 브라우저간 실시간 영상/음성/데이터 통신을 가능하게 해준다. 즉 별도의 플러그인이나 프로그램이 필요 없다! WebRTC는 P2P 구조로 되어있다. 기기간 통신하기 때문에 서버의 성능이 크게 필요하지 않다. WebRTC는 구글에 제안되었다. 이후 Mozilla, Opera, MS 등의 기관들이 표준 확립에 참여하고있다. WebRTC 공식 웹사이트
PeerJS는 WebRTC를 쉽게 사용하기 위해 만들어진 wrapper이다. ID만 지정해주면 손쉽게 P2P 연결을 처리해준다! PeerJS 공식 웹사이트
- 배포 서버는 aws EC2
- 웹 프레임워크는 Express.js
- WebRTC 이외의 실시간 통신은 Socket.IO
- Let's Encrypt로 https 적용(크롬 기준 WebRTC에 https가 필요)
- PeerJS 서버는 공식 서버를 사용
간단한 결과는 다음과 같다. 왼쪽 부터 데스크탑, 아이패드, 아이폰으로 캡쳐한 영상이다. 😎
npm init -y
npm i uuid socket.io express ejs
npm i -g peer
const express = require('express');
const app = express();
const { v4: uuidV4 } = require('uuid');
const fs = require('fs');
const https = require('https');
const server = https.createServer(
{
key: fs.readFileSync('/etc/letsencrypt/live/your.domain.here/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/your.domain.here/cert.pem'),
ca: fs.readFileSync('/etc/letsencrypt/live/your.domain.here/chain.pem'),
requestCert: false,
rejectUnauthorized: false,
},
app
);
const io = require('socket.io')(server);
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`);
});
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room });
});
io.on('connection', (socket) => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId);
socket.to(roomId).broadcast.emit('user-connected', userId);
socket.on('disconnect', () => {
socket.to(roomId).broadcast.emit('user-disconnected', userId);
});
});
});
server.listen(portNumber);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script>
const ROOM_ID = '<%= roomId %>';
</script>
<script
defer
src="https://unpkg.com/peerjs@1.2.0/dist/peerjs.min.js"
></script>
<script src="/socket.io/socket.io.js" defer></script>
<script src="script.js" defer></script>
<title>Document</title>
<style>
#video-grid {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
grid-auto-rows: 300px;
}
video {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
</head>
<body>
<div id="video-grid"></div>
</body>
</html>
const socket = io('/');
const videoGrid = document.getElementById('video-grid');
const myPeer = new Peer();
const myVideo = document.createElement('video');
myVideo.muted = true;
const peers = {};
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((stream) => {
addVideoStream(myVideo, stream);
myPeer.on('call', (call) => {
call.answer(stream);
const video = document.createElement('video');
call.on('stream', (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on('user-connected', (userId) => {
connectToNewUser(userId, stream);
});
});
socket.on('user-disconnected', (userId) => {
if (peers[userId]) peers[userId].close();
});
myPeer.on('open', (id) => {
socket.emit('join-room', ROOM_ID, id);
});
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream);
const video = document.createElement('video');
call.on('stream', (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
call.on('close', () => {
video.remove();
});
peers[userId] = call;
}
function addVideoStream(video, stream) {
video.srcObject = stream;
video.addEventListener('loadedmetadata', () => {
video.play();
});
videoGrid.append(video);
}
안녕하세요. 좋은 글 감사합니다.
WebRTC를 적용한 웹 사이트를 하이브리드 앱으로 뽑고
이후 서비스 내부에서 음성채팅을 구현하려고 합니다.
이런 경우 상대방이 폰에 앱을 설치했다는 가정하에
누군가 음성채팅을 연결하고자 할때 연결을 시도한다는 알람이 가게끔 할 수 있나요? (ex 보이스톡)