{"id":22445757,"url":"https://github.com/1boch1/skip-or-meet","last_synced_at":"2026-04-19T05:37:00.098Z","repository":{"id":189603383,"uuid":"419494115","full_name":"1boch1/skip-or-meet","owner":"1boch1","description":"P2P video chat application","archived":false,"fork":false,"pushed_at":"2024-04-01T21:52:15.000Z","size":12584,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-01T15:35:00.931Z","etag":null,"topics":["nodejs","p2p","websocket"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/1boch1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-20T21:25:37.000Z","updated_at":"2024-07-24T11:55:32.000Z","dependencies_parsed_at":"2025-02-01T15:40:29.416Z","dependency_job_id":null,"html_url":"https://github.com/1boch1/skip-or-meet","commit_stats":null,"previous_names":["1boch1/skip-or-meet"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1boch1%2Fskip-or-meet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1boch1%2Fskip-or-meet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1boch1%2Fskip-or-meet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1boch1%2Fskip-or-meet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/1boch1","download_url":"https://codeload.github.com/1boch1/skip-or-meet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245832680,"owners_count":20679701,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nodejs","p2p","websocket"],"created_at":"2024-12-06T03:16:45.445Z","updated_at":"2026-04-19T05:37:00.046Z","avatar_url":"https://github.com/1boch1.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skip Or Meet\r\nP2P Video Chat Application\r\n\r\n## Libraries\r\n\r\n- [React.js](https://it.reactjs.org/)\r\n- [PeerJS ](https://peerjs.com/)\r\n- [Express](https://expressjs.com/)\r\n- [Socket.io](https://socket.io/)\r\n\r\n\r\n## Preview\r\n\r\n![skipormeet](https://user-images.githubusercontent.com/69087218/133236799-94f388da-7197-4a13-ac31-db5c5992ae66.png)\r\n\r\n![skipormeet-mobile](https://user-images.githubusercontent.com/69087218/133236818-c0bb9c37-9148-49e0-a693-ac350116dbb5.png)\r\n\r\n## Project setup\r\n\r\n- #### Install the dependencies running this command in ./ and ./client\r\n\r\n  ### `npm install`\r\n\r\n- #### Start the Express server running this command in ./ (using nodemon)\r\n\r\n  ### `nodemon server.js`\r\n\r\n  \u003e Open [http://localhost:5000](http://localhost:5000) to view it in the browser.\r\n\r\n- #### Start the PeerJs server running this command in ./\r\n\r\n  ### `peerjs --port 3001`\r\n\r\n- #### Start the React app running this command in ./client\r\n\r\n  ### `npm start`\r\n\r\n  \u003e Open [http://localhost:3000](http://localhost:3000) to view it in the browser.\r\n\r\n\r\n\r\n## Explanation\r\n\r\n- The client opens the website and connects to the Express server\r\n\r\n  ```javascript\r\n  const socket = io(\"https://localhost:5000\");\r\n  ```\r\n\r\n- The browser asks for audio and video permissions\r\n\r\n  ```javascript\r\n  navigator.mediaDevices\r\n        .getUserMedia({ video: true, audio: true })\r\n        .then((currentStream) =\u003e {\r\n  ```\r\n\r\n- The client creates a PeerJS instance, a signaling server assign a peerID to it triggering .on(\"open\") that emits a \"wantToJoin\" message to the Express server\r\n\r\n    ```javascript\r\n    myPeer = new Peer(undefined, {\r\n          host: \"localhost\",\r\n          port: 3001,\r\n          path: \"/\",\r\n        });\r\n\r\n        myPeer.on(\"open\", (peerID) =\u003e {\r\n          socket.emit(\"wantToJoin\", peerID);\r\n        });\r\n    ```\r\n    \r\n- The Express server receives the \"wantToJoin\" message and decides\r\n  - If there are no available socket.io rooms it creates one, adds the client, puts the room in a queue of available rooms and waits\r\n  - If there is an available room, so if there is a user alone in a room waiting to connect with another user, the server joins the client to that room, makes the room unavailable and then sends to the user already in the room a \"new member\" message with the peer id of the new member\r\n\r\n    ```javascript\r\n    socket.on(\"wantToJoin\", (peerID) =\u003e {\r\n    //If there is a room with a place left\r\n\r\n    if (available_rooms.length \u003e 0) {\r\n      //Get a room from the queue, removing it\r\n      //from the list\r\n\r\n      let available_room = available_rooms.shift();\r\n\r\n      //Join the room and send to the host a \"new_member\"\r\n\r\n      socket.to(available_room).emit(\"new_member\", peerID);\r\n      socket.join(available_room, () =\u003e {});\r\n\r\n      room = available_room;\r\n    }\r\n\r\n    //If the server must create a new room\r\n    else {\r\n      //Creates a new room and set the user\r\n      //as host\r\n\r\n      let new_room = uuidv4();\r\n\r\n      available_rooms.push(new_room);\r\n\r\n      socket.join(new_room, () =\u003e {});\r\n\r\n      room = new_room;\r\n    }\r\n    ```    \r\n    \r\n    \r\n- The other client receives the \"new_member\" message with the new user peer id and starts a P2P call\r\n\r\n  ```javascript\r\n         socket.on(\"new_member\", (strangerPeerID) =\u003e {\r\n          const call = myPeer.call(strangerPeerID, currentStream);\r\n\r\n          call.on(\"stream\", (userVideoStream) =\u003e {\r\n            setUserVideoReady(() =\u003e true);\r\n            userVideo.current.srcObject = userVideoStream;\r\n          });\r\n\r\n          //If the call closes\r\n\r\n          call.on(\"close\", () =\u003e {\r\n            setUserVideoReady(() =\u003e false);\r\n\r\n            setUserVideoReady(() =\u003e false);\r\n            window.location.reload();\r\n          });\r\n\r\n          peers[strangerPeerID] = call;\r\n        });\r\n  ```\r\n\r\n- When the first client receives the call, the video WebRTC stream starts\r\n\r\n  ```javascript\r\n         myPeer.on(\"call\", (call) =\u003e {\r\n          call.answer(currentStream);\r\n\r\n          call.on(\"stream\", (userVideoStream) =\u003e {\r\n            setUserVideoReady(() =\u003e true);\r\n            userVideo.current.srcObject = userVideoStream;\r\n          });\r\n        });\r\n  ```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1boch1%2Fskip-or-meet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F1boch1%2Fskip-or-meet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1boch1%2Fskip-or-meet/lists"}