이번 졸업 프로젝트를 이루는 여러 기능 중 가장 핵심 기능은 실시간 화상회의 기능이다. 오디오, 비디오 등을 real-time으로 공유하는 기능을 제공하는 여러 API중 WebRTC를 사용해서 기능을 구현하기로 했고, 오늘부터 공부를 해보려고 합니다.!
전반적인 이해는 Google Developers - WebRTC Tutorial을 참고했습니다.
MDN - WebRTC 문서에 따르면,
WebRTC(Web Real-Time Communication)은 웹 애플리케이션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어를 포착하고 마음대로 스트림할 뿐 아니라, 임의의 데이터도 교환할 수 있도록 하는 기술입니다.
이다. Google Chrome이 오픈소스화 한 프로젝트에서 기원했고, 다음과 같은 과정을 통해 데이터를 주고받는다.
한마디로 별다른 플러그인이나 소프트웨어 설치없이 브라우저간 Real Time Communication을 제공하는 JavaScript API이다.
위키피디아에 따르면,
getUserMedia
: 오디오와 비디오 미디어를 가져온다.RTCPeerConnection
: 피어 간 오디오, 비디오 통신을 활성화한다.RTCDataChannel
: 피어 간 양방향 임의 데이터 통신을 허용한다.자세한 동작은 실습을 통해 익히려고 한다. How To Create A Video Chat App With WebRTC의 튜토리얼을 참고해서 실습을 해봤습니다.
npm init -y
npm i express ejs socket.io
npm i uuid
npm i --save-dev nodemon
"scripts": {
"devStart": "nodemon server.js"
},
Peer-to-Peer connection을 쉽게 구현할 수 있게 도와주는 API이다. peerjs.com에서 자세한 설명을 찾을 수 있다.
-> 여기서는 여러 user를 connect하고, user들에게 고유 id를 부여하기 위해 사용한다.
npm i -g peer
peerjs --port 3001
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs') // view engine 설정
app.use(express.static('public')) // html, css등 static file들 경로 설정
// creating a new room -> redirect to the room
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`) // dynamic url -> url 뒤에 uuid 붙음
})
// 해당 room으로 들어가게
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) // new user join시 알림
socket.broadcast.to(roomId).emit('user-connected', userId);
socket.on('disconnect', () => {
socket.broadcast.to(roomId).emit('user-disconnected', userId);
})
})
})
server.listen(3000)
const socket = io('/') // socket이 app이 실행중인 root path와 연결되도록
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
host: '/', //root
port: '3001'
}) // connection to peer server
const myVideo = document.createElement('video')
myVideo.muted = true
const peers = {}
// webcam 띄우기
navigator.mediaDevices.getUserMedia({
video: true,
// audio: true
}).then(stream => {
addVideoStream(myVideo, stream) // video 띄우기
// recieving calls
myPeer.on('call', call => {
call.answer(stream) //추가된 new user의 call 띄우기
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream);
}) ///추가된 new user의 입장에서도 기존 user 띄우기
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
})
})
// 방 나간 유저 바로 지우기
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
// 비디오 띄우기
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
// making calls
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;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
const ROOM_ID = "<%= roomId %>";
</script>
<script defer src="https://unpkg.com/peerjs@1.3.1/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>
nodejs를 잘 모르는 상태에서 구현하려고 하니 한번에 100% 이해는 어려운것같다^_ㅠ,, 일단 오늘은 여기까지