Peer-to-Peer

app.js
const frontendsocket = io(); const myface = document.getElementById("myface"); const mute = document.getElementById("mute"); const camera = document.getElementById("camera"); const camerasSelect = document.getElementById("cameras"); const call = document.getElementById("call"); call.hidden = true; let myStream; let muted = false; let cameraOff = false; let roomName; let myPeerConnection; async function getCamera() { try { const devices = await navigator.mediaDevices.enumerateDevices(); //장치 리스트 가져오기 const cameras = devices.filter((device) => device.kind === "videoinput"); //videoinput만 필터링 const CurrentCamera = myStream.getVideoTracks()[0]; cameras.forEach((camera) => { const option = document.createElement("option"); option.value = camera.deviceId; //카메라의 고유 값을 value에 넣기 option.innerText = camera.label; //사용자가 선택할 때는 label을 보고 선택 가능하게 하기 if (CurrentCamera.lable === camera.label) { option.selected = true; } camerasSelect.appendChild(option); //카메라 정보를 option 항목에 넣어주기 }); } catch (e) { console.log(e); } } async function getMedia(deviceId) { const initialConstraints = { //deviceId가 없을 때 실행 audio: true, video: { facingMode: "environment" }, //카메라가 전후면에 달려있을 > 경우 후면 카메라의 정보를 받음 }; const cameraConstraints = { //deviceId가 있을 때 실행 audio: true, video: { deviceId: { exact: deviceId } }, }; try { myStream = await navigator.mediaDevices.getUserMedia( deviceId ? cameraConstraints : initialConstraints ); myface.srcObject = myStream; if (!deviceId) { //처음 딱 1번만 실행(getMedia를 실행할 때만) await getCamera(); } } catch (e) { console.log(e); } } function handleMuteButton() { myStream .getAudioTracks() .forEach((track) => (track.enabled = !track.enabled)); if (!muted) { mute.innerText = "Unmute"; muted = true; } else { mute.innerText = "Mute"; muted = false; } } function handleCameraButton() { console.log(myStream.getVideoTracks()); myStream .getVideoTracks() .forEach((track) => (track.enabled = !track.enabled)); if (!cameraOff) { camera.innerText = "Turn Camera On"; cameraOff = true; } else { camera.innerText = "Turn Camera Off"; cameraOff = false; } } async function handleCameraChange() { await getMedia(camerasSelect.value); } mute.addEventListener("click", handleMuteButton); camera.addEventListener("click", handleCameraButton); camerasSelect.addEventListener("input", handleCameraChange); //카메라 변경 확인 //Welcome Form (choose a room) const welcome = document.getElementById("welcome"); const welcomeForm = welcome.querySelector("form"); async function startMedia() { welcome.hidden = true; call.hidden = false; await getMedia(); makeConnection(); } function handleWelcomeSubmit(event) { event.preventDefault(); const input = welcomeForm.querySelector("input"); frontendsocket.emit("join_room", input.value, startMedia); roomName = input.value; input.value = ""; } welcomeForm.addEventListener("submit", handleWelcomeSubmit); // Socket Code frontendsocket.on("welcome", async () => { const offer = await myPeerConnection.createOffer(); //내가 누구인지를 알려주는 내용 myPeerConnection.setLocalDescription(offer);// 내 위치정보를 연결 console.log("sent the offer"); frontendsocket.emit("offer", offer, roomName); }); frontendsocket.on("offer", (offer) => { console.log(offer); }); //RTC code function makeConnection() { myPeerConnection = new RTCPeerConnection(); //RTCPeerConnection 인스턴스 생성 myStream .getTracks() .forEach((track) => myPeerConnection.addTrack(track, myStream)); //영상,음성 트랙을 myPeerConnection에 추가해준다. ->P2P 연결 }
server.js
import http from "http"; import SocketIO from "socket.io"; import { instrument } from "@socket.io/admin-ui"; import express from "express"; const app = express(); const PORT = 3000; app.set("view engine", "pug"); app.set("views", __dirname + "/views"); // 기본 path를 /public으로 설정 app.use("/public", express.static(__dirname + "/public")); app.get("/", (_, res) => res.render("home")); app.get("/*", (_, res) => res.redirect("/")); const httpServer = http.createServer(app); const wsServer = SocketIO(httpServer); wsServer.on("connection", (backendsocket) => { backendsocket.on("join_room", (roomName, done) => { backendsocket.join(roomName); done(); backendsocket.to(roomName).emit("welcome"); //특정 room에 이벤트 보내기 }); backendsocket.on("offer", (offer, roomName) => { backendsocket.to(roomName).emit("offer", offer); }); //offer 이벤트가 들어오면 roomName에 있는 모두에게 offer 이벤트를 전달하면서 offer를 뿌린다. }); const handleListen = () => console.log(`Listening on > http://localhost:${PORT}`); httpServer.listen(PORT, handleListen);