Started vidstack port

This commit is contained in:
WardPearce
2024-03-25 23:26:01 +13:00
parent 4d2daf9644
commit e0cd4b2c3f
9 changed files with 198 additions and 572 deletions
-1
View File
@@ -16,7 +16,6 @@ Modern material design for Invidious
- Integrates with Invidious subscriptions, watch history & more.
- Live stream support.
- Dash support (WIP).
- Support for higher qualities if not proxying.
- Chapters.
- Audio only mode.
+55 -243
View File
@@ -9,14 +9,11 @@
"version": "0.0.1",
"dependencies": {
"beercss": "^3.5.1",
"dashjs": "^4.7.4",
"event-source-polyfill": "^1.0.31",
"eventsource": "^2.0.2",
"hls.js": "^1.5.7",
"human-number": "^2.0.4",
"plyr": "^3.7.8",
"media-icons": "^0.10.0",
"sponsorblock-api": "^0.2.4",
"svelte-persisted-store": "^0.9.1"
"svelte-persisted-store": "^0.9.1",
"vidstack": "^1.10.9"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
@@ -1324,7 +1321,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -1385,42 +1381,6 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/bcp-47": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-1.0.8.tgz",
"integrity": "sha512-Y9y1QNBBtYtv7hcmoX0tR+tUNSFZGZ6OL6vKPObq8BbOhkCoyayF6ogfLTgAli/KuAEbsYHYUNq2AQuY6IuLag==",
"dependencies": {
"is-alphabetical": "^1.0.0",
"is-alphanumerical": "^1.0.0",
"is-decimal": "^1.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/bcp-47-match": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-1.0.3.tgz",
"integrity": "sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/bcp-47-normalize": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-1.1.1.tgz",
"integrity": "sha512-jWZ1Jdu3cs0EZdfCkS0UE9Gg01PtxnChjEBySeB+Zo6nkqtFfnvtoQQgP1qU1Oo4qgJgxhTI6Sf9y/pZIhPs0A==",
"dependencies": {
"bcp-47": "^1.0.0",
"bcp-47-match": "^1.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/beercss": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/beercss/-/beercss-3.5.1.tgz",
@@ -1434,7 +1394,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true,
"engines": {
"node": ">=8"
}
@@ -1452,7 +1411,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@@ -1498,7 +1456,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -1522,7 +1479,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -1542,11 +1498,6 @@
"periscopic": "^3.1.0"
}
},
"node_modules/codem-isoboxer": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.9.tgz",
"integrity": "sha512-4XOTqEzBWrGOZaMd+sTED2hLpzfBbiQCf1W6OBGkIHqk1D8uwy8WFLazVbdQwfDpQ+vf39lqTGPa9IhWW0roTA=="
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1591,16 +1542,6 @@
"node": ">= 0.6"
}
},
"node_modules/core-js": {
"version": "3.36.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.36.0.tgz",
"integrity": "sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1644,38 +1585,6 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/custom-event-polyfill": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz",
"integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w=="
},
"node_modules/dashjs": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/dashjs/-/dashjs-4.7.4.tgz",
"integrity": "sha512-+hldo25QPP3H/NOwqUrvt4uKdMse60/Gsz9AUAnoYfhga8qHWq4nWiojUosOiigbigkDTCAn9ORcvUaKCvmfCA==",
"dependencies": {
"bcp-47-match": "^1.0.3",
"bcp-47-normalize": "^1.1.1",
"codem-isoboxer": "0.3.9",
"es6-promise": "^4.2.8",
"fast-deep-equal": "2.0.1",
"html-entities": "^1.2.1",
"imsc": "^1.1.5",
"localforage": "^1.7.1",
"path-browserify": "^1.0.1",
"ua-parser-js": "^1.0.37"
}
},
"node_modules/dashjs/node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"node_modules/dashjs/node_modules/fast-deep-equal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -2067,19 +1976,6 @@
"node": ">=0.10.0"
}
},
"node_modules/event-source-polyfill": {
"version": "1.0.31",
"resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz",
"integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA=="
},
"node_modules/eventsource": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz",
"integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==",
"engines": {
"node": ">=12.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",
@@ -2151,7 +2047,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -2237,7 +2132,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -2369,16 +2263,6 @@
"node": ">=8"
}
},
"node_modules/hls.js": {
"version": "1.5.7",
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.5.7.tgz",
"integrity": "sha512-Hnyf7ojTBtXHeOW1/t6wCBJSiK1WpoKF9yg7juxldDx8u3iswrkPt2wbOA/1NiwU4j27DSIVoIEJRAhcdMef/A=="
},
"node_modules/html-entities": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz",
"integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA=="
},
"node_modules/human-number": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/human-number/-/human-number-2.0.4.tgz",
@@ -2399,11 +2283,6 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -2430,14 +2309,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/imsc": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/imsc/-/imsc-1.1.5.tgz",
"integrity": "sha512-V8je+CGkcvGhgl2C1GlhqFFiUOIEdwXbXLiu1Fcubvvbo+g9inauqT3l0pNYXGoLPBj3jxtZz9t+wCopMkwadQ==",
"dependencies": {
"sax": "1.2.1"
}
},
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -2463,33 +2334,10 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/is-alphabetical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
"integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-alphanumerical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
"dependencies": {
"is-alphabetical": "^1.0.0",
"is-decimal": "^1.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
@@ -2497,20 +2345,10 @@
"node": ">=8"
}
},
"node_modules/is-decimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2519,7 +2357,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -2531,7 +2368,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
@@ -2626,14 +2462,6 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
@@ -2643,19 +2471,6 @@
"node": ">=10"
}
},
"node_modules/loadjs": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/loadjs/-/loadjs-4.2.0.tgz",
"integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA=="
},
"node_modules/localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"dependencies": {
"lie": "3.1.1"
}
},
"node_modules/locate-character": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
@@ -2721,6 +2536,22 @@
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
},
"node_modules/media-captions": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/media-captions/-/media-captions-1.0.3.tgz",
"integrity": "sha512-y2Qi5rqjwgH97zoko1vzu5Q6nnS0KzEQSvd4NOjnFym9JqnFb5VSsUg21RNb5cQ/nhCFJ0wz/XK+2uMwFCr6TQ==",
"engines": {
"node": ">=16"
}
},
"node_modules/media-icons": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/media-icons/-/media-icons-0.10.0.tgz",
"integrity": "sha512-M9loX7KUWsID3T8pRSN6/+MNKPEm9dNteqJk7yfo9ZaAIEYzEd07jWTVRlRmgVMKoAh1kY7funD6Qe1prrTJMQ==",
"engines": {
"node": ">=16"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -2858,7 +2689,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2931,11 +2761,6 @@
"node": ">=6"
}
},
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -2991,7 +2816,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
},
@@ -2999,18 +2823,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/plyr": {
"version": "3.7.8",
"resolved": "https://registry.npmjs.org/plyr/-/plyr-3.7.8.tgz",
"integrity": "sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==",
"dependencies": {
"core-js": "^3.26.1",
"custom-event-polyfill": "^1.0.7",
"loadjs": "^4.2.0",
"rangetouch": "^2.0.1",
"url-polyfill": "^1.1.12"
}
},
"node_modules/postcss": {
"version": "8.4.35",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
@@ -3190,16 +3002,10 @@
}
]
},
"node_modules/rangetouch": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz",
"integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA=="
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
@@ -3343,11 +3149,6 @@
"rimraf": "bin.js"
}
},
"node_modules/sax": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
"integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="
},
"node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
@@ -3671,7 +3472,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -3743,26 +3543,18 @@
"node": ">=14.17"
}
},
"node_modules/ua-parser-js": {
"version": "1.0.37",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
"integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==",
"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"
}
],
"node_modules/unplugin": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.10.0.tgz",
"integrity": "sha512-CuZtvvO8ua2Wl+9q2jEaqH6m3DoQ38N7pvBYQbbaeNlWGvK2l6GHiKi29aIHDPoSxdUzQ7Unevf1/ugil5X6Pg==",
"dependencies": {
"acorn": "^8.11.3",
"chokidar": "^3.6.0",
"webpack-sources": "^3.2.3",
"webpack-virtual-modules": "^0.6.1"
},
"engines": {
"node": "*"
"node": ">=14.0.0"
}
},
"node_modules/uri-js": {
@@ -3774,17 +3566,24 @@
"punycode": "^2.1.0"
}
},
"node_modules/url-polyfill": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.12.tgz",
"integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A=="
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
},
"node_modules/vidstack": {
"version": "1.10.9",
"resolved": "https://registry.npmjs.org/vidstack/-/vidstack-1.10.9.tgz",
"integrity": "sha512-YjaCdQxsRrhQpdR48jtNhusMrC5009BWQ3KtFhBzAMEDN23wW5qLNqdWfSgXVogZdpk/C2W/+79HcdDiW12PYg==",
"dependencies": {
"media-captions": "^1.0.1",
"unplugin": "^1.6.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/vite": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.1.5.tgz",
@@ -3874,6 +3673,19 @@
}
}
},
"node_modules/webpack-sources": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz",
"integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg=="
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+3 -6
View File
@@ -34,13 +34,10 @@
"type": "module",
"dependencies": {
"beercss": "^3.5.1",
"dashjs": "^4.7.4",
"event-source-polyfill": "^1.0.31",
"eventsource": "^2.0.2",
"hls.js": "^1.5.7",
"human-number": "^2.0.4",
"plyr": "^3.7.8",
"media-icons": "^0.10.0",
"sponsorblock-api": "^0.2.4",
"svelte-persisted-store": "^0.9.1"
"svelte-persisted-store": "^0.9.1",
"vidstack": "^1.10.9"
}
}
+122 -305
View File
@@ -1,33 +1,33 @@
<script lang="ts">
import Plyr, { type PlyrEvent, type SourceInfo, type Track } from 'plyr';
// Needed to overwrite Beercss styles.
import Dash from 'dashjs';
import Hls from 'hls.js';
import 'plyr/dist/plyr.css';
import { SponsorBlock, type Category } from 'sponsorblock-api';
import { onDestroy, onMount, tick } from 'svelte';
import { get } from 'svelte/store';
import 'vidstack/bundle';
import type { MediaPlayerClass } from 'dashjs';
import { SponsorBlock, type Category } from 'sponsorblock-api';
import { onDestroy, onMount } from 'svelte';
import { get } from 'svelte/store';
import type { MediaTimeUpdateEvent, PlayerSrc } from 'vidstack';
import type { MediaPlayerElement } from 'vidstack/elements';
import { MediaQualityRadioGroupElement, defineCustomElement } from 'vidstack/elements';
import 'vidstack/icons';
import {
invidiousInstance,
playerAlwaysLoop,
playerAutoPlay,
playerDash,
playerProxyVideos,
playerSavePlaybackPosition,
sponsorBlockCategories,
sponsorBlock as sponsorBlockStore,
sponsorBlockUrl
} from '../store';
import type { VideoPlay } from './Api/model';
import { getDynamicTheme } from './theme';
defineCustomElement(MediaQualityRadioGroupElement);
export let data: { video: VideoPlay };
export let currentTime: number = 0;
export let audioMode = false;
let previousMode = structuredClone(audioMode);
let player: MediaPlayerElement;
let src: PlayerSrc = [];
let categoryBeingSkipped = '';
export function seekTo(time: number) {
if (typeof player !== 'undefined') {
@@ -35,309 +35,126 @@
}
}
let player: Plyr | undefined = undefined;
let audio: HTMLAudioElement | undefined = undefined;
let categoryBeingSkipped = '';
let sponsorBlock: SponsorBlock | undefined;
let hls: Hls | undefined;
let dash: MediaPlayerClass | undefined;
$: {
if (previousMode !== audioMode) {
tick().then(async () => {
savePlayerPos();
document.getElementsByClassName('plyr')[0]?.remove();
await createPlayer();
previousMode = structuredClone(audioMode);
});
}
}
async function createPlayer() {
if (data.video.isUpcoming || !data.video.isListed) {
return;
}
const playerPos = localStorage.getItem(data.video.videoId);
const tracks: Track[] = [];
for (const caption of data.video.captions) {
// Have to preload captions, due to cors issue with how plyr
// grabs captions
if (!caption) {
continue;
}
const captions = await fetch(`${get(invidiousInstance)}${caption.url}`);
if (captions.status === 200) {
tracks.push({
kind: 'captions',
label: caption.label,
srcLang: caption.languageCode,
src: URL.createObjectURL(await captions.blob())
});
}
}
const sourceInfo: SourceInfo = {
type: !audioMode ? 'video' : 'audio',
previewThumbnails: {
src: data.video.videoThumbnails[0].url
},
poster: data.video.videoThumbnails[0].url,
tracks: tracks,
sources: []
};
const videoElement = document.getElementById('player') as HTMLMediaElement;
const qualitySettings = {
default: 720,
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240]
};
if (audioMode) {
qualitySettings.options = [];
data.video.adaptiveFormats.forEach((source) => {
if (typeof source.audioQuality !== 'undefined' && source.container === 'm4a') {
const bitrate = Number(source.bitrate);
qualitySettings.options.push(bitrate);
sourceInfo.sources.push({
src: source.url,
type: source.type,
size: bitrate
});
}
});
qualitySettings.default = qualitySettings.options[0];
}
player = new Plyr(videoElement, {
controls: [
'play-large',
'play',
'progress',
'current-time',
'duration',
'volume',
'captions',
'settings',
'download',
'fullscreen'
],
quality: qualitySettings
});
if (get(sponsorBlockStore)) {
const currentCategories = get(sponsorBlockCategories);
if (currentCategories.length > 0) {
sponsorBlock = new SponsorBlock('', { baseURL: get(sponsorBlockUrl) });
try {
const segments = await sponsorBlock.getSegments(
data.video.videoId,
get(sponsorBlockCategories) as Category[]
);
player.on('timeupdate', (event: PlyrEvent) => {
segments.forEach((segment) => {
if (
event.detail.plyr.currentTime >= segment.startTime &&
event.detail.plyr.currentTime <= segment.endTime
) {
categoryBeingSkipped = segment.category;
event.detail.plyr.currentTime = segment.endTime + 1;
ui('#sponsorblock-alert');
}
});
});
} catch {}
}
}
player.on('loadeddata', (event: PlyrEvent) => {
if (get(playerSavePlaybackPosition) && playerPos) {
event.detail.plyr.currentTime = Number(playerPos);
}
});
player.on('timeupdate', (event: PlyrEvent) => {
currentTime = event.detail.plyr.currentTime;
});
player.on('pause', () => {
savePlayerPos();
});
player.autoplay = get(playerAutoPlay);
player.loop = get(playerAlwaysLoop);
if (!audioMode) {
if (!data.video.hlsUrl) {
if (get(playerDash)) {
dash = Dash.MediaPlayer().create();
dash.initialize(videoElement, data.video.dashUrl + '?local=true', get(playerAutoPlay));
} else {
const proxyVideos = get(playerProxyVideos);
if (proxyVideos) {
let src;
sourceInfo.sources = data.video.formatStreams.map((format) => {
if (proxyVideos) {
const rawSrc = new URL(format.url);
rawSrc.host = import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE.replace(
'http://',
''
).replace('https://', '');
src = rawSrc.toString();
} else {
src = format.url;
}
return {
src: src,
size: Number(format.size.split('x')[1]),
type: format.type
};
});
} else {
data.video.adaptiveFormats.forEach((format) => {
if (typeof format.resolution !== 'undefined') {
const size = Number(format.resolution.replace('p', ''));
sourceInfo.sources.push({
type: format.type,
src: format.url,
size: size
});
}
});
let audioSrc = data.video.adaptiveFormats.filter((audioFormat) => {
if (audioFormat.audioQuality === 'AUDIO_QUALITY_MEDIUM') {
return true;
} else {
return false;
}
});
if (audioSrc.length === 0) {
audioSrc = data.video.adaptiveFormats.filter((audioFormat) => {
if (audioFormat.audioQuality === 'AUDIO_QUALITY_LOW') {
return true;
} else {
return false;
}
});
}
audio = new Audio(audioSrc[0].url);
audio.load();
audio.volume = player.volume;
player.on('volumechange', (event: PlyrEvent) => {
if (!audio) return;
audio.volume = event.detail.plyr.volume;
});
player.on('waiting', () => {
if (!audio) return;
audio.pause();
});
player.on('seeked', (event: PlyrEvent) => {
if (!audio) return;
audio.currentTime = event.detail.plyr.currentTime;
if (player?.playing) {
audio.play();
}
});
player.on('ratechange', (event: PlyrEvent) => {
if (!audio) return;
audio.playbackRate = event.detail.plyr.speed;
});
player.on('playing', () => {
if (!audio) return;
audio.play();
});
player.on('pause', () => {
if (!audio) return;
audio.pause();
});
}
}
} else {
hls = new Hls();
hls.loadSource(data.video.hlsUrl + '?local=true');
hls.attachMedia(videoElement);
}
}
player.source = sourceInfo;
const currentTheme = await getDynamicTheme();
document.documentElement.style.setProperty('--plyr-color-main', currentTheme['--primary']);
document.documentElement.style.setProperty(
'--plyr-menu-background',
currentTheme['--secondary-container']
);
document.documentElement.style.setProperty(
'--plyr-menu-color',
currentTheme['--secondary-text']
);
}
function savePlayerPos() {
if (get(playerSavePlaybackPosition) && player?.currentTime) {
if (player.currentTime < player.duration - 10 && player.currentTime > 10) {
localStorage.setItem(data.video.videoId, player.currentTime.toString());
} else {
localStorage.removeItem(data.video.videoId);
}
}
}
const proxyVideos = get(playerProxyVideos);
onMount(async () => {
await createPlayer();
if (!data.video.hlsUrl) {
player.addEventListener('time-update', () => {
currentTime = player.currentTime;
});
player.addEventListener('pause', () => {
savePlayerPos();
});
if (get(sponsorBlockCategories)) {
const currentCategories = get(sponsorBlockCategories);
if (currentCategories.length > 0) {
const sponsorBlock = new SponsorBlock('', { baseURL: get(sponsorBlockUrl) });
try {
const segments = await sponsorBlock.getSegments(
data.video.videoId,
get(sponsorBlockCategories) as Category[]
);
player.addEventListener('time-update', (event: MediaTimeUpdateEvent) => {
segments.forEach((segment) => {
if (
event.detail.currentTime >= segment.startTime &&
event.detail.currentTime <= segment.endTime
) {
categoryBeingSkipped = segment.category;
player.currentTime = segment.endTime + 1;
ui('#sponsorblock-alert');
}
});
});
} catch {}
}
}
if (get(playerDash)) {
src = [{ src: data.video.dashUrl + '?local=true', type: 'application/dash+xml' }];
} else {
let formattedSrc;
src = data.video.formatStreams.map((format) => {
if (proxyVideos) {
const rawSrc = new URL(format.url);
rawSrc.host = import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE.replace(
'http://',
''
).replace('https://', '');
formattedSrc = rawSrc.toString();
} else {
formattedSrc = format.url;
}
return {
src: formattedSrc,
type: format.type.split(';')[0]
};
});
}
if (get(playerSavePlaybackPosition)) {
const playerPos = localStorage.getItem(`v_${data.video.videoId}`);
if (playerPos) {
player.currentTime = Number(playerPos);
}
}
} else {
src = [
{
src: data.video.hlsUrl + '?local=true',
type: 'application/x-mpegurl'
}
];
}
});
onDestroy(async () => {
savePlayerPos();
function savePlayerPos() {
if (get(playerSavePlaybackPosition) && player.currentTime) {
if (player.currentTime < player.duration - 10 && player.currentTime > 10) {
localStorage.setItem(`v_${data.video.videoId}`, player.currentTime.toString());
} else {
localStorage.removeItem(`v_${data.video.videoId}`);
}
}
}
player = undefined;
sponsorBlock = undefined;
hls = undefined;
dash = undefined;
audio = undefined;
document.getElementsByClassName('plyr')[0]?.remove();
onDestroy(() => {
savePlayerPos();
player.destroy();
});
</script>
<media-player
bind:this={player}
autoPlay={$playerAutoPlay}
loop={$playerAlwaysLoop}
title={data.video.title}
streamType={data.video.hlsUrl ? 'live' : 'on-demand'}
viewType={audioMode ? 'audio' : 'video'}
playsInline={true}
{src}
>
<media-provider>
<media-poster class="vds-poster" src={data.video.videoThumbnails[0].url}></media-poster>
</media-provider>
<media-audio-layout></media-audio-layout>
<media-video-layout></media-video-layout>
{#if data.video.storyboards && data.video.storyboards.length > 3}
<media-video-layout
thumbnails={`${import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE}${data.video.storyboards[3].url}`}
></media-video-layout>
{/if}
</media-player>
<div class="snackbar" id="sponsorblock-alert">
<span
>Skipping <span class="bold" style="text-transform: capitalize;">{categoryBeingSkipped}</span
></span
>
</div>
{#if data.video.isUpcoming}
<h3>Video hasn't premiered yet</h3>
{:else if !data.video.isListed}
<h3>Video isn't listed</h3>
{:else}
{#if audioMode}
<div style="margin-top: 50vh;"></div>
{/if}
{#key audioMode}
<video id="player" playsinline controls> </video>
{/key}
{/if}
+3 -2
View File
@@ -63,8 +63,9 @@
{/if}
</a>
<div class="small-padding">
{#if localStorage.getItem(video.videoId)}
<progress value={localStorage.getItem(video.videoId)} max={video.lengthSeconds}></progress>
{#if localStorage.getItem(`v_${video.videoId}`)}
<progress value={localStorage.getItem(`v_${video.videoId}`)} max={video.lengthSeconds}
></progress>
{/if}
<nav class="no-margin">
<div class="max">
@@ -155,7 +155,11 @@
on:click={() => seekTo(timestamp.time)}
class="timestamps"
class:primary={timestamp.time <= currentTime}
>{timestamp.title} - {timestamp.timePretty}</button
>{timestamp.timePretty}
{#if !timestamp.title.startsWith('-')}
-
{/if}
{timestamp.title}</button
>
{/each}
{/if}
-11
View File
@@ -1,11 +0,0 @@
.plyr--full-ui.plyr--video .plyr__control--overlaid, .plyr__control {
display: flex !important;
}
video {
max-height: 720px;
}
.plyr:fullscreen video {
max-height: initial !important;
}
+5 -2
View File
@@ -9,10 +9,13 @@
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
"moduleResolution": "bundler",
"types": [
"vidstack/svelte"
]
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}
}
+5 -1
View File
@@ -1,6 +1,10 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { vite as vidstack } from 'vidstack/plugins';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()],
plugins: [
vidstack(),
sveltekit()
],
});