diff --git a/frontend/Dockerfile b/frontend/Dockerfile
index 8882549..0a5f3ab 100644
--- a/frontend/Dockerfile
+++ b/frontend/Dockerfile
@@ -7,7 +7,7 @@ ENV VITE_STRIPE_PUBLISHABLE_KEY=${VITE_STRIPE_PUBLISHABLE_KEY}
COPY package*.json ./
-RUN npm install
+RUN npm install --legacy-peer-deps
COPY . .
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 03c1668..1e356ee 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -10,9 +10,12 @@
"dependencies": {
"@stripe/react-stripe-js": "^3.1.1",
"@stripe/stripe-js": "^5.5.0",
+ "@types/video.js": "^7.3.58",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-router-dom": "^7.1.3"
+ "react-router-dom": "^7.1.3",
+ "socket.io-client": "^4.8.1",
+ "video.js": "^8.21.0"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
@@ -283,6 +286,18 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/runtime": {
+ "version": "7.26.7",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz",
+ "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/template": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
@@ -1359,6 +1374,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/@stripe/react-stripe-js": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.1.1.tgz",
@@ -1475,6 +1496,12 @@
"@types/react": "^18.0.0"
}
},
+ "node_modules/@types/video.js": {
+ "version": "7.3.58",
+ "resolved": "https://registry.npmjs.org/@types/video.js/-/video.js-7.3.58.tgz",
+ "integrity": "sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ==",
+ "license": "MIT"
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz",
@@ -1694,6 +1721,54 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@videojs/http-streaming": {
+ "version": "3.16.2",
+ "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.16.2.tgz",
+ "integrity": "sha512-fvt4ko7FknxiT9FnjyNQt6q2px+awrkM+Orv7IB/4gldvj94u4fowGfmNHynnvNTPgPkdxHklGmFLGfclYw8HA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "^4.1.1",
+ "aes-decrypter": "^4.0.2",
+ "global": "^4.4.0",
+ "m3u8-parser": "^7.2.0",
+ "mpd-parser": "^1.3.1",
+ "mux.js": "7.1.0",
+ "video.js": "^7 || ^8"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ },
+ "peerDependencies": {
+ "video.js": "^8.19.0"
+ }
+ },
+ "node_modules/@videojs/vhs-utils": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz",
+ "integrity": "sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "global": "^4.4.0"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ }
+ },
+ "node_modules/@videojs/xhr": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.7.0.tgz",
+ "integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "global": "~4.4.0",
+ "is-function": "^1.0.1"
+ }
+ },
"node_modules/@vitejs/plugin-react": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz",
@@ -1714,6 +1789,15 @@
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
}
},
+ "node_modules/@xmldom/xmldom": {
+ "version": "0.8.10",
+ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
+ "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/acorn": {
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
@@ -1737,6 +1821,18 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
+ "node_modules/aes-decrypter": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.2.tgz",
+ "integrity": "sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "^4.1.1",
+ "global": "^4.4.0",
+ "pkcs7": "^1.0.4"
+ }
+ },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -2156,6 +2252,11 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/dom-walk": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
+ "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
+ },
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -2177,6 +2278,45 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/engine.io-client": {
+ "version": "6.6.3",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
+ "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
+ "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-client/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "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.24.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
@@ -2669,6 +2809,16 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/global": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
+ "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
+ "license": "MIT",
+ "dependencies": {
+ "min-document": "^2.19.0",
+ "process": "^0.11.10"
+ }
+ },
"node_modules/globals": {
"version": "15.14.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
@@ -2798,6 +2948,12 @@
"node": ">=8"
}
},
+ "node_modules/is-function": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
+ "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==",
+ "license": "MIT"
+ },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -3019,6 +3175,17 @@
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
+ "node_modules/m3u8-parser": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-7.2.0.tgz",
+ "integrity": "sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "^4.1.1",
+ "global": "^4.4.0"
+ }
+ },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -3043,6 +3210,14 @@
"node": ">=8.6"
}
},
+ "node_modules/min-document": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
+ "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
+ "dependencies": {
+ "dom-walk": "^0.1.0"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3066,13 +3241,44 @@
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/mpd-parser": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.1.tgz",
+ "integrity": "sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "^4.0.0",
+ "@xmldom/xmldom": "^0.8.3",
+ "global": "^4.4.0"
+ },
+ "bin": {
+ "mpd-to-m3u8-json": "bin/parse.js"
+ }
+ },
"node_modules/ms": {
"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/mux.js": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-7.1.0.tgz",
+ "integrity": "sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime": "^7.11.2",
+ "global": "^4.4.0"
+ },
+ "bin": {
+ "muxjs-transmux": "bin/transmux.js"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ }
+ },
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@@ -3318,6 +3524,18 @@
"node": ">= 6"
}
},
+ "node_modules/pkcs7": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
+ "integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5"
+ },
+ "bin": {
+ "pkcs7": "bin/cli.js"
+ }
+ },
"node_modules/postcss": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
@@ -3478,6 +3696,15 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -3624,6 +3851,12 @@
"node": ">=8.10.0"
}
},
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
+ "license": "MIT"
+ },
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@@ -3790,6 +4023,68 @@
"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-client/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "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/socket.io-parser/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -4164,6 +4459,57 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/video.js": {
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/video.js/-/video.js-8.21.0.tgz",
+ "integrity": "sha512-zcwerRb257QAuWfi8NH9yEX7vrGKFthjfcONmOQ4lxFRpDAbAi+u5LAjCjMWqhJda6zEmxkgdDpOMW3Y21QpXA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/http-streaming": "^3.16.2",
+ "@videojs/vhs-utils": "^4.1.1",
+ "@videojs/xhr": "2.7.0",
+ "aes-decrypter": "^4.0.2",
+ "global": "4.4.0",
+ "m3u8-parser": "^7.2.0",
+ "mpd-parser": "^1.3.1",
+ "mux.js": "^7.0.1",
+ "videojs-contrib-quality-levels": "4.1.0",
+ "videojs-font": "4.2.0",
+ "videojs-vtt.js": "0.15.5"
+ }
+ },
+ "node_modules/videojs-contrib-quality-levels": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz",
+ "integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "global": "^4.4.0"
+ },
+ "engines": {
+ "node": ">=16",
+ "npm": ">=8"
+ },
+ "peerDependencies": {
+ "video.js": "^8"
+ }
+ },
+ "node_modules/videojs-font": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.2.0.tgz",
+ "integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/videojs-vtt.js": {
+ "version": "0.15.5",
+ "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz",
+ "integrity": "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "global": "^4.3.1"
+ }
+ },
"node_modules/vite": {
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.9.tgz",
@@ -4357,6 +4703,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/frontend/package.json b/frontend/package.json
index 41b8b2e..cea08d6 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -13,9 +13,12 @@
"dependencies": {
"@stripe/react-stripe-js": "^3.1.1",
"@stripe/stripe-js": "^5.5.0",
+ "@types/video.js": "^7.3.58",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-router-dom": "^7.1.3"
+ "react-router-dom": "^7.1.3",
+ "socket.io-client": "^4.8.1",
+ "video.js": "^8.21.0"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
diff --git a/frontend/public/images/sample_game_video.mp4 b/frontend/public/images/sample_game_video.mp4
new file mode 100644
index 0000000..6cee752
Binary files /dev/null and b/frontend/public/images/sample_game_video.mp4 differ
diff --git a/frontend/src/components/Stream/StreamerRoute.tsx b/frontend/src/components/Stream/StreamerRoute.tsx
index 09e4d3a..897e447 100644
--- a/frontend/src/components/Stream/StreamerRoute.tsx
+++ b/frontend/src/components/Stream/StreamerRoute.tsx
@@ -32,7 +32,7 @@ const StreamerRoute: React.FC = () => {
}, [streamerName]);
if (isLoading) {
- return
Loading...
; // Or your loading component
+ return Loading...
; // Or your loading component
}
return isLive ? : ;
diff --git a/frontend/src/components/Video/ChatPanel.tsx b/frontend/src/components/Video/ChatPanel.tsx
index a710cd3..5e7fc85 100644
--- a/frontend/src/components/Video/ChatPanel.tsx
+++ b/frontend/src/components/Video/ChatPanel.tsx
@@ -1,4 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
+import { io, Socket } from "socket.io-client";
import Input from "../Layout/Input";
interface ChatMessage {
@@ -15,9 +16,38 @@ interface ChatPanelProps {
const ChatPanel: React.FC = ({ streamId, chatterId }) => {
const [messages, setMessages] = useState([]);
const [inputMessage, setInputMessage] = useState("");
- const lastReceivedRef = useRef("");
+ const [socket, setSocket] = useState(null);
const chatContainerRef = useRef(null);
+ // Initialize socket connection
+ useEffect(() => {
+ const newSocket = io("/", {
+ path: "/api/socket.io",
+ withCredentials: true
+ }); // Make sure this matches your backend URL
+ setSocket(newSocket);
+
+ newSocket.on("connect", () => {
+ console.log("Socket Connection established!");
+ // Join the stream's chat room
+ newSocket.emit("join", { stream_id: streamId });
+ });
+
+ newSocket.on("new_message", (data: ChatMessage) => {
+ setMessages(prev => [...prev, data]);
+ });
+
+ newSocket.on("error", (error) => {
+ console.error("Socket error:", error);
+ });
+
+ // Cleanup on unmount
+ return () => {
+ newSocket.emit("leave", { stream_id: streamId });
+ newSocket.close();
+ };
+ }, [streamId]);
+
// Load initial chat history
useEffect(() => {
const loadPastChat = async () => {
@@ -27,10 +57,6 @@ const ChatPanel: React.FC = ({ streamId, chatterId }) => {
const data = await response.json();
if (data.chat_history) {
setMessages(data.chat_history);
- if (data.chat_history.length > 0) {
- lastReceivedRef.current =
- data.chat_history[data.chat_history.length - 1].time_sent;
- }
}
} catch (error) {
console.error("Error loading chat history:", error);
@@ -42,61 +68,21 @@ const ChatPanel: React.FC = ({ streamId, chatterId }) => {
// Auto-scroll to bottom when new messages arrive
useEffect(() => {
- if (chatContainerRef.current)
- chatContainerRef.current.scrollTop =
- chatContainerRef.current.scrollHeight;
+ if (chatContainerRef.current) {
+ chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;
+ }
}, [messages]);
- // Poll for new messages
- useEffect(() => {
- const getRecentChats = async () => {
- if (!lastReceivedRef.current) return;
+ const sendChat = () => {
+ if (!inputMessage.trim() || !chatterId || !socket) return;
- try {
- const response = await fetch(
- `/api/load_new_chat/${streamId}?last_received=${lastReceivedRef.current}`
- );
- if (!response.ok) throw new Error("Failed to fetch recent chats");
- const newMessages = await response.json();
- if (newMessages && newMessages.length > 0) {
- setMessages((prev) => [...prev, ...newMessages]);
- lastReceivedRef.current =
- newMessages[newMessages.length - 1].time_sent;
- }
- } catch (error) {
- console.error("Error fetching recent chats:", error);
- }
- };
+ socket.emit("send_message", {
+ chatter_id: chatterId,
+ stream_id: streamId,
+ message: inputMessage.trim()
+ });
- const pollInterval = setInterval(getRecentChats, 3000); // Poll every 3 seconds
- return () => clearInterval(pollInterval);
- }, [streamId]);
-
- const sendChat = async () => {
- if (!inputMessage.trim() || !chatterId) return;
-
- try {
- const response = await fetch("/api/send_chat", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- chatter_id: chatterId,
- stream_id: streamId,
- message: inputMessage,
- }),
- });
-
- if (response.ok) {
- const data = await response.json();
- if (data.chat_sent) {
- setInputMessage("");
- }
- }
- } catch (error) {
- console.error("Error sending chat:", error);
- }
+ setInputMessage("");
};
const handleKeyPress = (e: React.KeyboardEvent) => {
@@ -105,9 +91,9 @@ const ChatPanel: React.FC = ({ streamId, chatterId }) => {
sendChat();
}
};
-
+
return (
-
+
Stream Chat
= ({ streamId, chatterId }) => {
);
};
-export default ChatPanel;
+export default ChatPanel;
\ No newline at end of file
diff --git a/frontend/src/components/Video/VideoPlayer.tsx b/frontend/src/components/Video/VideoPlayer.tsx
index 22d1261..bd34642 100644
--- a/frontend/src/components/Video/VideoPlayer.tsx
+++ b/frontend/src/components/Video/VideoPlayer.tsx
@@ -27,11 +27,14 @@ const VideoPlayer: React.FC = ({ streamId }) => {
controls: true,
fluid: true,
responsive: true,
+ // autoplay: true,
+ loop: true,
aspectRatio: "16:9",
sources: [
{
- src: `/api/hls1/${streamId}`,
- type: "application/x-mpegURL",
+ src: `/images/sample_game_video.mp4`,
+ // type: "application/x-mpegURL",
+ type: 'video/mp4'
},
],
});
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
index 6aa68b7..a1d0c1d 100644
--- a/nginx/nginx.conf
+++ b/nginx/nginx.conf
@@ -46,5 +46,9 @@ http {
location / {
proxy_pass http://frontend:5173; # frontend is the name of the React container in docker-compose
}
+
+ location /socket.io/ {
+ proxy_pass http://web_server:5000/socket.io/;
+ }
}
}
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 1f14298..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,410 +0,0 @@
-{
- "name": "Team-Software-Project",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "dependencies": {
- "@types/video.js": "^7.3.58",
- "axios": "^1.7.9",
- "react": "^19.0.0",
- "react-dom": "^19.0.0",
- "video.js": "^8.21.0"
- },
- "devDependencies": {
- "@types/react": "^19.0.8",
- "@types/react-dom": "^19.0.3"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.26.7",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz",
- "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==",
- "license": "MIT",
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@types/react": {
- "version": "19.0.8",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.8.tgz",
- "integrity": "sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "csstype": "^3.0.2"
- }
- },
- "node_modules/@types/react-dom": {
- "version": "19.0.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.3.tgz",
- "integrity": "sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^19.0.0"
- }
- },
- "node_modules/@types/video.js": {
- "version": "7.3.58",
- "resolved": "https://registry.npmjs.org/@types/video.js/-/video.js-7.3.58.tgz",
- "integrity": "sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ==",
- "license": "MIT"
- },
- "node_modules/@videojs/http-streaming": {
- "version": "3.16.2",
- "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.16.2.tgz",
- "integrity": "sha512-fvt4ko7FknxiT9FnjyNQt6q2px+awrkM+Orv7IB/4gldvj94u4fowGfmNHynnvNTPgPkdxHklGmFLGfclYw8HA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "@videojs/vhs-utils": "^4.1.1",
- "aes-decrypter": "^4.0.2",
- "global": "^4.4.0",
- "m3u8-parser": "^7.2.0",
- "mpd-parser": "^1.3.1",
- "mux.js": "7.1.0",
- "video.js": "^7 || ^8"
- },
- "engines": {
- "node": ">=8",
- "npm": ">=5"
- },
- "peerDependencies": {
- "video.js": "^8.19.0"
- }
- },
- "node_modules/@videojs/vhs-utils": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz",
- "integrity": "sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "global": "^4.4.0"
- },
- "engines": {
- "node": ">=8",
- "npm": ">=5"
- }
- },
- "node_modules/@videojs/xhr": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.7.0.tgz",
- "integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.5.5",
- "global": "~4.4.0",
- "is-function": "^1.0.1"
- }
- },
- "node_modules/@xmldom/xmldom": {
- "version": "0.8.10",
- "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
- "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/aes-decrypter": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.2.tgz",
- "integrity": "sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "@videojs/vhs-utils": "^4.1.1",
- "global": "^4.4.0",
- "pkcs7": "^1.0.4"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "license": "MIT"
- },
- "node_modules/axios": {
- "version": "1.7.9",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
- "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/csstype": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/dom-walk": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
- "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
- },
- "node_modules/follow-redirects": {
- "version": "1.15.9",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
- "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
- "node_modules/form-data": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
- "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/global": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
- "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
- "license": "MIT",
- "dependencies": {
- "min-document": "^2.19.0",
- "process": "^0.11.10"
- }
- },
- "node_modules/is-function": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
- "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==",
- "license": "MIT"
- },
- "node_modules/m3u8-parser": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-7.2.0.tgz",
- "integrity": "sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "@videojs/vhs-utils": "^4.1.1",
- "global": "^4.4.0"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/min-document": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
- "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
- "dependencies": {
- "dom-walk": "^0.1.0"
- }
- },
- "node_modules/mpd-parser": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.1.tgz",
- "integrity": "sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "@videojs/vhs-utils": "^4.0.0",
- "@xmldom/xmldom": "^0.8.3",
- "global": "^4.4.0"
- },
- "bin": {
- "mpd-to-m3u8-json": "bin/parse.js"
- }
- },
- "node_modules/mux.js": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-7.1.0.tgz",
- "integrity": "sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@babel/runtime": "^7.11.2",
- "global": "^4.4.0"
- },
- "bin": {
- "muxjs-transmux": "bin/transmux.js"
- },
- "engines": {
- "node": ">=8",
- "npm": ">=5"
- }
- },
- "node_modules/pkcs7": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
- "integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@babel/runtime": "^7.5.5"
- },
- "bin": {
- "pkcs7": "bin/cli.js"
- }
- },
- "node_modules/process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6.0"
- }
- },
- "node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT"
- },
- "node_modules/react": {
- "version": "19.0.0",
- "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz",
- "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-dom": {
- "version": "19.0.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz",
- "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.25.0"
- },
- "peerDependencies": {
- "react": "^19.0.0"
- }
- },
- "node_modules/regenerator-runtime": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "license": "MIT"
- },
- "node_modules/scheduler": {
- "version": "0.25.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
- "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
- "license": "MIT"
- },
- "node_modules/video.js": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/video.js/-/video.js-8.21.0.tgz",
- "integrity": "sha512-zcwerRb257QAuWfi8NH9yEX7vrGKFthjfcONmOQ4lxFRpDAbAi+u5LAjCjMWqhJda6zEmxkgdDpOMW3Y21QpXA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "@videojs/http-streaming": "^3.16.2",
- "@videojs/vhs-utils": "^4.1.1",
- "@videojs/xhr": "2.7.0",
- "aes-decrypter": "^4.0.2",
- "global": "4.4.0",
- "m3u8-parser": "^7.2.0",
- "mpd-parser": "^1.3.1",
- "mux.js": "^7.0.1",
- "videojs-contrib-quality-levels": "4.1.0",
- "videojs-font": "4.2.0",
- "videojs-vtt.js": "0.15.5"
- }
- },
- "node_modules/videojs-contrib-quality-levels": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz",
- "integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==",
- "license": "Apache-2.0",
- "dependencies": {
- "global": "^4.4.0"
- },
- "engines": {
- "node": ">=16",
- "npm": ">=8"
- },
- "peerDependencies": {
- "video.js": "^8"
- }
- },
- "node_modules/videojs-font": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.2.0.tgz",
- "integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==",
- "license": "Apache-2.0"
- },
- "node_modules/videojs-vtt.js": {
- "version": "0.15.5",
- "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz",
- "integrity": "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "global": "^4.3.1"
- }
- }
- }
-}
diff --git a/package.json b/package.json
deleted file mode 100644
index 4c6d8ed..0000000
--- a/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "dependencies": {
- "@types/video.js": "^7.3.58",
- "axios": "^1.7.9",
- "react": "^19.0.0",
- "react-dom": "^19.0.0",
- "video.js": "^8.21.0"
- },
- "devDependencies": {
- "@types/react": "^19.0.8",
- "@types/react-dom": "^19.0.3"
- }
-}