From fd4b4384ac847803ba905a96b91b0d13eeb37ef1 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Fri, 13 Dec 2024 19:14:37 +0530 Subject: [PATCH 01/12] click to chat button --- src/pages/VirtualSpace.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pages/VirtualSpace.tsx b/src/pages/VirtualSpace.tsx index c9ab5c8..ec35f1b 100644 --- a/src/pages/VirtualSpace.tsx +++ b/src/pages/VirtualSpace.tsx @@ -5,6 +5,7 @@ import OtherUser from "@/components/UserAvatar/OtherUser"; import { handleKeyPress } from "@/lib/helperFns/handleKeyPress"; import UserDetails from "@/components/UserDetails/UserDetails"; import GroupChat from "@/components/Chat/GroupChat/GroupChat"; +import { Button } from "@/components/ui/button"; const VirtualSpace = () => { const [position, setPosition] = useState({ x: 0, y: 0 }); @@ -16,6 +17,7 @@ const VirtualSpace = () => { const [latestMessage, setLatestMessage] = useState(""); const [userMsg, setUserMsg] = useState(""); const [proximityMessage, setProximityMessage] = useState(null); + const [nearUser, setNearUser] = useState(null); useEffect(() => { const socket = new WebSocket(import.meta.env.VITE_WS_SERVER_URL); @@ -74,6 +76,7 @@ const VirtualSpace = () => { setProximityMessage( `User/s ${nearbyUsers.join(", ")} is near you` ); + setNearUser(nearbyUsers); } } else { setProximityMessage(null); @@ -204,8 +207,13 @@ const VirtualSpace = () => { {proximityMessage && ( -
- {proximityMessage} +
+
+ {proximityMessage} +
+
)}
From 98454a4df7cb3d8e3c105e8ad86419d0e8a23a2a Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Fri, 13 Dec 2024 20:51:41 +0530 Subject: [PATCH 02/12] video call button --- src/pages/VirtualSpace.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/VirtualSpace.tsx b/src/pages/VirtualSpace.tsx index ec35f1b..26474b4 100644 --- a/src/pages/VirtualSpace.tsx +++ b/src/pages/VirtualSpace.tsx @@ -196,7 +196,7 @@ const VirtualSpace = () => { />
-
Latest message: {latestMessage}
+
Latest message by user: {latestMessage}
{ +
)} From 10d3c57c109227b72651e8cdf03dea804d2a7a68 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Fri, 13 Dec 2024 21:43:20 +0530 Subject: [PATCH 03/12] chat route --- src/pages/VirtualSpace.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/VirtualSpace.tsx b/src/pages/VirtualSpace.tsx index 26474b4..52042f1 100644 --- a/src/pages/VirtualSpace.tsx +++ b/src/pages/VirtualSpace.tsx @@ -20,7 +20,7 @@ const VirtualSpace = () => { const [nearUser, setNearUser] = useState(null); useEffect(() => { - const socket = new WebSocket(import.meta.env.VITE_WS_SERVER_URL); + const socket = new WebSocket(import.meta.env.VITE_WS_SERVER_URL + "/chat"); const handleOpen = () => { console.log("Connected to Server"); From 9813572c596a140151061274f30d94508ba68cd2 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Wed, 18 Dec 2024 20:45:34 +0530 Subject: [PATCH 04/12] socket io is working prolly --- package-lock.json | 398 ++++++++++++++++++++++++- package.json | 4 + src/components/VideoCall/VideoCall.tsx | 274 +++++++++++++++++ src/config/videoSocket.ts | 70 +++++ src/main.tsx | 22 +- src/pages/VideoCallPage.tsx | 275 +++++++++++++++++ src/pages/VirtualSpace.tsx | 2 + src/types/video.ts | 14 + 8 files changed, 1048 insertions(+), 11 deletions(-) create mode 100644 src/components/VideoCall/VideoCall.tsx create mode 100644 src/config/videoSocket.ts create mode 100644 src/pages/VideoCallPage.tsx create mode 100644 src/types/video.ts diff --git a/package-lock.json b/package-lock.json index 50e6913..e10e388 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,15 @@ "version": "0.0.0", "dependencies": { "@radix-ui/react-slot": "^1.1.0", + "@types/socket.io-client": "^1.4.36", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.468.0", + "mediasoup-client": "^3.7.18", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-router-dom": "^7.0.2", + "socket.io-client": "^4.8.1", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7" }, @@ -1332,6 +1336,12 @@ "win32" ] }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1377,6 +1387,21 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -1391,6 +1416,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.10.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", @@ -1401,6 +1432,13 @@ "undici-types": "~6.20.0" } }, + "node_modules/@types/npm-events-package": { + "name": "@types/events", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz", + "integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==", + "license": "MIT" + }, "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", @@ -1429,6 +1467,12 @@ "@types/react": "*" } }, + "node_modules/@types/socket.io-client": { + "version": "1.4.36", + "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz", + "integrity": "sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", @@ -1823,6 +1867,18 @@ "postcss": "^8.1.0" } }, + "node_modules/awaitqueue": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/awaitqueue/-/awaitqueue-3.0.2.tgz", + "integrity": "sha512-AVAtRwmf0DNSesMdyanFKKejTrOnjdKtz5LIDQFu2OTUgXvB/CRTYMrkPAF/2GCF9XBtYVxSwxDORlD41S+RyQ==", + "license": "ISC", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2052,6 +2108,15 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2089,7 +2154,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2110,6 +2174,26 @@ "dev": true, "license": "MIT" }, + "node_modules/detect-europe-js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz", + "integrity": "sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2141,6 +2225,28 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, + "node_modules/engine.io-client": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", + "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -2380,6 +2486,28 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-6.0.2.tgz", + "integrity": "sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/fake-mediastreamtrack": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fake-mediastreamtrack/-/fake-mediastreamtrack-1.2.0.tgz", + "integrity": "sha512-AxHtlEmka1sqNoe3Ej1H1hJc9gjjO/6vCbCPm4D4QeEXvzhjYumA+iZ7wOi2WrmkAhGElHhBgWoNgJhFccectA==", + "license": "ISC", + "dependencies": { + "event-target-shim": "^6.0.2", + "uuid": "^9.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2640,6 +2768,23 @@ "dev": true, "license": "MIT" }, + "node_modules/h264-profile-level-id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-2.0.0.tgz", + "integrity": "sha512-X4CLryVbVA0CtjTExS4G5U1gb2Z4wa32AF8ukVmFuLdw2JRq2aHisor7SY5SYTUUrUSqq0KdPIO18sql6IWIQw==", + "license": "ISC", + "dependencies": { + "@types/debug": "^4.1.12", + "debug": "^4.3.4" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mediasoup" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2765,6 +2910,26 @@ "node": ">=0.12.0" } }, + "node_modules/is-standalone-pwa": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz", + "integrity": "sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2954,6 +3119,44 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, + "node_modules/mediasoup-client": { + "version": "3.7.18", + "resolved": "https://registry.npmjs.org/mediasoup-client/-/mediasoup-client-3.7.18.tgz", + "integrity": "sha512-cz+c2qM6KGJWKGYxySSSmkNL475mt19ZUi2tn7n+1q/kY9uZtOIS4+jebdI6wn4LMJMMpDworVM/GoBqOpzKAQ==", + "license": "ISC", + "dependencies": { + "@types/debug": "^4.1.12", + "@types/npm-events-package": "npm:@types/events@^3.0.3", + "awaitqueue": "^3.0.2", + "debug": "^4.3.7", + "fake-mediastreamtrack": "^1.2.0", + "h264-profile-level-id": "^2.0.0", + "npm-events-package": "npm:events@^3.3.0", + "queue-microtask": "^1.2.3", + "sdp-transform": "^2.15.0", + "supports-color": "^9.4.0", + "ua-parser-js": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mediasoup" + } + }, + "node_modules/mediasoup-client/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3002,7 +3205,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -3067,6 +3269,16 @@ "node": ">=0.10.0" } }, + "node_modules/npm-events-package": { + "name": "events", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3467,6 +3679,46 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.0.2.tgz", + "integrity": "sha512-m5AcPfTRUcjwmhBzOJGEl6Y7+Crqyju0+TgTQxoS4SO+BkWbhOrcfZNq6wSWdl2BBbJbsAoBUb8ZacOFT+/JlA==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.0.2.tgz", + "integrity": "sha512-VJOQ+CDWFDGaWdrG12Nl+d7yHtLaurNgAQZVgaIy7/Xd+DojgmYLosFfZdGz1wpxmjJIAkAMVTKWcvkx1oggAw==", + "license": "MIT", + "dependencies": { + "react-router": "7.0.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -3595,6 +3847,15 @@ "loose-envify": "^1.1.0" } }, + "node_modules/sdp-transform": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-2.15.0.tgz", + "integrity": "sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==", + "license": "MIT", + "bin": { + "sdp-verify": "checker.js" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -3605,6 +3866,12 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3638,6 +3905,34 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3911,6 +4206,12 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "license": "Apache-2.0" }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3965,6 +4266,57 @@ } } }, + "node_modules/ua-is-frozen": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz", + "integrity": "sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, + "node_modules/ua-parser-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-2.0.0.tgz", + "integrity": "sha512-SASgD4RlB7+SCMmlVNqrhPw0f/2pGawWBzJ2+LwGTD0GgNnrKGzPJDiraGHJDwW9Zm5DH2lTmUpqDpbZjJY4+Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "AGPL-3.0-or-later", + "dependencies": { + "detect-europe-js": "^0.1.2", + "is-standalone-pwa": "^0.1.1", + "ua-is-frozen": "^0.1.2" + }, + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", @@ -4019,6 +4371,19 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vite": { "version": "5.4.11", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", @@ -4192,6 +4557,35 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index a8e0339..960e0f7 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,15 @@ }, "dependencies": { "@radix-ui/react-slot": "^1.1.0", + "@types/socket.io-client": "^1.4.36", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.468.0", + "mediasoup-client": "^3.7.18", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-router-dom": "^7.0.2", + "socket.io-client": "^4.8.1", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7" }, diff --git a/src/components/VideoCall/VideoCall.tsx b/src/components/VideoCall/VideoCall.tsx new file mode 100644 index 0000000..02ea3f8 --- /dev/null +++ b/src/components/VideoCall/VideoCall.tsx @@ -0,0 +1,274 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import React, { useState, useEffect, useRef } from "react"; +import { types as mediasoupTypes, Device } from "mediasoup-client"; +import { setupVideoSocket } from "@/config/videoSocket"; +import { RtpCapabilities, TransportParams } from "@/types/video"; + +const VideoCall: React.FC = () => { + const [localStream, setLocalStream] = useState(null); + const [isConnected, setIsConnected] = useState(false); + const localVideoRef = useRef(null); + const remoteVideoRef = useRef(null); + + const videoSocket = setupVideoSocket(); + const deviceRef = useRef(null); + const producerTransportRef = useRef(null); + const consumerTransportRef = useRef(null); + const producerRef = useRef(null); + const consumerRef = useRef(null); + + useEffect(() => { + setupConnection(); + + // Listen for new producers + videoSocket.socket.on("newProducer", () => { + console.log("New producer available"); + consumeMedia(); + }); + + return () => { + // Cleanup + localStream?.getTracks().forEach((track) => track.stop()); + videoSocket.socket.off("newProducer"); + + // Close transports and producers/consumers + producerTransportRef.current?.close(); + consumerTransportRef.current?.close(); + producerRef.current?.close(); + consumerRef.current?.close(); + }; + }, []); + + const setupConnection = async () => { + try { + await getLocalStream(); + await setupMediasoupDevice(); + await createProducerTransport(); + await produceMedia(); + await createConsumerTransport(); + setIsConnected(true); + } catch (error) { + console.error("Connection setup error:", error); + setIsConnected(false); + } + }; + + const getLocalStream = async () => { + try { + const stream = await navigator.mediaDevices.getUserMedia({ + video: true, + audio: true, + }); + setLocalStream(stream); + if (localVideoRef.current) { + localVideoRef.current.srcObject = stream; + } + } catch (error) { + console.error("Error getting local stream:", error); + } + }; + + const setupMediasoupDevice = async () => { + deviceRef.current = new Device(); + return new Promise((resolve, reject) => { + videoSocket.getRouterCapabilities( + (routerRtpCapabilities: RtpCapabilities) => { + try { + if (deviceRef.current) { + deviceRef.current.load({ routerRtpCapabilities }); + resolve(); + } else { + reject(new Error("Device not initialized")); + } + } catch (error) { + console.error("Error loading device:", error); + reject(error); + } + } + ); + }); + }; + + const createProducerTransport = async () => { + return new Promise((resolve, reject) => { + videoSocket.createProducerTransport((params: TransportParams) => { + try { + if (!deviceRef.current) throw new Error("Device not initialized"); + + producerTransportRef.current = + deviceRef.current.createSendTransport(params); + + producerTransportRef.current.on( + "connect", + async ({ dtlsParameters }, callback) => { + try { + await videoSocket.connectProducerTransport( + dtlsParameters, + callback + ); + } catch (error) { + console.error("Producer transport connect error:", error); + } + } + ); + + producerTransportRef.current.on( + "produce", + async ({ kind, rtpParameters }, callback) => { + try { + const result = await videoSocket.produce( + kind, + rtpParameters, + callback + ); + // Notify other clients about new producer + videoSocket.socket.emit("newProducer"); + return result; + } catch (error) { + console.error("Produce error:", error); + } + } + ); + + resolve(); + } catch (error) { + console.error("Create producer transport error:", error); + reject(error); + } + }); + }); + }; + + const produceMedia = async () => { + try { + if (!producerTransportRef.current || !localStream) return; + + const audioTrack = localStream.getAudioTracks()[0]; + const videoTrack = localStream.getVideoTracks()[0]; + + if (audioTrack) { + producerRef.current = await producerTransportRef.current.produce({ + track: audioTrack, + // Removed audioGain as it's not a valid option + }); + } + if (videoTrack) { + producerRef.current = await producerTransportRef.current.produce({ + track: videoTrack, + encodings: [ + { maxBitrate: 1000000 }, + { maxBitrate: 500000 }, + { maxBitrate: 100000 }, + ], + }); + } + } catch (error) { + console.error("Produce media error:", error); + } + }; + + const createConsumerTransport = async () => { + return new Promise((resolve, reject) => { + videoSocket.createConsumerTransport((params: TransportParams) => { + try { + if (!deviceRef.current) throw new Error("Device not initialized"); + + consumerTransportRef.current = + deviceRef.current.createRecvTransport(params); + + consumerTransportRef.current.on( + "connect", + async ({ dtlsParameters }, callback) => { + try { + await videoSocket.connectConsumerTransport( + dtlsParameters, + callback + ); + } catch (error) { + console.error("Consumer transport connect error:", error); + } + } + ); + + resolve(); + } catch (error) { + console.error("Create consumer transport error:", error); + reject(error); + } + }); + }); + }; + + const consumeMedia = async () => { + try { + if (!deviceRef.current || !consumerTransportRef.current) { + throw new Error("Transport or device not initialized"); + } + + const consumerParams = await new Promise((resolve, reject) => { + if (!deviceRef.current) { + throw new Error("Device not initialized"); + } + videoSocket.consume(deviceRef.current.rtpCapabilities, (params) => { + if (params.error) { + reject(new Error(params.error)); + } else { + resolve(params); + } + }); + }); + + // Consume the media track + consumerRef.current = await consumerTransportRef.current.consume({ + id: consumerParams.id, + producerId: consumerParams.producerId, + kind: consumerParams.kind, + rtpParameters: consumerParams.rtpParameters, + appData: consumerParams.appData, + }); + + // Update remote video source + if (remoteVideoRef.current) { + const newRemoteStream = new MediaStream([consumerRef.current.track]); + remoteVideoRef.current.srcObject = newRemoteStream; + } + + // Resume consumer if paused + if (consumerRef.current.paused) { + await consumerRef.current.resume(); + } + } catch (error) { + console.error("Consume media error:", error); + } + }; + + return ( +
+
+

Local Video

+
+
+

Remote Video

+ {isConnected ? ( +
+
+ ); +}; + +export default VideoCall; diff --git a/src/config/videoSocket.ts b/src/config/videoSocket.ts new file mode 100644 index 0000000..90f623a --- /dev/null +++ b/src/config/videoSocket.ts @@ -0,0 +1,70 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// src/config/videoSocket.ts +import io, {Socket } from 'socket.io-client'; +import { types as mediasoupTypes, } from 'mediasoup-client'; +import { RtpCapabilities, TransportParams } from '@/types/video'; + +const SOCKET_URL = 'http://localhost:8080'; + +export const setupVideoSocket = () => { + const socket: typeof Socket = io(SOCKET_URL, { path: '/video' }); + + return { + socket, + getRouterCapabilities: (callback: (caps: RtpCapabilities) => void) => { + socket.emit('getRouterRtpCapabilities', null, callback); + }, + createProducerTransport: (callback: (params: TransportParams) => void) => { + socket.emit('createProducerTransport', null, callback); + }, + createConsumerTransport: (callback: (params: TransportParams) => void) => { + socket.emit('createConsumerTransport', null, callback); + }, + connectProducerTransport: (dtlsParameters: mediasoupTypes.DtlsParameters, callback: () => void) => { + socket.emit('connectProducerTransport', { dtlsParameters }, callback); + }, + connectConsumerTransport: (dtlsParameters: mediasoupTypes.DtlsParameters, callback: () => void) => { + socket.emit('connectConsumerTransport', { dtlsParameters }, callback); + }, + // produce: (kind: mediasoupTypes.MediaKind, rtpParameters: mediasoupTypes.RtpParameters, callback: (id: { id: string }) => void) => { + // socket.emit('produce', { kind, rtpParameters }, callback); + // }, + // consume: (rtpCapabilities: mediasoupTypes.RtpCapabilities, callback: (consumerParams: any) => void) => { + // socket.emit('consume', { rtpCapabilities }, callback); + // }, + resume: (callback: () => void) => { + socket.emit('resume', null, callback); + }, + produce: ( + kind: mediasoupTypes.MediaKind, + rtpParameters: mediasoupTypes.RtpParameters, + callback: (id: { id: string }) => void + ) => { + return new Promise((resolve, reject) => { + socket.emit('produce', { kind, rtpParameters }, (response:any) => { + if (response.error) { + reject(new Error(response.error)); + } else { + resolve(response); + callback(response); + } + }); + }); + }, + consume: ( + rtpCapabilities: mediasoupTypes.RtpCapabilities, + callback: (consumerParams: any) => void + ) => { + return new Promise((resolve, reject) => { + socket.emit('consume', { rtpCapabilities }, (response:any) => { + if (response.error) { + reject(new Error(response.error)); + } else { + resolve(response); + callback(response); + } + }); + }); + }, + }; +}; \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx index bef5202..24f947b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,14 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App.tsx"; +import { BrowserRouter, Route, Routes } from "react-router-dom"; +import VideoCallPage from "./pages/VideoCallPage.tsx"; -createRoot(document.getElementById('root')!).render( - - - , -) +createRoot(document.getElementById("root")!).render( + + + } /> + } /> + + +); diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx new file mode 100644 index 0000000..49b730d --- /dev/null +++ b/src/pages/VideoCallPage.tsx @@ -0,0 +1,275 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +//import React, { useRef } from "react"; +import { useEffect } from "react"; +import io from "socket.io-client"; +//import { types as mediasoupClient } from "mediasoup-client"; + +const VideoCallPage: React.FC = () => { + // const localVideoRef = useRef(null); + // const remoteVideoRef = useRef(null); + + const socket = io("http://localhost:8080"); + console.log("reached here"); + + useEffect(() => { + socket.on("connect", () => { + console.log("Client connected, socket ID: " + socket.id); + }); + + socket.on("connection-success", ({ socketId }: any) => { + console.log("Received socket ID: " + socketId); + }); + + socket.on("connect_error", (err: any) => { + console.error("Connection error details:", err); + console.error("Error stack:", err.stack); + }); + + socket.on("error", (err: any) => { + console.error("Socket error:", err); + }); + + socket.on("hello", (msg: any) => { + console.log(msg); + }); + + return () => { + socket.disconnect(); + }; + }, []); + + console.log("reached here1"); + + // let device: mediasoupClient.Device; + // let rtpCapabilities: any; + // let producerTransport: mediasoupClient.Transport; + // let consumerTransport: mediasoupClient.Transport; + // let producer: mediasoupClient.Producer; + // let consumer: mediasoupClient.Consumer; + + // let params: { + // track?: MediaStreamTrack; + // encodings: { rid: string; maxBitrate: number; scalabilityMode: string }[]; + // codecOptions: { videoGoogleStartBitrate: number }; + // } = { + // encodings: [ + // { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, + // { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, + // { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, + // ], + // codecOptions: { + // videoGoogleStartBitrate: 1000, + // }, + // }; + + // const streamSuccess = async (stream: MediaStream) => { + // if (localVideoRef.current) { + // localVideoRef.current.srcObject = stream; + // } + // const track = stream.getVideoTracks()[0]; + // params = { track, ...params }; + // }; + + // const getLocalStream = () => { + // navigator.mediaDevices + // .getUserMedia({ + // audio: false, + // video: { + // width: { min: 640, max: 1920 }, + // height: { min: 400, max: 1080 }, + // }, + // }) + // .then(streamSuccess) + // .catch((error) => console.log(error.message)); + // }; + + // const createDevice = async () => { + // try { + // device = new mediasoupClient.Device(); + // await device.load({ routerRtpCapabilities: rtpCapabilities }); + // console.log("RTP Capabilities", device.rtpCapabilities); + // } catch (error) { + // console.error(error); + // if ((error as any).name === "UnsupportedError") { + // console.warn("Browser not supported"); + // } + // } + // }; + + // const getRtpCapabilities = () => { + // socket.emit("getRtpCapabilities", (data: any) => { + // console.log(`Router RTP Capabilities... ${data.rtpCapabilities}`); + // rtpCapabilities = data.rtpCapabilities; + // }); + // }; + + // const createSendTransport = () => { + // socket.emit( + // "createWebRtcTransport", + // { sender: true }, + // ({ params }: any) => { + // if (params.error) { + // console.error(params.error); + // return; + // } + + // producerTransport = device.createSendTransport(params); + + // producerTransport.on( + // "connect", + // async ({ dtlsParameters }, callback, errback) => { + // try { + // await socket.emit("transport-connect", { dtlsParameters }); + // callback(); + // } catch (error: any) { + // errback(error); + // } + // } + // ); + + // producerTransport.on( + // "produce", + // async (parameters, callback, errback) => { + // try { + // await socket.emit( + // "transport-produce", + // { + // kind: parameters.kind, + // rtpParameters: parameters.rtpParameters, + // appData: parameters.appData, + // }, + // ({ id }: any) => callback({ id }) + // ); + // } catch (error: any) { + // errback(error); + // } + // } + // ); + // } + // ); + // }; + + // const connectSendTransport = async () => { + // producer = await producerTransport.produce(params); + + // producer.on("trackended", () => { + // console.log("track ended"); + // }); + + // producer.on("transportclose", () => { + // console.log("transport ended"); + // }); + // }; + + // const createRecvTransport = async () => { + // socket.emit( + // "createWebRtcTransport", + // { sender: false }, + // ({ params }: any) => { + // if (params.error) { + // console.error(params.error); + // return; + // } + + // consumerTransport = device.createRecvTransport(params); + + // consumerTransport.on( + // "connect", + // async ({ dtlsParameters }, callback, errback) => { + // try { + // await socket.emit("transport-recv-connect", { dtlsParameters }); + // callback(); + // } catch (error: any) { + // errback(error); + // } + // } + // ); + // } + // ); + // }; + + // const connectRecvTransport = async () => { + // socket.emit( + // "consume", + // { rtpCapabilities: device.rtpCapabilities }, + // async ({ params }: any) => { + // if (params.error) { + // console.error("Cannot Consume"); + // return; + // } + + // consumer = await consumerTransport.consume({ + // id: params.id, + // producerId: params.producerId, + // kind: params.kind, + // rtpParameters: params.rtpParameters, + // }); + + // const { track } = consumer; + // if (remoteVideoRef.current) { + // remoteVideoRef.current.srcObject = new MediaStream([track]); + // } + + // socket.emit("consumer-resume"); + // } + // ); + // }; + + return ( + //
+ //
+ //
+ // + //
+ //
+ // + //
+ //
+ // + // + // + // + // + // + // + //
+
hi
+ ); +}; + +export default VideoCallPage; diff --git a/src/pages/VirtualSpace.tsx b/src/pages/VirtualSpace.tsx index 52042f1..c74a927 100644 --- a/src/pages/VirtualSpace.tsx +++ b/src/pages/VirtualSpace.tsx @@ -6,6 +6,7 @@ import { handleKeyPress } from "@/lib/helperFns/handleKeyPress"; import UserDetails from "@/components/UserDetails/UserDetails"; import GroupChat from "@/components/Chat/GroupChat/GroupChat"; import { Button } from "@/components/ui/button"; +import VideoCall from "@/components/VideoCall/VideoCall"; const VirtualSpace = () => { const [position, setPosition] = useState({ x: 0, y: 0 }); @@ -217,6 +218,7 @@ const VirtualSpace = () => { + )} diff --git a/src/types/video.ts b/src/types/video.ts new file mode 100644 index 0000000..331018f --- /dev/null +++ b/src/types/video.ts @@ -0,0 +1,14 @@ +// src/types/video.ts +import { types as mediasoupTypes } from 'mediasoup-client'; + +export interface RtpCapabilities { + codecs: mediasoupTypes.RtpCodecCapability[]; + headerExtensions: mediasoupTypes.RtpHeaderExtension[]; +} + +export interface TransportParams { + id: string; + iceParameters: mediasoupTypes.IceParameters; + iceCandidates: mediasoupTypes.IceCandidate[]; + dtlsParameters: mediasoupTypes.DtlsParameters; +} \ No newline at end of file From a18403ffb97edfa4664431a92dcc7e21c63dd3ef Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Wed, 18 Dec 2024 20:50:12 +0530 Subject: [PATCH 05/12] broadcast new user --- src/pages/VideoCallPage.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index 49b730d..24da77c 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -32,6 +32,9 @@ const VideoCallPage: React.FC = () => { socket.on("hello", (msg: any) => { console.log(msg); }); + socket.on("new-user", (msg: any) => { + console.log(msg); + }); return () => { socket.disconnect(); From 6c56c40c5bd669ca9781ae476a0bb3aa67ea831c Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Wed, 18 Dec 2024 21:24:24 +0530 Subject: [PATCH 06/12] get local media --- src/pages/VideoCallPage.tsx | 80 ++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index 24da77c..c609a25 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -//import React, { useRef } from "react"; +import { useRef } from "react"; +import { Button } from "@/components/ui/button"; import { useEffect } from "react"; import io from "socket.io-client"; //import { types as mediasoupClient } from "mediasoup-client"; const VideoCallPage: React.FC = () => { - // const localVideoRef = useRef(null); + const localVideoRef = useRef(null); // const remoteVideoRef = useRef(null); const socket = io("http://localhost:8080"); @@ -50,41 +51,41 @@ const VideoCallPage: React.FC = () => { // let producer: mediasoupClient.Producer; // let consumer: mediasoupClient.Consumer; - // let params: { - // track?: MediaStreamTrack; - // encodings: { rid: string; maxBitrate: number; scalabilityMode: string }[]; - // codecOptions: { videoGoogleStartBitrate: number }; - // } = { - // encodings: [ - // { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, - // { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, - // { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, - // ], - // codecOptions: { - // videoGoogleStartBitrate: 1000, - // }, - // }; + let params: { + track?: MediaStreamTrack; + encodings: { rid: string; maxBitrate: number; scalabilityMode: string }[]; + codecOptions: { videoGoogleStartBitrate: number }; + } = { + encodings: [ + { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, + { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, + { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, + ], + codecOptions: { + videoGoogleStartBitrate: 1000, + }, + }; - // const streamSuccess = async (stream: MediaStream) => { - // if (localVideoRef.current) { - // localVideoRef.current.srcObject = stream; - // } - // const track = stream.getVideoTracks()[0]; - // params = { track, ...params }; - // }; + const streamSuccess = async (stream: MediaStream) => { + if (localVideoRef.current) { + localVideoRef.current.srcObject = stream; + } + const track = stream.getVideoTracks()[0]; + params = { track, ...params }; + }; - // const getLocalStream = () => { - // navigator.mediaDevices - // .getUserMedia({ - // audio: false, - // video: { - // width: { min: 640, max: 1920 }, - // height: { min: 400, max: 1080 }, - // }, - // }) - // .then(streamSuccess) - // .catch((error) => console.log(error.message)); - // }; + const getLocalStream = () => { + navigator.mediaDevices + .getUserMedia({ + audio: false, + video: { + width: { min: 640, max: 1920 }, + height: { min: 400, max: 1080 }, + }, + }) + .then(streamSuccess) + .catch((error) => console.log(error.message)); + }; // const createDevice = async () => { // try { @@ -271,7 +272,14 @@ const VideoCallPage: React.FC = () => { // Connect Recv Transport & Consume // // -
hi
+
+ +
+
+ {" "} +
+
+
); }; From e5fd8810a2fa0ebbcce1b73ddeae8163089a9bf2 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Thu, 19 Dec 2024 13:30:35 +0530 Subject: [PATCH 07/12] get rtp capabilities --- src/pages/VideoCallPage.tsx | 54 ++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index c609a25..4a1dc6d 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -1,13 +1,18 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { useRef } from "react"; +import { useRef, useState } from "react"; import { Button } from "@/components/ui/button"; import { useEffect } from "react"; import io from "socket.io-client"; +import * as mediasoupClient from "mediasoup-client"; + //import { types as mediasoupClient } from "mediasoup-client"; const VideoCallPage: React.FC = () => { const localVideoRef = useRef(null); + const [rtpCapabilities, setRtpCapabilities] = + useState(null); // const remoteVideoRef = useRef(null); + const deviceRef = useRef(null); //check this=> do we need usestate/useeffect here ? const socket = io("http://localhost:8080"); console.log("reached here"); @@ -87,25 +92,30 @@ const VideoCallPage: React.FC = () => { .catch((error) => console.log(error.message)); }; - // const createDevice = async () => { - // try { - // device = new mediasoupClient.Device(); - // await device.load({ routerRtpCapabilities: rtpCapabilities }); - // console.log("RTP Capabilities", device.rtpCapabilities); - // } catch (error) { - // console.error(error); - // if ((error as any).name === "UnsupportedError") { - // console.warn("Browser not supported"); - // } - // } - // }; + const createDevice = async () => { + try { + const device = new mediasoupClient.Device(); + deviceRef.current = device; + if (rtpCapabilities) { + await device.load({ routerRtpCapabilities: rtpCapabilities }); + console.log("RTP Capabilities", device.rtpCapabilities); + } else { + console.warn("RTP Capabilities not set"); + } + } catch (error) { + console.error(error); + if ((error as any).name === "UnsupportedError") { + console.warn("Browser not supported"); + } + } + }; - // const getRtpCapabilities = () => { - // socket.emit("getRtpCapabilities", (data: any) => { - // console.log(`Router RTP Capabilities... ${data.rtpCapabilities}`); - // rtpCapabilities = data.rtpCapabilities; - // }); - // }; + const getRtpCapabilities = () => { + socket.emit("getRtpCapabilities", (rtpCapabilities: any) => { + console.log(`Router RTP Capabilities... ${rtpCapabilities}`); + setRtpCapabilities(rtpCapabilities); + }); + }; // const createSendTransport = () => { // socket.emit( @@ -279,6 +289,12 @@ const VideoCallPage: React.FC = () => { {" "} + ); }; From 24db8671dbd2e9572ff82712177a09ccdc3619e0 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Thu, 19 Dec 2024 17:12:53 +0530 Subject: [PATCH 08/12] small bug pending --- src/pages/VideoCallPage.tsx | 382 +++++++++++++++++++----------------- 1 file changed, 204 insertions(+), 178 deletions(-) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index 4a1dc6d..fb0e980 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -5,14 +5,21 @@ import { useEffect } from "react"; import io from "socket.io-client"; import * as mediasoupClient from "mediasoup-client"; -//import { types as mediasoupClient } from "mediasoup-client"; - const VideoCallPage: React.FC = () => { const localVideoRef = useRef(null); const [rtpCapabilities, setRtpCapabilities] = useState(null); - // const remoteVideoRef = useRef(null); - const deviceRef = useRef(null); //check this=> do we need usestate/useeffect here ? + + const deviceRef = useRef(null); + const producerTransportRef = useRef( + null + ); + const consumerTransportRef = useRef( + null + ); + const producerRef = useRef(null); + const consumerRef = useRef(null); + const remoteVideoRef = useRef(null); const socket = io("http://localhost:8080"); console.log("reached here"); @@ -49,13 +56,6 @@ const VideoCallPage: React.FC = () => { console.log("reached here1"); - // let device: mediasoupClient.Device; - // let rtpCapabilities: any; - // let producerTransport: mediasoupClient.Transport; - // let consumerTransport: mediasoupClient.Transport; - // let producer: mediasoupClient.Producer; - // let consumer: mediasoupClient.Consumer; - let params: { track?: MediaStreamTrack; encodings: { rid: string; maxBitrate: number; scalabilityMode: string }[]; @@ -110,184 +110,176 @@ const VideoCallPage: React.FC = () => { } }; - const getRtpCapabilities = () => { - socket.emit("getRtpCapabilities", (rtpCapabilities: any) => { - console.log(`Router RTP Capabilities... ${rtpCapabilities}`); - setRtpCapabilities(rtpCapabilities); + const getRtpCapabilities = async () => { + await socket.emit("getRtpCapabilities", (data: any) => { + console.log(`Router RTP Capabilities... ${data.rtpCapabilities}`); + setRtpCapabilities(data.rtpCapabilities); + }); + }; + + const createSendTransport = async () => { + await socket.emit( + "createWebRtcTransport", + { sender: true }, + ({ params }: any) => { + if (params.error) { + console.log(params.error); + return; + } + + console.log(params); + + if (deviceRef.current) { + producerTransportRef.current = + deviceRef.current.createSendTransport(params); + } else { + console.warn("Device is not initialized."); + return; + } + producerTransportRef.current?.on( + "connect", + async ({ dtlsParameters }: any, callback: any, errback: any) => { + try { + await socket.emit("transport-connect", { + //transportId: producerTransportRef.current?.id, + dtlsParameters: dtlsParameters, + }); + + callback(); + } catch (error) { + errback(error); + } + } + ); + + producerTransportRef.current?.on( + "produce", + async (parameters: any, callback: any, errback: any) => { + console.log(parameters); + try { + await socket.emit( + "transport-produce", + { + //transportId: producerTransportRef.current?.id, + kind: parameters.kind, + rtpParameters: parameters.rtpParameters, + appData: parameters.appData, + }, + ({ id }: any) => { + callback({ id }); + } + ); + + callback(); + } catch (error: any) { + errback(error); + } + } + ); + } + ); + }; + + const connectSendTransport = async () => { + if (producerTransportRef.current) { + producerRef.current = await producerTransportRef.current?.produce(params); + } else { + console.warn("Device is not initialized.(send transport error)"); + return; + } + + producerRef.current?.on("trackended", () => { + console.log("track ended"); + }); + producerRef.current?.on("transportclose", () => { + console.log("transport ended"); }); }; - // const createSendTransport = () => { - // socket.emit( - // "createWebRtcTransport", - // { sender: true }, - // ({ params }: any) => { - // if (params.error) { - // console.error(params.error); - // return; - // } - - // producerTransport = device.createSendTransport(params); - - // producerTransport.on( - // "connect", - // async ({ dtlsParameters }, callback, errback) => { - // try { - // await socket.emit("transport-connect", { dtlsParameters }); - // callback(); - // } catch (error: any) { - // errback(error); - // } - // } - // ); - - // producerTransport.on( - // "produce", - // async (parameters, callback, errback) => { - // try { - // await socket.emit( - // "transport-produce", - // { - // kind: parameters.kind, - // rtpParameters: parameters.rtpParameters, - // appData: parameters.appData, - // }, - // ({ id }: any) => callback({ id }) - // ); - // } catch (error: any) { - // errback(error); - // } - // } - // ); - // } - // ); - // }; - - // const connectSendTransport = async () => { - // producer = await producerTransport.produce(params); - - // producer.on("trackended", () => { - // console.log("track ended"); - // }); - - // producer.on("transportclose", () => { - // console.log("transport ended"); - // }); - // }; - - // const createRecvTransport = async () => { - // socket.emit( - // "createWebRtcTransport", - // { sender: false }, - // ({ params }: any) => { - // if (params.error) { - // console.error(params.error); - // return; - // } - - // consumerTransport = device.createRecvTransport(params); - - // consumerTransport.on( - // "connect", - // async ({ dtlsParameters }, callback, errback) => { - // try { - // await socket.emit("transport-recv-connect", { dtlsParameters }); - // callback(); - // } catch (error: any) { - // errback(error); - // } - // } - // ); - // } - // ); - // }; - - // const connectRecvTransport = async () => { - // socket.emit( - // "consume", - // { rtpCapabilities: device.rtpCapabilities }, - // async ({ params }: any) => { - // if (params.error) { - // console.error("Cannot Consume"); - // return; - // } - - // consumer = await consumerTransport.consume({ - // id: params.id, - // producerId: params.producerId, - // kind: params.kind, - // rtpParameters: params.rtpParameters, - // }); - - // const { track } = consumer; - // if (remoteVideoRef.current) { - // remoteVideoRef.current.srcObject = new MediaStream([track]); - // } - - // socket.emit("consumer-resume"); - // } - // ); - // }; + const createRecvTransport = async () => { + await socket.emit( + "createWebRtcTransport", + { sender: false }, + ({ params }: any) => { + if (params.error) { + console.log(params.error); + return; + } + console.log(params); + + if (deviceRef.current) { + consumerTransportRef.current = + deviceRef.current?.createRecvTransport(params); + } else { + console.warn( + "Device is not initialized.(createWebRtcTransport error)" + ); + return; + } + + consumerTransportRef.current?.on( + "connect", + async ({ dtlsParameters }: any, callback: any, errback: any) => { + try { + await socket.emit("transport-recv-connect", { + //transportId: consumerTransportRef.current?.id, + dtlsParameters: dtlsParameters, + }); + + callback(); + } catch (error) { + errback(error); + } + } + ); + } + ); + }; + + const connectRecvTransport = async () => { + socket.emit( + "consume", + { + rtpCapabilities: deviceRef.current?.rtpCapabilities, + }, + async ({ params }: any) => { + if (params.error) { + console.error("Cannot Consume"); + return; + } + console.log(params); + + if (consumerTransportRef.current) { + consumerRef.current = await consumerTransportRef.current?.consume({ + id: params.id, + producerId: params.producerId, + kind: params.kind, + rtpParameters: params.rtpParameters, + }); + + const { track } = consumerRef.current; + if (remoteVideoRef.current) { + remoteVideoRef.current.srcObject = new MediaStream([track]); + } + socket.emit("consumer-resume"); + } else { + console.warn("Device is not initialized.(consume error)"); + return; + } + } + ); + }; return ( - //
- //
- //
- // - //
- //
- // - //
- //
- // - // - // - // - // - // - // - //
{" "}
+
+ {" "} +
+ + + + + + + + +
); }; From c68ea0cef0433df994fd5b56c6a07150dd06a3a2 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Fri, 20 Dec 2024 15:37:05 +0530 Subject: [PATCH 09/12] send and receive is working on the same browser --- src/pages/VideoCallPage.tsx | 100 +++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 36 deletions(-) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index fb0e980..00cda31 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -19,6 +19,16 @@ const VideoCallPage: React.FC = () => { ); const producerRef = useRef(null); const consumerRef = useRef(null); + const [params, setParams] = useState({ + encodings: [ + { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, + { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, + { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, + ], + codecOptions: { + videoGoogleStartBitrate: 1000, + }, + }); const remoteVideoRef = useRef(null); const socket = io("http://localhost:8080"); @@ -56,27 +66,30 @@ const VideoCallPage: React.FC = () => { console.log("reached here1"); - let params: { - track?: MediaStreamTrack; - encodings: { rid: string; maxBitrate: number; scalabilityMode: string }[]; - codecOptions: { videoGoogleStartBitrate: number }; - } = { - encodings: [ - { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, - { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, - { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, - ], - codecOptions: { - videoGoogleStartBitrate: 1000, - }, - }; + // let params: any = { + // encodings: [ + // { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, + // { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, + // { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, + // ], + // codecOptions: { + // videoGoogleStartBitrate: 1000, + // }, + // }; const streamSuccess = async (stream: MediaStream) => { if (localVideoRef.current) { localVideoRef.current.srcObject = stream; } const track = stream.getVideoTracks()[0]; - params = { track, ...params }; + // params = { + // track, + // ...params, + // }; + setParams((prev) => ({ + ...prev, // Preserve existing properties + track, // Add or overwrite the `track` property + })); }; const getLocalStream = () => { @@ -136,6 +149,8 @@ const VideoCallPage: React.FC = () => { console.warn("Device is not initialized."); return; } + + console.log("reached here 1"); producerTransportRef.current?.on( "connect", async ({ dtlsParameters }: any, callback: any, errback: any) => { @@ -151,49 +166,62 @@ const VideoCallPage: React.FC = () => { } } ); + console.log("reached here 2"); producerTransportRef.current?.on( "produce", async (parameters: any, callback: any, errback: any) => { - console.log(parameters); + console.log("Produce parameters received:", parameters); try { - await socket.emit( + socket.emit( "transport-produce", { - //transportId: producerTransportRef.current?.id, kind: parameters.kind, rtpParameters: parameters.rtpParameters, appData: parameters.appData, }, - ({ id }: any) => { - callback({ id }); + (response: any) => { + if (response.error) { + throw new Error(response.error); + } + callback({ id: response.id }); } ); - - callback(); - } catch (error: any) { + } catch (error) { + console.error("Error in transport-produce:", error); errback(error); } } ); + console.log("reached here 3"); } ); }; const connectSendTransport = async () => { - if (producerTransportRef.current) { - producerRef.current = await producerTransportRef.current?.produce(params); - } else { - console.warn("Device is not initialized.(send transport error)"); - return; - } + try { + if (producerTransportRef.current) { + try { + producerRef.current = await producerTransportRef.current?.produce( + params + ); + } catch (error: any) { + console.log("error here:", error); + } + } else { + console.warn("Device is not initialized.(send transport error)"); + return; + } - producerRef.current?.on("trackended", () => { - console.log("track ended"); - }); - producerRef.current?.on("transportclose", () => { - console.log("transport ended"); - }); + producerRef.current?.on("trackended", () => { + console.log("track ended"); + }); + producerRef.current?.on("transportclose", () => { + console.log("transport ended"); + }); + } catch (error: any) { + console.dir("error from connectSendTransport: ", error); + } }; const createRecvTransport = async () => { @@ -237,7 +265,7 @@ const VideoCallPage: React.FC = () => { }; const connectRecvTransport = async () => { - socket.emit( + await socket.emit( "consume", { rtpCapabilities: deviceRef.current?.rtpCapabilities, From 4a76f2d93ada30952fd2d3c516c381a4a0be214e Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Fri, 20 Dec 2024 15:49:58 +0530 Subject: [PATCH 10/12] removing comments --- src/pages/VideoCallPage.tsx | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index 00cda31..0e37f83 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -66,29 +66,15 @@ const VideoCallPage: React.FC = () => { console.log("reached here1"); - // let params: any = { - // encodings: [ - // { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, - // { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, - // { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, - // ], - // codecOptions: { - // videoGoogleStartBitrate: 1000, - // }, - // }; - const streamSuccess = async (stream: MediaStream) => { if (localVideoRef.current) { localVideoRef.current.srcObject = stream; } const track = stream.getVideoTracks()[0]; - // params = { - // track, - // ...params, - // }; + setParams((prev) => ({ - ...prev, // Preserve existing properties - track, // Add or overwrite the `track` property + ...prev, + track, })); }; From 6605e4c66391ee658beaa652e0ed6c063aa46cf5 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Fri, 20 Dec 2024 20:12:50 +0530 Subject: [PATCH 11/12] bug solving attempts --- src/pages/VideoCallPage.tsx | 46 +++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index 0e37f83..0dca4bd 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -31,7 +31,7 @@ const VideoCallPage: React.FC = () => { }); const remoteVideoRef = useRef(null); - const socket = io("http://localhost:8080"); + const socket = io("https://localhost:8080"); console.log("reached here"); useEffect(() => { @@ -219,7 +219,7 @@ const VideoCallPage: React.FC = () => { console.log(params.error); return; } - console.log(params); + console.log("Received transport params:", params); if (deviceRef.current) { consumerTransportRef.current = @@ -230,22 +230,34 @@ const VideoCallPage: React.FC = () => { ); return; } - - consumerTransportRef.current?.on( - "connect", - async ({ dtlsParameters }: any, callback: any, errback: any) => { - try { - await socket.emit("transport-recv-connect", { - //transportId: consumerTransportRef.current?.id, - dtlsParameters: dtlsParameters, - }); - - callback(); - } catch (error) { - errback(error); + console.log("i did reach here"); + //some error here=>this part is not being triggered,nor does it give any error + try { + consumerTransportRef.current?.on( + "connect", + async ({ dtlsParameters }: any, callback: any, errback: any) => { + console.log( + "Connect event triggered with dtlsParameters:", + dtlsParameters + ); + try { + // + await socket.emit("transport-recv-connect", { + //transportId: consumerTransportRef.current?.id, + dtlsParameters: dtlsParameters, + }); + + callback(); + } catch (error) { + errback(error); + } } - } - ); + ); + } catch (error: any) { + console.log("error in emitting transport-recv-connect :", error); + } + + console.log("but did i reach here?"); } ); }; From 9299eb0ac54b7b26158496b3f4f783befca487f5 Mon Sep 17 00:00:00 2001 From: Yash Hegde Date: Sun, 22 Dec 2024 11:12:35 +0530 Subject: [PATCH 12/12] attempt to create 1-1 communication --- src/pages/VideoCallPage.tsx | 50 ++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/pages/VideoCallPage.tsx b/src/pages/VideoCallPage.tsx index 0dca4bd..2007d4f 100644 --- a/src/pages/VideoCallPage.tsx +++ b/src/pages/VideoCallPage.tsx @@ -19,6 +19,7 @@ const VideoCallPage: React.FC = () => { ); const producerRef = useRef(null); const consumerRef = useRef(null); + const [isProducer, setIsProducer] = useState(false); const [params, setParams] = useState({ encodings: [ { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, @@ -39,8 +40,9 @@ const VideoCallPage: React.FC = () => { console.log("Client connected, socket ID: " + socket.id); }); - socket.on("connection-success", ({ socketId }: any) => { + socket.on("connection-success", ({ socketId, existsProducer }: any) => { console.log("Received socket ID: " + socketId); + console.log("Does a producer exist " + existsProducer); }); socket.on("connect_error", (err: any) => { @@ -66,7 +68,7 @@ const VideoCallPage: React.FC = () => { console.log("reached here1"); - const streamSuccess = async (stream: MediaStream) => { + const streamSuccess = (stream: MediaStream) => { if (localVideoRef.current) { localVideoRef.current.srcObject = stream; } @@ -76,6 +78,8 @@ const VideoCallPage: React.FC = () => { ...prev, track, })); + + goConnect(true); }; const getLocalStream = () => { @@ -91,16 +95,38 @@ const VideoCallPage: React.FC = () => { .catch((error) => console.log(error.message)); }; + const goConsume = () => { + goConnect(false); + }; + + const goConnect = (producerOrConsumer: any) => { + setIsProducer(producerOrConsumer); + console.log("device value is ", deviceRef.current); + + if (deviceRef.current === undefined) { + getRtpCapabilities(); + } else { + goCreateTransport(); + } + }; + + const goCreateTransport = () => { + if (isProducer) { + createSendTransport(); + } else { + createRecvTransport(); + } + }; const createDevice = async () => { try { const device = new mediasoupClient.Device(); - deviceRef.current = device; - if (rtpCapabilities) { - await device.load({ routerRtpCapabilities: rtpCapabilities }); - console.log("RTP Capabilities", device.rtpCapabilities); - } else { - console.warn("RTP Capabilities not set"); + if (!rtpCapabilities) { + throw new Error("RTP Capabilities are null or undefined."); } + await device.load({ routerRtpCapabilities: rtpCapabilities }); + deviceRef.current = device; + console.log("Device initialized successfully"); + goCreateTransport(); } catch (error) { console.error(error); if ((error as any).name === "UnsupportedError") { @@ -110,9 +136,10 @@ const VideoCallPage: React.FC = () => { }; const getRtpCapabilities = async () => { - await socket.emit("getRtpCapabilities", (data: any) => { + await socket.emit("createRoom", (data: any) => { console.log(`Router RTP Capabilities... ${data.rtpCapabilities}`); setRtpCapabilities(data.rtpCapabilities); + createDevice(); }); }; @@ -180,6 +207,7 @@ const VideoCallPage: React.FC = () => { } ); console.log("reached here 3"); + connectSendTransport(); } ); }; @@ -258,6 +286,7 @@ const VideoCallPage: React.FC = () => { } console.log("but did i reach here?"); + connectRecvTransport(); } ); }; @@ -347,6 +376,9 @@ const VideoCallPage: React.FC = () => { > Connect Recv Transport & Consume + + + ); };