From ced009a0bfaa83a28e2b8daeaa49f1e59ee0c9c3 Mon Sep 17 00:00:00 2001 From: yewon830 Date: Wed, 21 Aug 2024 21:55:30 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat=20:=20openvidu=20browser=20=ED=8A=9C?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=EC=96=BC=20=EC=BD=94=EB=93=9C=20=EB=B0=98?= =?UTF-8?q?=EC=98=81,=20=ED=83=80=EC=9E=85=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=8F=20=ED=95=A8=EC=88=98=ED=98=95=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/package.json | 1 + front/server/signalingServer.ts | 75 ---- front/src/App.css | 3 + front/src/App.tsx | 1 + front/src/components/VideoCall/OvVideo.tsx | 22 + front/src/components/VideoCall/UserVideo.css | 18 + .../VideoCall/UserVideoComponents.tsx | 30 ++ .../components/VideoCall/VideoCallBoxList.tsx | 384 +++++++++++++----- .../VideoCall/registerServiceWorker.js | 117 ++++++ front/src/components/VideoCall/video.css | 231 +++++++++++ front/yarn.lock | 72 +++- 11 files changed, 780 insertions(+), 174 deletions(-) delete mode 100644 front/server/signalingServer.ts create mode 100644 front/src/components/VideoCall/OvVideo.tsx create mode 100644 front/src/components/VideoCall/UserVideo.css create mode 100644 front/src/components/VideoCall/UserVideoComponents.tsx create mode 100644 front/src/components/VideoCall/registerServiceWorker.js create mode 100644 front/src/components/VideoCall/video.css diff --git a/front/package.json b/front/package.json index 30c588e7..72f19126 100644 --- a/front/package.json +++ b/front/package.json @@ -18,6 +18,7 @@ "axios": "^1.7.2", "express": "^4.19.2", "jwt-decode": "^4.0.0", + "openvidu-browser": "^2.30.1", "phaser": "^3.80.1", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/front/server/signalingServer.ts b/front/server/signalingServer.ts deleted file mode 100644 index 91827928..00000000 --- a/front/server/signalingServer.ts +++ /dev/null @@ -1,75 +0,0 @@ -import express from 'express'; -import http from 'http'; -import { Server as socketIo } from 'socket.io'; - -interface Room{ - users: string[] -} - - -const app = express(); // express 애플리케이션 인스턴스 생성 -const server = http.createServer(app); // hTTP 서버 생성, 이 서버가 Express 애플리케이션 처리 - -// socket.io 서버 인스턴스 -const io = new socketIo(server, { - cors: { - origin: true, // FIXME :보안을 위해 CORS 설정 구체화 해줘야 함 - }, -}); - -const totalRooms :{[key: string] : Room} = {}; // {방의 이름 : [user 소켓 id]}의 객체 - -// 클라이언트가 socket.io 서버에 연결 되어있을 때 -io.on('connection', (socket: any) => { - console.log(`Client connected. socket: ${socket.id}`); - - // 채팅을 위한 방에 접속 - socket.on('join', (data: { room: string }) => { - if(!data?.room) return; - socket.join(data.room); - // 방이 없으면 새로운 방을 만든다. - if(!totalRooms[data.room]){ - totalRooms[data.room] = {users: []}; - } - //방에 사용자를 추가 - totalRooms[data.room].users.push(socket.id); - socket.room = data.room; - - console.log(`Join room ${data.room}. Socket ${socket.id}`); - }); - - // peer가 제안 :: SDP 방식(제안-응답) - socket.on('offer', (data: { sdp: string; room: string }) => { - socket.to(data.room).emit('offer', { sdp: data.sdp, sender: socket.id }); - }); - - // peer가 응답 - socket.on('answer', (data: { sdp: string; room: string }) => { - socket.to(data.room).emit('answer', { sdp: data.sdp, sender: socket.id }); - }); - - // peer가 자신이 데이터를 보낼 수 있는 네트워크 경로를 찾기 위해 ICE 프로세스 수행 - socket.on('candidate', (data: { candidate: string; room: string }) => { - socket.to(data.room).emit('candidate', { candidate: data.candidate, sender: socket.id }); - }); - - // 연결 종료 - socket.on('disconnect', () => { - // 방에서 사용자 제거 - if(socket.room && totalRooms[socket.room]){ - totalRooms[socket.room].users = totalRooms[socket.room].users.filter( - (id) => id !==socket.id - ) - //사용자가 한명도 없으면 방 없앰 - if(totalRooms[socket.room].users.length ===0){ - delete totalRooms[socket.room]; - } - } - console.log('Client disconnected'); - }); - }); - -// 포트 실행 -server.listen(5001, () => { // 포트 번호 - console.log('Listening on port 5001'); -}); \ No newline at end of file diff --git a/front/src/App.css b/front/src/App.css index e69de29b..0e6befce 100644 --- a/front/src/App.css +++ b/front/src/App.css @@ -0,0 +1,3 @@ +.stream-container { + padding: 0; +} \ No newline at end of file diff --git a/front/src/App.tsx b/front/src/App.tsx index 099d9b0a..777ec312 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -7,6 +7,7 @@ import { ServerMap } from "./components/Phaser/ServerMap"; import Home from "./pages/Home"; import Join from "./pages/Join"; import Login from "./pages/Login"; +import VideoCallBoxList from "./components/VideoCall/VideoCallBoxList"; function App() { return ( diff --git a/front/src/components/VideoCall/OvVideo.tsx b/front/src/components/VideoCall/OvVideo.tsx new file mode 100644 index 00000000..3fd9caaa --- /dev/null +++ b/front/src/components/VideoCall/OvVideo.tsx @@ -0,0 +1,22 @@ +import { StreamManager } from 'openvidu-browser'; +import React, { useRef, useEffect } from 'react'; + + +interface OpenViduVideoComponentProps { + streamManager: StreamManager | undefined; +} + +// 최종적으로 미디어 스트림을 표시하는 최종 HTMl 래핑. +const OpenViduVideoComponent: React.FC = ({ streamManager }) => { + const videoRef = useRef(null); // videoRef의 타입을 HTMLVideoElement로 지정 + + useEffect(() => { + if (streamManager && videoRef.current) { + streamManager.addVideoElement(videoRef.current); + } + }, [streamManager]); + + return