diff --git a/client/package-lock.json b/client/package-lock.json index c2583c4..b671692 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -31,6 +31,7 @@ "next-auth": "^4.24.8", "next-themes": "^0.3.0", "next-video": "^1.2.0", + "peerjs": "^1.5.4", "react": "^18", "react-dom": "^18", "react-hook-form": "^7.53.1", @@ -2168,6 +2169,14 @@ "sparse-bitfield": "^3.0.3" } }, + "node_modules/@msgpack/msgpack": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz", + "integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==", + "engines": { + "node": ">= 10" + } + }, "node_modules/@mux/mux-node": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/@mux/mux-node/-/mux-node-8.8.0.tgz", @@ -9004,6 +9013,41 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/peerjs": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/peerjs/-/peerjs-1.5.4.tgz", + "integrity": "sha512-yFsoLMnurJKlQbx6kVSBpOp+AlNldY1JQS2BrSsHLKCZnq6t7saHleuHM5svuLNbQkUJXHLF3sKOJB1K0xulOw==", + "dependencies": { + "@msgpack/msgpack": "^2.8.0", + "eventemitter3": "^4.0.7", + "peerjs-js-binarypack": "^2.1.0", + "webrtc-adapter": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/peer" + } + }, + "node_modules/peerjs-js-binarypack": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/peerjs-js-binarypack/-/peerjs-js-binarypack-2.1.0.tgz", + "integrity": "sha512-YIwCC+pTzp3Bi8jPI9UFKO0t0SLo6xALnHkiNt/iUFmUUZG0fEEmEyFKvjsDKweiFitzHRyhuh6NvyJZ4nNxMg==", + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/peer" + } + }, + "node_modules/peerjs/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -9901,6 +9945,11 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/sdp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.0.tgz", + "integrity": "sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -11034,6 +11083,18 @@ "node": ">=4.0" } }, + "node_modules/webrtc-adapter": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-9.0.1.tgz", + "integrity": "sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==", + "dependencies": { + "sdp": "^3.2.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, "node_modules/whatwg-url": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", diff --git a/client/package.json b/client/package.json index 9783d97..4eeae84 100644 --- a/client/package.json +++ b/client/package.json @@ -35,6 +35,7 @@ "next-auth": "^4.24.8", "next-themes": "^0.3.0", "next-video": "^1.2.0", + "peerjs": "^1.5.4", "react": "^18", "react-dom": "^18", "react-hook-form": "^7.53.1", diff --git a/client/src/components/PeerConnect/index.tsx b/client/src/components/PeerConnect/index.tsx new file mode 100644 index 0000000..c2ba661 --- /dev/null +++ b/client/src/components/PeerConnect/index.tsx @@ -0,0 +1,94 @@ +"use client"; + +import { useEffect, useRef, useState } from "react"; +import Peer from "peerjs"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; + +export default function PeerConnect() { + const myVideoRef = useRef(null); + const callingVideoRef = useRef(null); + + const [peerInstance, setPeerInstance] = useState(null); + const [uniqueId, setUniqueId] = useState(""); + const [idToCall, setIdToCall] = useState(""); + + const generateRandomString = () => Math.random().toString(36).substring(2); + + const handleCall = () => { + navigator.mediaDevices + .getUserMedia({ + video: true, + audio: true, + }) + .then((stream) => { + const call = peerInstance?.call(idToCall, stream); + if (call) { + call.on("stream", (userVideoStream) => { + console.log("4"); + if (callingVideoRef.current) { + console.log("5"); + callingVideoRef.current.srcObject = userVideoStream; + } + }); + } + }); + }; + + useEffect(() => { + setUniqueId(generateRandomString()); + }, []); + + useEffect(() => { + if (uniqueId && typeof window !== "undefined") { + const peer: Peer = new Peer(uniqueId, { + host: "localhost", + port: 9000, + path: "/myapp", + }); + + setPeerInstance(peer); + + navigator.mediaDevices + .getUserMedia({ + video: true, + audio: true, + }) + .then((stream) => { + if (myVideoRef.current) { + myVideoRef.current.srcObject = stream; + } + + peer.on("call", (call) => { + call.answer(stream); + call.on("stream", (userVideoStream) => { + if (callingVideoRef.current) { + callingVideoRef.current.srcObject = userVideoStream; + } + }); + }); + }); + + return () => { + if (peer) { + peer.destroy(); + } + }; + } + }, [uniqueId]); + + return ( +
+

your id: {uniqueId}

+
+ ); +}