From 50b067f9cd95a190378c81da8535ce45938ffdd8 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 5 Feb 2025 06:36:05 +0100 Subject: [PATCH] Separate player in dedicated build * Separate player in a dedicated build, that we can control using vite. We had too many issues with Angular build system and we can now have the same build between the embed and the client. We can also embed SVG directly in the CSS * Upgrade p2p-media-loader to v2 * Update internal infohashes to reflect this p2p-media-loader protocol change (they are updated at PeerTube startup) * Minimum required iOS version is now v14 --- client/.browserslistrc | 2 +- client/.eslintrc.json | 3 +- client/.gitignore | 2 + client/angular.json | 11 +- client/e2e/tsconfig.json | 2 +- client/package.json | 16 +- .../+video-watch/player-styles.component.scss | 6 +- .../+video-watch/video-watch.component.ts | 8 +- client/src/assets/player/index.ts | 2 - client/src/root-helpers/plugins-manager.ts | 7 +- .../translations-manager.ts | 0 .../src/standalone/build-tools/vite-utils.ts | 21 + client/src/standalone/player/package.json | 31 ++ client/src/standalone/player/src/index.ts | 5 + .../src}/peertube-player-local-storage.ts | 0 .../player/src}/peertube-player.ts | 4 +- .../standalone/player/src/sass/player.scss | 2 + .../src/sass/shared}/_player-variables.scss | 2 - .../player/src/sass/shared}/bezels.scss | 0 .../player/src/sass/shared}/context-menu.scss | 4 +- .../player/src/sass/shared}/control-bar.scss | 32 +- .../player/src/sass/shared}/dock.scss | 0 .../player/src/sass/shared}/index.scss | 0 .../player/src/sass/shared}/mobile.scss | 0 .../sass/shared}/offline-notification.scss | 0 .../src/sass/shared}/peertube-skin.scss | 2 +- .../player/src/sass/shared}/playlist.scss | 8 +- .../src/sass/shared}/settings-menu.scss | 2 +- .../player/src/sass/shared}/spinner.scss | 0 .../player/src/sass/shared}/stats.scss | 0 .../player/src/sass/shared}/storyboard.scss | 0 .../player/src/sass/shared}/upnext.scss | 0 .../player/src/sass/svg}/arrow-down.svg | 0 .../player/src/sass/svg}/arrow-up.svg | 0 .../player/src/sass/svg}/big-play-button.svg | 0 .../player/src/sass/svg}/code.svg | 0 .../player/src/sass/svg}/fullscreen.svg | 0 .../player/src/sass/svg}/info.svg | 0 .../player/src/sass/svg}/link-2.svg | 0 .../player/src/sass/svg}/next.svg | 0 .../player/src/sass/svg/playlists.svg | 77 +++ .../player/src/sass/svg}/repeat.svg | 0 .../player/src/sass/svg}/settings.svg | 0 .../player/src/sass/svg}/theater.svg | 0 .../player/src/sass/svg}/tick-white.svg | 0 .../player/src/sass/svg}/volume-mute.svg | 0 .../player/src/sass/svg}/volume.svg | 0 .../src/standalone/player/src/sass/svg/x.svg | 1 + .../src}/shared/bezels/bezels-plugin.ts | 0 .../player/src}/shared/bezels/index.ts | 0 .../player/src}/shared/bezels/pause-bezel.ts | 0 .../player/src}/shared/common/index.ts | 0 .../player/src}/shared/common/utils.ts | 0 .../shared/context-menu/context-menu-item.ts | 0 .../context-menu/context-menu-plugin.ts | 0 .../src}/shared/context-menu/context-menu.ts | 0 .../player/src}/shared/context-menu/index.ts | 0 .../player/src}/shared/context-menu/util.ts | 0 .../control-bar/caption-toggle-button.ts | 0 .../shared/control-bar/chapters-plugin.ts | 0 .../player/src}/shared/control-bar/index.ts | 0 .../control-bar/next-previous-video-button.ts | 0 .../shared/control-bar/p2p-info-button.ts | 0 .../control-bar/peertube-link-button.ts | 0 .../control-bar/peertube-live-display.ts | 0 .../progress-bar-marker-component.ts | 0 .../shared/control-bar/storyboard-plugin.ts | 0 .../src}/shared/control-bar/theater-button.ts | 0 .../src}/shared/control-bar/time-tooltip.ts | 0 .../player/src}/shared/dock/index.ts | 0 .../shared/dock/peertube-dock-component.ts | 0 .../src}/shared/dock/peertube-dock-plugin.ts | 0 .../player/src}/shared/hotkeys/index.ts | 0 .../shared/hotkeys/peertube-hotkeys-plugin.ts | 0 .../player/src}/shared/metrics/index.ts | 0 .../src}/shared/metrics/metrics-plugin.ts | 0 .../player/src}/shared/mobile/index.ts | 0 .../shared/mobile/peertube-mobile-buttons.ts | 0 .../shared/mobile/peertube-mobile-plugin.ts | 0 .../shared/p2p-media-loader/hls-plugin.ts | 35 +- .../src}/shared/p2p-media-loader/index.ts | 0 .../p2p-media-loader-plugin.ts | 85 +-- .../redundancy-url-manager.ts | 22 +- .../p2p-media-loader/segment-url-builder.ts | 2 +- .../p2p-media-loader/segment-validator.ts | 41 +- .../player/src}/shared/peertube/index.ts | 0 .../src}/shared/peertube/peertube-plugin.ts | 0 .../control-bar-options-builder.ts | 0 .../hls-options-builder.ts | 128 +++-- .../shared/player-options-builder/index.ts | 0 .../web-video-options-builder.ts | 0 .../player/src}/shared/playlist/index.ts | 0 .../src}/shared/playlist/playlist-button.ts | 0 .../shared/playlist/playlist-menu-item.ts | 0 .../src}/shared/playlist/playlist-menu.ts | 0 .../src}/shared/playlist/playlist-plugin.ts | 0 .../player/src}/shared/resolutions/index.ts | 0 .../peertube-resolutions-plugin.ts | 0 .../player/src}/shared/settings/index.ts | 0 .../src}/shared/settings/menu-focus-fixed.ts | 0 .../shared/settings/resolution-menu-button.ts | 0 .../shared/settings/resolution-menu-item.ts | 0 .../src}/shared/settings/settings-dialog.ts | 0 .../shared/settings/settings-menu-button.ts | 0 .../shared/settings/settings-menu-item.ts | 0 .../shared/settings/settings-panel-child.ts | 0 .../src}/shared/settings/settings-panel.ts | 0 .../player/src}/shared/stats/index.ts | 0 .../player/src}/shared/stats/stats-card.ts | 2 + .../player/src}/shared/stats/stats-plugin.ts | 0 .../player/src}/shared/upnext/end-card.ts | 0 .../player/src}/shared/upnext/index.ts | 0 .../src}/shared/upnext/upnext-plugin.ts | 0 .../src}/shared/web-video/web-video-plugin.ts | 0 .../player/src}/types/index.ts | 0 .../src}/types/peertube-player-options.ts | 0 .../src}/types/peertube-videojs-typings.ts | 9 +- client/src/standalone/player/tsconfig.json | 6 + client/src/standalone/player/vite.config.mjs | 47 ++ client/src/standalone/videos/embed.scss | 6 +- client/src/standalone/videos/embed.ts | 25 +- .../videos/shared/peertube-plugin.ts | 3 +- .../videos/shared/player-options-builder.ts | 4 +- client/src/standalone/videos/vite.config.mjs | 18 +- client/yarn.lock | 514 +++++++++--------- packages/node-utils/src/crypto.ts | 4 + packages/node-utils/src/index.ts | 1 + packages/node-utils/src/p2p.ts | 7 + .../tests/src/api/object-storage/videos.ts | 2 +- packages/tests/src/api/server/tracker.ts | 2 +- .../tests/src/api/transcoding/transcoder.ts | 2 +- .../tests/src/api/videos/multiple-servers.ts | 2 +- .../api/videos/video-static-file-privacy.ts | 2 +- packages/tests/src/cli/update-host.ts | 2 +- packages/tests/src/shared/live.ts | 12 +- .../src/shared/{webtorrent.ts => p2p.ts} | 0 .../tests/src/shared/streaming-playlists.ts | 65 ++- packages/tests/src/shared/tracker.ts | 11 +- packages/tests/src/shared/videos.ts | 2 +- scripts/build/client.sh | 9 +- scripts/build/embed.sh | 2 + scripts/client-report.sh | 1 + scripts/dev/client.sh | 8 +- scripts/dev/embed.sh | 2 + server/core/controllers/tracker.ts | 28 +- server/core/initializers/constants.ts | 6 +- .../shared/object-to-model-attributes.ts | 2 +- server/core/lib/hls.ts | 21 +- server/core/lib/live/shared/muxing-session.ts | 2 +- server/core/models/video/video-file.ts | 16 +- .../models/video/video-streaming-playlist.ts | 38 +- 151 files changed, 868 insertions(+), 578 deletions(-) delete mode 100644 client/src/assets/player/index.ts rename client/src/{assets/player => root-helpers}/translations-manager.ts (100%) create mode 100644 client/src/standalone/build-tools/vite-utils.ts create mode 100644 client/src/standalone/player/package.json create mode 100644 client/src/standalone/player/src/index.ts rename client/src/{assets/player => standalone/player/src}/peertube-player-local-storage.ts (100%) rename client/src/{assets/player => standalone/player/src}/peertube-player.ts (99%) create mode 100644 client/src/standalone/player/src/sass/player.scss rename client/src/{sass/player => standalone/player/src/sass/shared}/_player-variables.scss (93%) rename client/src/{sass/player => standalone/player/src/sass/shared}/bezels.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/context-menu.scss (89%) rename client/src/{sass/player => standalone/player/src/sass/shared}/control-bar.scss (94%) rename client/src/{sass/player => standalone/player/src/sass/shared}/dock.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/index.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/mobile.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/offline-notification.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/peertube-skin.scss (98%) rename client/src/{sass/player => standalone/player/src/sass/shared}/playlist.scss (91%) rename client/src/{sass/player => standalone/player/src/sass/shared}/settings-menu.scss (97%) rename client/src/{sass/player => standalone/player/src/sass/shared}/spinner.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/stats.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/storyboard.scss (100%) rename client/src/{sass/player => standalone/player/src/sass/shared}/upnext.scss (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/arrow-down.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/arrow-up.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/big-play-button.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/code.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/fullscreen.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/info.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/link-2.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/next.svg (100%) create mode 100644 client/src/standalone/player/src/sass/svg/playlists.svg rename client/src/{assets/player/images => standalone/player/src/sass/svg}/repeat.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/settings.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/theater.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/tick-white.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/volume-mute.svg (100%) rename client/src/{assets/player/images => standalone/player/src/sass/svg}/volume.svg (100%) create mode 100644 client/src/standalone/player/src/sass/svg/x.svg rename client/src/{assets/player => standalone/player/src}/shared/bezels/bezels-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/bezels/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/bezels/pause-bezel.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/common/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/common/utils.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/context-menu/context-menu-item.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/context-menu/context-menu-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/context-menu/context-menu.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/context-menu/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/context-menu/util.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/caption-toggle-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/chapters-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/next-previous-video-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/p2p-info-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/peertube-link-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/peertube-live-display.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/progress-bar-marker-component.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/storyboard-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/theater-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/control-bar/time-tooltip.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/dock/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/dock/peertube-dock-component.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/dock/peertube-dock-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/hotkeys/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/hotkeys/peertube-hotkeys-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/metrics/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/metrics/metrics-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/mobile/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/mobile/peertube-mobile-buttons.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/mobile/peertube-mobile-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/p2p-media-loader/hls-plugin.ts (95%) rename client/src/{assets/player => standalone/player/src}/shared/p2p-media-loader/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/p2p-media-loader/p2p-media-loader-plugin.ts (74%) rename client/src/{assets/player => standalone/player/src}/shared/p2p-media-loader/redundancy-url-manager.ts (67%) rename client/src/{assets/player => standalone/player/src}/shared/p2p-media-loader/segment-url-builder.ts (84%) rename client/src/{assets/player => standalone/player/src}/shared/p2p-media-loader/segment-validator.ts (76%) rename client/src/{assets/player => standalone/player/src}/shared/peertube/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/peertube/peertube-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/player-options-builder/control-bar-options-builder.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/player-options-builder/hls-options-builder.ts (66%) rename client/src/{assets/player => standalone/player/src}/shared/player-options-builder/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/player-options-builder/web-video-options-builder.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/playlist/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/playlist/playlist-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/playlist/playlist-menu-item.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/playlist/playlist-menu.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/playlist/playlist-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/resolutions/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/resolutions/peertube-resolutions-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/menu-focus-fixed.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/resolution-menu-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/resolution-menu-item.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/settings-dialog.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/settings-menu-button.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/settings-menu-item.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/settings-panel-child.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/settings/settings-panel.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/stats/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/stats/stats-card.ts (99%) rename client/src/{assets/player => standalone/player/src}/shared/stats/stats-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/upnext/end-card.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/upnext/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/upnext/upnext-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/shared/web-video/web-video-plugin.ts (100%) rename client/src/{assets/player => standalone/player/src}/types/index.ts (100%) rename client/src/{assets/player => standalone/player/src}/types/peertube-player-options.ts (100%) rename client/src/{assets/player => standalone/player/src}/types/peertube-videojs-typings.ts (96%) create mode 100644 client/src/standalone/player/tsconfig.json create mode 100644 client/src/standalone/player/vite.config.mjs create mode 100644 packages/node-utils/src/p2p.ts rename packages/tests/src/shared/{webtorrent.ts => p2p.ts} (100%) diff --git a/client/.browserslistrc b/client/.browserslistrc index 9eb6a61de..cdc51d7ad 100644 --- a/client/.browserslistrc +++ b/client/.browserslistrc @@ -1,4 +1,4 @@ last 1 Chrome version last 2 Edge major versions Firefox ESR -ios_saf >= 13.1 +ios_saf >= 14 diff --git a/client/.eslintrc.json b/client/.eslintrc.json index d00e6e7ab..709aa79d1 100644 --- a/client/.eslintrc.json +++ b/client/.eslintrc.json @@ -163,7 +163,8 @@ "@typescript-eslint/unbound-method": [ "error", { "ignoreStatic": true } - ] + ], + "import/no-named-default": "off" } }, { diff --git a/client/.gitignore b/client/.gitignore index 6523ad810..04c0e93f1 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -12,6 +12,8 @@ /e2e/local.log /e2e/browserstack.err /e2e/screenshots +/src/standalone/player/build +/src/standalone/player/dist /src/standalone/embed-player-api/build /src/standalone/embed-player-api/dist /e2e/logs diff --git a/client/angular.json b/client/angular.json index 82c4ad217..8c0d6f144 100644 --- a/client/angular.json +++ b/client/angular.json @@ -183,7 +183,10 @@ "includePaths": [ "src/sass/include", "." - ] + ], + "sass": { + "silenceDeprecations": [ "import", "mixed-decls", "color-functions", "global-builtin" ] + } }, "assets": [ "src/assets/images", @@ -212,7 +215,9 @@ "is-plain-object", "parse-srcset", "deepmerge", - "core-js/features/reflect" + "core-js/features/reflect", + "hammerjs", + "jschannel" ], "scripts": [], "extractLicenses": false, @@ -241,7 +246,7 @@ { "type": "anyComponentStyle", "maximumWarning": "6kb", - "maximumError": "100kb" + "maximumError": "120kb" } ], "fileReplacements": [ diff --git a/client/e2e/tsconfig.json b/client/e2e/tsconfig.json index af776ebd3..f5958a4b2 100644 --- a/client/e2e/tsconfig.json +++ b/client/e2e/tsconfig.json @@ -5,7 +5,7 @@ "noImplicitAny": false, "esModuleInterop": true, "module": "commonjs", - "target": "ES2015", + "target": "ES2018", "typeRoots": [ "../node_modules/@types", "../node_modules" diff --git a/client/package.json b/client/package.json index ae3b47d64..d9fce706b 100644 --- a/client/package.json +++ b/client/package.json @@ -24,10 +24,13 @@ "net": false, "stream": false, "os": false, + "http": false, + "dgram": false, "util": false }, "workspaces": [ - "../packages/*" + "../packages/*", + "./src/standalone/player" ], "typings": "*.d.ts", "devDependencies": { @@ -55,8 +58,6 @@ "@ngx-loading-bar/http-client": "^7.0.0", "@ngx-loading-bar/router": "^7.0.0", "@peertube/maildev": "^1.2.0", - "@peertube/p2p-media-loader-core": "^1.0.20", - "@peertube/p2p-media-loader-hlsjs": "^1.0.20", "@peertube/xliffmerge": "^2.0.3", "@plussub/srt-vtt-parser": "^2.0.5", "@popperjs/core": "^2.11.5", @@ -103,8 +104,11 @@ "markdown-it": "14.1.0", "markdown-it-emoji": "^3.0.0", "ngx-uploadx": "^7.0.0", + "p2p-media-loader-core": "^2.1.2", + "p2p-media-loader-hlsjs": "^2.1.2", "primeng": "^17", "rxjs": "^7.3.0", + "sass-embedded": "^1.83.4", "sha.js": "^2.4.11", "socket.io-client": "^4.5.4", "stylelint": "^16.2.1", @@ -115,9 +119,9 @@ "tslib": "^2.4.0", "typescript": "~5.7.3", "video.js": "^7.19.2", - "vite": "^5.3.1", - "vite-plugin-checker": "^0.7.2", - "vite-plugin-node-polyfills": "^0.22.0", + "vite": "^6.0.11", + "vite-plugin-checker": "^0.8.0", + "vite-plugin-node-polyfills": "^0.23.0", "zone.js": "~0.15.0" }, "dependencies": {} diff --git a/client/src/app/+videos/+video-watch/player-styles.component.scss b/client/src/app/+videos/+video-watch/player-styles.component.scss index c0befc10a..d2b386a5b 100644 --- a/client/src/app/+videos/+video-watch/player-styles.component.scss +++ b/client/src/app/+videos/+video-watch/player-styles.component.scss @@ -1,5 +1 @@ -@use 'node_modules/video.js/dist/video-js'; - -$assets-path: '../../assets/'; - -@use '../../../sass/player/index'; +@use '../../../standalone/player/build/peertube-player.css'; diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts index ca4956439..6f4c3fa65 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.ts +++ b/client/src/app/+videos/+video-watch/video-watch.component.ts @@ -47,16 +47,18 @@ import { logger } from '@root-helpers/logger' import { isP2PEnabled, videoRequiresFileToken, videoRequiresUserAuth } from '@root-helpers/video' import debug from 'debug' import { forkJoin, map, Observable, of, Subscription, switchMap } from 'rxjs' +import { environment } from '../../../environments/environment' import { + cleanupVideoWatch, + getStoredTheater, + getStoredVideoWatchHistory, HLSOptions, PeerTubePlayer, PeerTubePlayerConstructorOptions, PeerTubePlayerLoadOptions, PlayerMode, videojs -} from '../../../assets/player' -import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage' -import { environment } from '../../../environments/environment' +} from '@peertube/player' import { DateToggleComponent } from '../../shared/shared-main/date/date-toggle.component' import { PluginPlaceholderComponent } from '../../shared/shared-main/plugins/plugin-placeholder.component' import { VideoViewsCounterComponent } from '../../shared/shared-video/video-views-counter.component' diff --git a/client/src/assets/player/index.ts b/client/src/assets/player/index.ts deleted file mode 100644 index d34188ea7..000000000 --- a/client/src/assets/player/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './peertube-player' -export * from './types' diff --git a/client/src/root-helpers/plugins-manager.ts b/client/src/root-helpers/plugins-manager.ts index b11af1511..c82836f9f 100644 --- a/client/src/root-helpers/plugins-manager.ts +++ b/client/src/root-helpers/plugins-manager.ts @@ -2,7 +2,7 @@ import debug from 'debug' import { firstValueFrom, ReplaySubject } from 'rxjs' import { first, shareReplay } from 'rxjs/operators' -import { RegisterClientHelpers } from 'src/types/register-client-option.model' +import { RegisterClientHelpers } from '../types/register-client-option.model' import { getExternalAuthHref, getHookType, internalRunHook } from '@peertube/peertube-core-utils' import { ClientDoAction, @@ -83,6 +83,7 @@ class PluginsManager { private readonly onFormFields: OnFormFields private readonly onSettingsScripts: OnSettingsScripts private readonly onClientRoute: OnClientRoute + private readonly backendUrl: string constructor (options: { doAction?: ClientDoAction @@ -90,12 +91,14 @@ class PluginsManager { onFormFields?: OnFormFields onSettingsScripts?: OnSettingsScripts onClientRoute?: OnClientRoute + backendUrl?: string }) { this.doAction = options.doAction this.peertubeHelpersFactory = options.peertubeHelpersFactory this.onFormFields = options.onFormFields this.onSettingsScripts = options.onSettingsScripts this.onClientRoute = options.onClientRoute + this.backendUrl = options.backendUrl } static getPluginPathPrefix (isTheme: boolean) { @@ -281,7 +284,7 @@ class PluginsManager { logger.info(`Loading script ${clientScript.script} of plugin ${plugin.name}`) - const absURL = (environment.apiUrl || window.location.origin) + clientScript.script + const absURL = (this.backendUrl || environment.apiUrl || window.location.origin) + clientScript.script return dynamicImport(absURL) .then((script: ClientScript) => { return script.register({ diff --git a/client/src/assets/player/translations-manager.ts b/client/src/root-helpers/translations-manager.ts similarity index 100% rename from client/src/assets/player/translations-manager.ts rename to client/src/root-helpers/translations-manager.ts diff --git a/client/src/standalone/build-tools/vite-utils.ts b/client/src/standalone/build-tools/vite-utils.ts new file mode 100644 index 000000000..bf366659c --- /dev/null +++ b/client/src/standalone/build-tools/vite-utils.ts @@ -0,0 +1,21 @@ +import { resolve } from 'path' + +export function getCSSConfig (root: string) { + return { + preprocessorOptions: { + scss: { + api: 'modern-compiler', + loadPaths: [ resolve(root, './src/sass/include') ], + // FIXME: Wait for bootstrap upgrade that fixes deprecated sass utils + silenceDeprecations: [ 'import', 'mixed-decls', 'color-functions', 'global-builtin' ] + } + } + } +} + +export function getAliasConfig (root: string) { + return [ + { find: /^video.js$/, replacement: resolve(root, './node_modules/video.js/core.js') }, + { find: '@root-helpers', replacement: resolve(root, './src/root-helpers') } + ] +} diff --git a/client/src/standalone/player/package.json b/client/src/standalone/player/package.json new file mode 100644 index 000000000..940ccb746 --- /dev/null +++ b/client/src/standalone/player/package.json @@ -0,0 +1,31 @@ +{ + "name": "@peertube/player", + "private": false, + "version": "0.0.0", + "scripts": { + "build": "rm -rf ./build && ../../../node_modules/.bin/vite build --mode production --config ./vite.config.mjs", + "dev": "../../../node_modules/.bin/vite build --mode dev --watch --config ./vite.config.mjs" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Chocobozzz/PeerTube.git" + }, + "keywords": [ + "peertube", + "embed" + ], + "main": "./build/peertube-player.js", + "exports": { + ".": "./build/peertube-player.js" + }, + "types": "./src/index.ts", + "author": "Chocobozzz", + "license": "AGPL-3.0", + "type": "module", + "sideEffects": true, + "bugs": { + "url": "https://github.com/Chocobozzz/PeerTube/issues" + }, + "homepage": "https://github.com/Chocobozzz/PeerTube#readme", + "dependencies": {} +} diff --git a/client/src/standalone/player/src/index.ts b/client/src/standalone/player/src/index.ts new file mode 100644 index 000000000..66e3e1497 --- /dev/null +++ b/client/src/standalone/player/src/index.ts @@ -0,0 +1,5 @@ +export * from './peertube-player' +export * from './peertube-player-local-storage' +export * from './types' + +import './sass/player.scss' diff --git a/client/src/assets/player/peertube-player-local-storage.ts b/client/src/standalone/player/src/peertube-player-local-storage.ts similarity index 100% rename from client/src/assets/player/peertube-player-local-storage.ts rename to client/src/standalone/player/src/peertube-player-local-storage.ts diff --git a/client/src/assets/player/peertube-player.ts b/client/src/standalone/player/src/peertube-player.ts similarity index 99% rename from client/src/assets/player/peertube-player.ts rename to client/src/standalone/player/src/peertube-player.ts index 2c4108bbb..182eb47cc 100644 --- a/client/src/assets/player/peertube-player.ts +++ b/client/src/standalone/player/src/peertube-player.ts @@ -31,6 +31,8 @@ import './shared/metrics/metrics-plugin' import './shared/p2p-media-loader/hls-plugin' import './shared/p2p-media-loader/p2p-media-loader-plugin' import './shared/web-video/web-video-plugin' +import './shared/dock/peertube-dock-component' +import './shared/dock/peertube-dock-plugin' import videojs, { VideoJsPlayer } from 'video.js' import { logger } from '@root-helpers/logger' import { PluginsManager } from '@root-helpers/plugins-manager' @@ -40,7 +42,7 @@ import { isMobile } from '@root-helpers/web-browser' import { buildVideoLink, decorateVideoLink, isDefaultLocale, pick } from '@peertube/peertube-core-utils' import { saveAverageBandwidth } from './peertube-player-local-storage' import { ControlBarOptionsBuilder, HLSOptionsBuilder, WebVideoOptionsBuilder } from './shared/player-options-builder' -import { TranslationsManager } from './translations-manager' +import { TranslationsManager } from '@root-helpers/translations-manager' import { PeerTubePlayerConstructorOptions, PeerTubePlayerLoadOptions, PlayerNetworkInfo, VideoJSPluginOptions } from './types' // Change 'Playback Rate' to 'Speed' (smaller for our settings menu) diff --git a/client/src/standalone/player/src/sass/player.scss b/client/src/standalone/player/src/sass/player.scss new file mode 100644 index 000000000..30d2493bc --- /dev/null +++ b/client/src/standalone/player/src/sass/player.scss @@ -0,0 +1,2 @@ +@use '../../../node_modules/video.js/dist/video-js'; +@use './shared/index.scss'; diff --git a/client/src/sass/player/_player-variables.scss b/client/src/standalone/player/src/sass/shared/_player-variables.scss similarity index 93% rename from client/src/sass/player/_player-variables.scss rename to client/src/standalone/player/src/sass/shared/_player-variables.scss index 8691bf6b2..9e0f41363 100644 --- a/client/src/sass/player/_player-variables.scss +++ b/client/src/standalone/player/src/sass/shared/_player-variables.scss @@ -22,5 +22,3 @@ $control-bar-total-height: $control-bar-height - $control-bar-slider-top; $progress-margin: 10px; $dock-padding: 20px; - -$assets-path: '../../assets/' !default; diff --git a/client/src/sass/player/bezels.scss b/client/src/standalone/player/src/sass/shared/bezels.scss similarity index 100% rename from client/src/sass/player/bezels.scss rename to client/src/standalone/player/src/sass/shared/bezels.scss diff --git a/client/src/sass/player/context-menu.scss b/client/src/standalone/player/src/sass/shared/context-menu.scss similarity index 89% rename from client/src/sass/player/context-menu.scss rename to client/src/standalone/player/src/sass/shared/context-menu.scss index f5b051be2..84f5928d1 100644 --- a/client/src/sass/player/context-menu.scss +++ b/client/src/standalone/player/src/sass/shared/context-menu.scss @@ -50,8 +50,8 @@ $context-menu-width: 350px; @each $icon in $icons { &[class$="-#{$icon}"] { - mask-image: url('#{$assets-path}/player/images/#{$icon}.svg'); - -webkit-mask-image: url('#{$assets-path}/player/images/#{$icon}.svg'); + mask-image: url('./svg/#{$icon}.svg'); + -webkit-mask-image: url('./svg/#{$icon}.svg'); } } diff --git a/client/src/sass/player/control-bar.scss b/client/src/standalone/player/src/sass/shared/control-bar.scss similarity index 94% rename from client/src/sass/player/control-bar.scss rename to client/src/standalone/player/src/sass/shared/control-bar.scss index af54d0ccc..14d7b1c8b 100644 --- a/client/src/sass/player/control-bar.scss +++ b/client/src/standalone/player/src/sass/shared/control-bar.scss @@ -270,11 +270,11 @@ $chapter-marker-size: 9px; @include margin-right(2px); &.icon-download { - background-image: url('#{$assets-path}/player/images/arrow-down.svg'); + background-image: url('./svg/arrow-down.svg'); } &.icon-upload { - background-image: url('#{$assets-path}/player/images/arrow-up.svg'); + background-image: url('./svg/arrow-up.svg'); } } } @@ -291,8 +291,8 @@ $chapter-marker-size: 9px; .icon { &.icon-next, &.icon-previous { - mask-image: url('#{$assets-path}/player/images/next.svg'); - -webkit-mask-image: url('#{$assets-path}/player/images/next.svg'); + mask-image: url('./svg/next.svg'); + -webkit-mask-image: url('./svg/next.svg'); mask-size: cover; -webkit-mask-size: cover; @@ -319,7 +319,7 @@ $chapter-marker-size: 9px; width: $control-bar-icon-size; height: $control-bar-icon-size; vertical-align: middle; - background: url('#{$assets-path}/player/images/volume.svg') no-repeat; + background: url('./svg/volume.svg') no-repeat; background-size: contain; &::before { @@ -328,7 +328,7 @@ $chapter-marker-size: 9px; } &.vjs-vol-0 .vjs-icon-placeholder { - background: url('#{$assets-path}/player/images/volume-mute.svg') no-repeat; + background: url('./svg/volume-mute.svg') no-repeat; background-size: contain; } } @@ -415,7 +415,7 @@ $chapter-marker-size: 9px; height: $control-bar-icon-size - 4px; width: $control-bar-icon-size - 4px; vertical-align: middle; - background: url('#{$assets-path}/player/images/settings.svg') no-repeat; + background: url('./svg/settings.svg') no-repeat; background-size: contain; &::before { @@ -448,7 +448,7 @@ $chapter-marker-size: 9px; width: $control-bar-icon-size - 4px; height: $control-bar-icon-size - 4px; vertical-align: middle; - background: url('#{$assets-path}/player/images/theater.svg') no-repeat; + background: url('./svg/theater.svg') no-repeat; background-size: contain; &::before { @@ -493,7 +493,7 @@ $chapter-marker-size: 9px; width: $control-bar-icon-size; height: $control-bar-icon-size; vertical-align: middle; - background: url('#{$assets-path}/player/images/fullscreen.svg') no-repeat; + background: url('./svg/fullscreen.svg') no-repeat; background-size: contain; &::before { @@ -515,14 +515,6 @@ $chapter-marker-size: 9px; .vjs-theater-control { display: none; } - - .vjs-peertube { - .icon, - .download-speed-text, - .upload-speed-text { - display: none !important; - } - } } .video-js.vjs-peertube-skin.vjs-size-570 .vjs-control-bar { @@ -540,6 +532,12 @@ $chapter-marker-size: 9px; .vjs-peertube-displayed { display: none !important; } + + .icon, + .download-speed-text, + .upload-speed-text { + display: none !important; + } } .vjs-peertube-link { diff --git a/client/src/sass/player/dock.scss b/client/src/standalone/player/src/sass/shared/dock.scss similarity index 100% rename from client/src/sass/player/dock.scss rename to client/src/standalone/player/src/sass/shared/dock.scss diff --git a/client/src/sass/player/index.scss b/client/src/standalone/player/src/sass/shared/index.scss similarity index 100% rename from client/src/sass/player/index.scss rename to client/src/standalone/player/src/sass/shared/index.scss diff --git a/client/src/sass/player/mobile.scss b/client/src/standalone/player/src/sass/shared/mobile.scss similarity index 100% rename from client/src/sass/player/mobile.scss rename to client/src/standalone/player/src/sass/shared/mobile.scss diff --git a/client/src/sass/player/offline-notification.scss b/client/src/standalone/player/src/sass/shared/offline-notification.scss similarity index 100% rename from client/src/sass/player/offline-notification.scss rename to client/src/standalone/player/src/sass/shared/offline-notification.scss diff --git a/client/src/sass/player/peertube-skin.scss b/client/src/standalone/player/src/sass/shared/peertube-skin.scss similarity index 98% rename from client/src/sass/player/peertube-skin.scss rename to client/src/standalone/player/src/sass/shared/peertube-skin.scss index ea9f3e335..381bde83a 100644 --- a/client/src/sass/player/peertube-skin.scss +++ b/client/src/standalone/player/src/sass/shared/peertube-skin.scss @@ -60,7 +60,7 @@ body { .vjs-icon-placeholder::before { content: ''; - background-image: url('#{$assets-path}/player/images/big-play-button.svg'); + background-image: url('./svg/big-play-button.svg'); @include big-play-button-triangle-size(45px); } diff --git a/client/src/sass/player/playlist.scss b/client/src/standalone/player/src/sass/shared/playlist.scss similarity index 91% rename from client/src/sass/player/playlist.scss rename to client/src/standalone/player/src/sass/shared/playlist.scss index c3e571b00..f39a8463b 100644 --- a/client/src/sass/player/playlist.scss +++ b/client/src/standalone/player/src/sass/shared/playlist.scss @@ -44,8 +44,8 @@ $playlist-menu-width: 350px; } .cross { - mask-image: url('#{$assets-path}/images/feather/x.svg'); - -webkit-mask-image: url('#{$assets-path}/images/feather/x.svg'); + mask-image: url('./svg/x.svg'); + -webkit-mask-image: url('./svg/x.svg'); mask-size: cover; -webkit-mask-size: cover; @@ -92,8 +92,8 @@ $playlist-menu-width: 350px; } .vjs-playlist-icon { - mask-image: url('#{$assets-path}/images/feather/playlists.svg'); - -webkit-mask-image: url('#{$assets-path}/images/feather/playlists.svg'); + mask-image: url('./svg/playlists.svg'); + -webkit-mask-image: url('./svg/playlists.svg'); mask-size: cover; -webkit-mask-size: cover; diff --git a/client/src/sass/player/settings-menu.scss b/client/src/standalone/player/src/sass/shared/settings-menu.scss similarity index 97% rename from client/src/sass/player/settings-menu.scss rename to client/src/standalone/player/src/sass/shared/settings-menu.scss index d2095e85b..0353c0b31 100644 --- a/client/src/sass/player/settings-menu.scss +++ b/client/src/standalone/player/src/sass/shared/settings-menu.scss @@ -145,7 +145,7 @@ $setting-transition-easing: ease-out; position: absolute; content: ' '; margin-top: 1px; - background-image: url('#{$assets-path}/player/images/tick-white.svg'); + background-image: url('./svg/tick-white.svg'); @include icon(15px); @include left(15px); diff --git a/client/src/sass/player/spinner.scss b/client/src/standalone/player/src/sass/shared/spinner.scss similarity index 100% rename from client/src/sass/player/spinner.scss rename to client/src/standalone/player/src/sass/shared/spinner.scss diff --git a/client/src/sass/player/stats.scss b/client/src/standalone/player/src/sass/shared/stats.scss similarity index 100% rename from client/src/sass/player/stats.scss rename to client/src/standalone/player/src/sass/shared/stats.scss diff --git a/client/src/sass/player/storyboard.scss b/client/src/standalone/player/src/sass/shared/storyboard.scss similarity index 100% rename from client/src/sass/player/storyboard.scss rename to client/src/standalone/player/src/sass/shared/storyboard.scss diff --git a/client/src/sass/player/upnext.scss b/client/src/standalone/player/src/sass/shared/upnext.scss similarity index 100% rename from client/src/sass/player/upnext.scss rename to client/src/standalone/player/src/sass/shared/upnext.scss diff --git a/client/src/assets/player/images/arrow-down.svg b/client/src/standalone/player/src/sass/svg/arrow-down.svg similarity index 100% rename from client/src/assets/player/images/arrow-down.svg rename to client/src/standalone/player/src/sass/svg/arrow-down.svg diff --git a/client/src/assets/player/images/arrow-up.svg b/client/src/standalone/player/src/sass/svg/arrow-up.svg similarity index 100% rename from client/src/assets/player/images/arrow-up.svg rename to client/src/standalone/player/src/sass/svg/arrow-up.svg diff --git a/client/src/assets/player/images/big-play-button.svg b/client/src/standalone/player/src/sass/svg/big-play-button.svg similarity index 100% rename from client/src/assets/player/images/big-play-button.svg rename to client/src/standalone/player/src/sass/svg/big-play-button.svg diff --git a/client/src/assets/player/images/code.svg b/client/src/standalone/player/src/sass/svg/code.svg similarity index 100% rename from client/src/assets/player/images/code.svg rename to client/src/standalone/player/src/sass/svg/code.svg diff --git a/client/src/assets/player/images/fullscreen.svg b/client/src/standalone/player/src/sass/svg/fullscreen.svg similarity index 100% rename from client/src/assets/player/images/fullscreen.svg rename to client/src/standalone/player/src/sass/svg/fullscreen.svg diff --git a/client/src/assets/player/images/info.svg b/client/src/standalone/player/src/sass/svg/info.svg similarity index 100% rename from client/src/assets/player/images/info.svg rename to client/src/standalone/player/src/sass/svg/info.svg diff --git a/client/src/assets/player/images/link-2.svg b/client/src/standalone/player/src/sass/svg/link-2.svg similarity index 100% rename from client/src/assets/player/images/link-2.svg rename to client/src/standalone/player/src/sass/svg/link-2.svg diff --git a/client/src/assets/player/images/next.svg b/client/src/standalone/player/src/sass/svg/next.svg similarity index 100% rename from client/src/assets/player/images/next.svg rename to client/src/standalone/player/src/sass/svg/next.svg diff --git a/client/src/standalone/player/src/sass/svg/playlists.svg b/client/src/standalone/player/src/sass/svg/playlists.svg new file mode 100644 index 000000000..247c073f0 --- /dev/null +++ b/client/src/standalone/player/src/sass/svg/playlists.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + diff --git a/client/src/assets/player/images/repeat.svg b/client/src/standalone/player/src/sass/svg/repeat.svg similarity index 100% rename from client/src/assets/player/images/repeat.svg rename to client/src/standalone/player/src/sass/svg/repeat.svg diff --git a/client/src/assets/player/images/settings.svg b/client/src/standalone/player/src/sass/svg/settings.svg similarity index 100% rename from client/src/assets/player/images/settings.svg rename to client/src/standalone/player/src/sass/svg/settings.svg diff --git a/client/src/assets/player/images/theater.svg b/client/src/standalone/player/src/sass/svg/theater.svg similarity index 100% rename from client/src/assets/player/images/theater.svg rename to client/src/standalone/player/src/sass/svg/theater.svg diff --git a/client/src/assets/player/images/tick-white.svg b/client/src/standalone/player/src/sass/svg/tick-white.svg similarity index 100% rename from client/src/assets/player/images/tick-white.svg rename to client/src/standalone/player/src/sass/svg/tick-white.svg diff --git a/client/src/assets/player/images/volume-mute.svg b/client/src/standalone/player/src/sass/svg/volume-mute.svg similarity index 100% rename from client/src/assets/player/images/volume-mute.svg rename to client/src/standalone/player/src/sass/svg/volume-mute.svg diff --git a/client/src/assets/player/images/volume.svg b/client/src/standalone/player/src/sass/svg/volume.svg similarity index 100% rename from client/src/assets/player/images/volume.svg rename to client/src/standalone/player/src/sass/svg/volume.svg diff --git a/client/src/standalone/player/src/sass/svg/x.svg b/client/src/standalone/player/src/sass/svg/x.svg new file mode 100644 index 000000000..7d5875ca8 --- /dev/null +++ b/client/src/standalone/player/src/sass/svg/x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/assets/player/shared/bezels/bezels-plugin.ts b/client/src/standalone/player/src/shared/bezels/bezels-plugin.ts similarity index 100% rename from client/src/assets/player/shared/bezels/bezels-plugin.ts rename to client/src/standalone/player/src/shared/bezels/bezels-plugin.ts diff --git a/client/src/assets/player/shared/bezels/index.ts b/client/src/standalone/player/src/shared/bezels/index.ts similarity index 100% rename from client/src/assets/player/shared/bezels/index.ts rename to client/src/standalone/player/src/shared/bezels/index.ts diff --git a/client/src/assets/player/shared/bezels/pause-bezel.ts b/client/src/standalone/player/src/shared/bezels/pause-bezel.ts similarity index 100% rename from client/src/assets/player/shared/bezels/pause-bezel.ts rename to client/src/standalone/player/src/shared/bezels/pause-bezel.ts diff --git a/client/src/assets/player/shared/common/index.ts b/client/src/standalone/player/src/shared/common/index.ts similarity index 100% rename from client/src/assets/player/shared/common/index.ts rename to client/src/standalone/player/src/shared/common/index.ts diff --git a/client/src/assets/player/shared/common/utils.ts b/client/src/standalone/player/src/shared/common/utils.ts similarity index 100% rename from client/src/assets/player/shared/common/utils.ts rename to client/src/standalone/player/src/shared/common/utils.ts diff --git a/client/src/assets/player/shared/context-menu/context-menu-item.ts b/client/src/standalone/player/src/shared/context-menu/context-menu-item.ts similarity index 100% rename from client/src/assets/player/shared/context-menu/context-menu-item.ts rename to client/src/standalone/player/src/shared/context-menu/context-menu-item.ts diff --git a/client/src/assets/player/shared/context-menu/context-menu-plugin.ts b/client/src/standalone/player/src/shared/context-menu/context-menu-plugin.ts similarity index 100% rename from client/src/assets/player/shared/context-menu/context-menu-plugin.ts rename to client/src/standalone/player/src/shared/context-menu/context-menu-plugin.ts diff --git a/client/src/assets/player/shared/context-menu/context-menu.ts b/client/src/standalone/player/src/shared/context-menu/context-menu.ts similarity index 100% rename from client/src/assets/player/shared/context-menu/context-menu.ts rename to client/src/standalone/player/src/shared/context-menu/context-menu.ts diff --git a/client/src/assets/player/shared/context-menu/index.ts b/client/src/standalone/player/src/shared/context-menu/index.ts similarity index 100% rename from client/src/assets/player/shared/context-menu/index.ts rename to client/src/standalone/player/src/shared/context-menu/index.ts diff --git a/client/src/assets/player/shared/context-menu/util.ts b/client/src/standalone/player/src/shared/context-menu/util.ts similarity index 100% rename from client/src/assets/player/shared/context-menu/util.ts rename to client/src/standalone/player/src/shared/context-menu/util.ts diff --git a/client/src/assets/player/shared/control-bar/caption-toggle-button.ts b/client/src/standalone/player/src/shared/control-bar/caption-toggle-button.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/caption-toggle-button.ts rename to client/src/standalone/player/src/shared/control-bar/caption-toggle-button.ts diff --git a/client/src/assets/player/shared/control-bar/chapters-plugin.ts b/client/src/standalone/player/src/shared/control-bar/chapters-plugin.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/chapters-plugin.ts rename to client/src/standalone/player/src/shared/control-bar/chapters-plugin.ts diff --git a/client/src/assets/player/shared/control-bar/index.ts b/client/src/standalone/player/src/shared/control-bar/index.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/index.ts rename to client/src/standalone/player/src/shared/control-bar/index.ts diff --git a/client/src/assets/player/shared/control-bar/next-previous-video-button.ts b/client/src/standalone/player/src/shared/control-bar/next-previous-video-button.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/next-previous-video-button.ts rename to client/src/standalone/player/src/shared/control-bar/next-previous-video-button.ts diff --git a/client/src/assets/player/shared/control-bar/p2p-info-button.ts b/client/src/standalone/player/src/shared/control-bar/p2p-info-button.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/p2p-info-button.ts rename to client/src/standalone/player/src/shared/control-bar/p2p-info-button.ts diff --git a/client/src/assets/player/shared/control-bar/peertube-link-button.ts b/client/src/standalone/player/src/shared/control-bar/peertube-link-button.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/peertube-link-button.ts rename to client/src/standalone/player/src/shared/control-bar/peertube-link-button.ts diff --git a/client/src/assets/player/shared/control-bar/peertube-live-display.ts b/client/src/standalone/player/src/shared/control-bar/peertube-live-display.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/peertube-live-display.ts rename to client/src/standalone/player/src/shared/control-bar/peertube-live-display.ts diff --git a/client/src/assets/player/shared/control-bar/progress-bar-marker-component.ts b/client/src/standalone/player/src/shared/control-bar/progress-bar-marker-component.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/progress-bar-marker-component.ts rename to client/src/standalone/player/src/shared/control-bar/progress-bar-marker-component.ts diff --git a/client/src/assets/player/shared/control-bar/storyboard-plugin.ts b/client/src/standalone/player/src/shared/control-bar/storyboard-plugin.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/storyboard-plugin.ts rename to client/src/standalone/player/src/shared/control-bar/storyboard-plugin.ts diff --git a/client/src/assets/player/shared/control-bar/theater-button.ts b/client/src/standalone/player/src/shared/control-bar/theater-button.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/theater-button.ts rename to client/src/standalone/player/src/shared/control-bar/theater-button.ts diff --git a/client/src/assets/player/shared/control-bar/time-tooltip.ts b/client/src/standalone/player/src/shared/control-bar/time-tooltip.ts similarity index 100% rename from client/src/assets/player/shared/control-bar/time-tooltip.ts rename to client/src/standalone/player/src/shared/control-bar/time-tooltip.ts diff --git a/client/src/assets/player/shared/dock/index.ts b/client/src/standalone/player/src/shared/dock/index.ts similarity index 100% rename from client/src/assets/player/shared/dock/index.ts rename to client/src/standalone/player/src/shared/dock/index.ts diff --git a/client/src/assets/player/shared/dock/peertube-dock-component.ts b/client/src/standalone/player/src/shared/dock/peertube-dock-component.ts similarity index 100% rename from client/src/assets/player/shared/dock/peertube-dock-component.ts rename to client/src/standalone/player/src/shared/dock/peertube-dock-component.ts diff --git a/client/src/assets/player/shared/dock/peertube-dock-plugin.ts b/client/src/standalone/player/src/shared/dock/peertube-dock-plugin.ts similarity index 100% rename from client/src/assets/player/shared/dock/peertube-dock-plugin.ts rename to client/src/standalone/player/src/shared/dock/peertube-dock-plugin.ts diff --git a/client/src/assets/player/shared/hotkeys/index.ts b/client/src/standalone/player/src/shared/hotkeys/index.ts similarity index 100% rename from client/src/assets/player/shared/hotkeys/index.ts rename to client/src/standalone/player/src/shared/hotkeys/index.ts diff --git a/client/src/assets/player/shared/hotkeys/peertube-hotkeys-plugin.ts b/client/src/standalone/player/src/shared/hotkeys/peertube-hotkeys-plugin.ts similarity index 100% rename from client/src/assets/player/shared/hotkeys/peertube-hotkeys-plugin.ts rename to client/src/standalone/player/src/shared/hotkeys/peertube-hotkeys-plugin.ts diff --git a/client/src/assets/player/shared/metrics/index.ts b/client/src/standalone/player/src/shared/metrics/index.ts similarity index 100% rename from client/src/assets/player/shared/metrics/index.ts rename to client/src/standalone/player/src/shared/metrics/index.ts diff --git a/client/src/assets/player/shared/metrics/metrics-plugin.ts b/client/src/standalone/player/src/shared/metrics/metrics-plugin.ts similarity index 100% rename from client/src/assets/player/shared/metrics/metrics-plugin.ts rename to client/src/standalone/player/src/shared/metrics/metrics-plugin.ts diff --git a/client/src/assets/player/shared/mobile/index.ts b/client/src/standalone/player/src/shared/mobile/index.ts similarity index 100% rename from client/src/assets/player/shared/mobile/index.ts rename to client/src/standalone/player/src/shared/mobile/index.ts diff --git a/client/src/assets/player/shared/mobile/peertube-mobile-buttons.ts b/client/src/standalone/player/src/shared/mobile/peertube-mobile-buttons.ts similarity index 100% rename from client/src/assets/player/shared/mobile/peertube-mobile-buttons.ts rename to client/src/standalone/player/src/shared/mobile/peertube-mobile-buttons.ts diff --git a/client/src/assets/player/shared/mobile/peertube-mobile-plugin.ts b/client/src/standalone/player/src/shared/mobile/peertube-mobile-plugin.ts similarity index 100% rename from client/src/assets/player/shared/mobile/peertube-mobile-plugin.ts rename to client/src/standalone/player/src/shared/mobile/peertube-mobile-plugin.ts diff --git a/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts b/client/src/standalone/player/src/shared/p2p-media-loader/hls-plugin.ts similarity index 95% rename from client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts rename to client/src/standalone/player/src/shared/p2p-media-loader/hls-plugin.ts index fd5fb2525..0bd34f8df 100644 --- a/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts +++ b/client/src/standalone/player/src/shared/p2p-media-loader/hls-plugin.ts @@ -5,6 +5,10 @@ import { logger } from '@root-helpers/logger' import Hlsjs, { ErrorData, Level, LevelSwitchingData, ManifestParsedData } from 'hls.js' import videojs from 'video.js' import { HLSPluginOptions, HlsjsConfigHandlerOptions, PeerTubeResolution, VideoJSTechHLS } from '../../types' +import { HlsJsP2PEngine, HlsWithP2PInstance } from 'p2p-media-loader-hlsjs' +import { omit } from '@peertube/peertube-core-utils' + +const HlsWithP2P = HlsJsP2PEngine.injectMixin(Hlsjs) type ErrorCounts = { [ type: string ]: number @@ -14,8 +18,6 @@ type ErrorCounts = { // Source handler registration // --------------------------------------------------------------------------- -type HookFn = (player: videojs.Player, hljs: Hlsjs) => void - let alreadyRegistered = false const registerSourceHandler = function (vjs: typeof videojs) { @@ -110,8 +112,6 @@ videojs.registerPlugin('hlsjs', HLSJSConfigHandler) // --------------------------------------------------------------------------- export class Html5Hlsjs { - private static hooks: { [id: string]: HookFn[] } = {} - private readonly videoElement: HTMLVideoElement private readonly errorCounts: ErrorCounts = {} private readonly player: videojs.Player @@ -121,7 +121,7 @@ export class Html5Hlsjs { private maxNetworkErrorRecovery = 5 - private hls: Hlsjs + private hls: HlsWithP2PInstance private hlsjsConfig: HLSPluginOptions = null private _duration: number = null @@ -410,10 +410,15 @@ export class Html5Hlsjs { this.videoElement.addEventListener('play', this.handlers.play) } - const loader = this.hlsjsConfig.loaderBuilder() - this.hls = new Hlsjs({ ...this.hlsjsConfig, loader }) + this.hls = new HlsWithP2P({ + ...omit(this.hlsjsConfig, [ 'p2pMediaLoaderOptions' ]), - this.player.trigger('hlsjs-initialized', { hlsjs: this.hls, engine: loader.getEngine() }) + p2p: { + core: this.hlsjsConfig.p2pMediaLoaderOptions + } + }) + + this.player.trigger('hlsjs-initialized', { hlsjs: this.hls }) this.hls.on(Hlsjs.Events.ERROR, (event, data) => this._onError(event, data)) this.hls.on(Hlsjs.Events.MANIFEST_PARSED, (event, data) => this._onMetaData(event, data)) @@ -462,17 +467,21 @@ export class Html5Hlsjs { this.hlsjsConfig.autoStartLoad = true this.player.autoplay('play') - const loader = this.hlsjsConfig.loaderBuilder() - this.hls = new Hlsjs({ - ...this.hlsjsConfig, - loader, + this.hls = new HlsWithP2P({ + ...omit(this.hlsjsConfig, [ 'p2pMediaLoaderOptions' ]), + + p2p: { + core: this.hlsjsConfig.p2pMediaLoaderOptions + }, + startPosition: this.duration() === Infinity ? undefined : currentTime, + startLevel }) - this.player.trigger('hlsjs-initialized', { hlsjs: this.hls, engine: loader.getEngine() }) + this.player.trigger('hlsjs-initialized', { hlsjs: this.hls }) this.hls.on(Hlsjs.Events.ERROR, (event, data) => this._onError(event, data)) this.registerLevelEventSwitch() diff --git a/client/src/assets/player/shared/p2p-media-loader/index.ts b/client/src/standalone/player/src/shared/p2p-media-loader/index.ts similarity index 100% rename from client/src/assets/player/shared/p2p-media-loader/index.ts rename to client/src/standalone/player/src/shared/p2p-media-loader/index.ts diff --git a/client/src/assets/player/shared/p2p-media-loader/p2p-media-loader-plugin.ts b/client/src/standalone/player/src/shared/p2p-media-loader/p2p-media-loader-plugin.ts similarity index 74% rename from client/src/assets/player/shared/p2p-media-loader/p2p-media-loader-plugin.ts rename to client/src/standalone/player/src/shared/p2p-media-loader/p2p-media-loader-plugin.ts index abcbd2261..07a038722 100644 --- a/client/src/assets/player/shared/p2p-media-loader/p2p-media-loader-plugin.ts +++ b/client/src/standalone/player/src/shared/p2p-media-loader/p2p-media-loader-plugin.ts @@ -1,9 +1,9 @@ -import { Events, Segment } from '@peertube/p2p-media-loader-core' -import { Engine, initHlsJsPlayer } from '@peertube/p2p-media-loader-hlsjs' import { addQueryParams } from '@peertube/peertube-core-utils' import { logger } from '@root-helpers/logger' import debug from 'debug' -import Hlsjs from 'hls.js' +import { FragLoadedData, default as Hlsjs } from 'hls.js' +import type { DownloadSource, SegmentErrorDetails, SegmentLoadDetails } from 'p2p-media-loader-core' +import type { HlsWithP2PInstance } from 'p2p-media-loader-hlsjs' import videojs from 'video.js' import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../../types' import { SettingsButton } from '../settings/settings-menu-button' @@ -14,8 +14,7 @@ const Plugin = videojs.getPlugin('plugin') class P2pMediaLoaderPlugin extends Plugin { declare private readonly options: P2PMediaLoaderPluginOptions - declare private hlsjs: Hlsjs - declare private p2pEngine: Engine + declare private hlsjs: HlsWithP2PInstance declare private statsP2PBytes: { pendingDownload: number[] pendingUpload: number[] @@ -33,6 +32,9 @@ class P2pMediaLoaderPlugin extends Plugin { declare private liveEnded: boolean + declare private connectedPeers: Set + declare private totalHTTPPeers: number + constructor (player: videojs.Player, options?: P2PMediaLoaderPluginOptions) { super(player) @@ -76,15 +78,13 @@ class P2pMediaLoaderPlugin extends Plugin { } { - const onHLSJSInitialized = (_: any, { hlsjs, engine }: { hlsjs: Hlsjs, engine: Engine }) => { - this.p2pEngine?.removeAllListeners() - this.p2pEngine?.destroy() + const onHLSJSInitialized = (_: any, { hlsjs }: { hlsjs: HlsWithP2PInstance }) => { + this.hlsjs?.p2pEngine?.destroy() clearInterval(this.networkInfoInterval) this.hlsjs = hlsjs - this.p2pEngine = engine - debugLogger('hls.js initialized, initializing p2p-media-loader plugin', { hlsjs, engine }) + debugLogger('hls.js initialized, initializing p2p-media-loader plugin', { hlsjs }) player.ready(() => this.initializePlugin()) } @@ -116,8 +116,7 @@ class P2pMediaLoaderPlugin extends Plugin { } dispose () { - this.p2pEngine?.removeAllListeners() - this.p2pEngine?.destroy() + this.hlsjs?.p2pEngine?.destroy() this.hlsjs?.destroy() this.options.segmentValidator?.destroy() @@ -152,15 +151,22 @@ class P2pMediaLoaderPlugin extends Plugin { } private initializePlugin () { - initHlsJsPlayer(this.player, this.hlsjs) + this.hlsjs.p2pEngine.addEventListener('onSegmentError', (details: SegmentErrorDetails) => { + if (navigator.onLine === false || this.liveEnded || details.downloadSource !== 'http') return - this.p2pEngine.on(Events.SegmentError, (segment: Segment, err) => { - if (navigator.onLine === false || this.liveEnded) return - - logger.clientError(`Segment ${segment.id} error.`, err) + const segment = details.segment + logger.clientError(`Segment ${segment.runtimeId} error.`, details) if (this.options.redundancyUrlManager) { - this.options.redundancyUrlManager.removeBySegmentUrl(segment.requestUrl) + this.options.redundancyUrlManager.onSegmentError(segment.url) + } + }) + + this.hlsjs.p2pEngine.addEventListener('onSegmentLoaded', (details: SegmentLoadDetails) => { + if (details.downloadSource !== 'http') return + + if (this.options.redundancyUrlManager) { + this.options.redundancyUrlManager.onSegmentSuccess(details.segmentUrl) } }) @@ -168,7 +174,8 @@ class P2pMediaLoaderPlugin extends Plugin { ? this.options.redundancyUrlManager.countBaseUrls() : 0 - this.statsP2PBytes.peersWithWebSeed = 1 + redundancyUrlsCount + this.totalHTTPPeers = 1 + redundancyUrlsCount + this.statsP2PBytes.peersWithWebSeed = this.totalHTTPPeers this.runStats() @@ -200,30 +207,44 @@ class P2pMediaLoaderPlugin extends Plugin { } private runStats () { - this.p2pEngine.on(Events.PieceBytesDownloaded, (method: string, _segment, bytes: number) => { + this.connectedPeers = new Set() + + if (this.hlsjs.p2pEngine.getConfig().core.mainStream.isP2PDisabled) { + this.hlsjs.on(Hlsjs.Events.FRAG_LOADED, (e, data: FragLoadedData) => { + const bytes = data.frag.stats.loaded + + this.statsHTTPBytes.pendingDownload.push(bytes) + this.statsHTTPBytes.totalDownload += bytes + }) + } + + this.hlsjs.p2pEngine.addEventListener('onChunkDownloaded', (bytes: number, method: DownloadSource) => { const elem = method === 'p2p' ? this.statsP2PBytes : this.statsHTTPBytes elem.pendingDownload.push(bytes) elem.totalDownload += bytes }) - this.p2pEngine.on(Events.PieceBytesUploaded, (method: string, _segment, bytes: number) => { - if (method !== 'p2p') { - logger.error(`Received upload from unknown method ${method}`) - return - } - + this.hlsjs.p2pEngine.addEventListener('onChunkUploaded', (bytes: number) => { this.statsP2PBytes.pendingUpload.push(bytes) this.statsP2PBytes.totalUpload += bytes }) - this.p2pEngine.on(Events.PeerConnect, () => { - this.statsP2PBytes.peersWithWebSeed++ - this.statsP2PBytes.peersP2POnly++ + this.hlsjs.p2pEngine.addEventListener('onPeerConnect', peer => { + if (peer.streamType !== 'main') return + + this.connectedPeers.add(peer.peerId) + this.statsP2PBytes.peersP2POnly = this.connectedPeers.size + + this.statsP2PBytes.peersWithWebSeed = this.totalHTTPPeers + this.statsP2PBytes.peersP2POnly }) - this.p2pEngine.on(Events.PeerClose, () => { - this.statsP2PBytes.peersWithWebSeed-- - this.statsP2PBytes.peersP2POnly-- + this.hlsjs.p2pEngine.addEventListener('onPeerClose', peer => { + if (peer.streamType !== 'main') return + + this.connectedPeers.delete(peer.peerId) + this.statsP2PBytes.peersP2POnly = this.connectedPeers.size + + this.statsP2PBytes.peersWithWebSeed = this.totalHTTPPeers + this.statsP2PBytes.peersP2POnly }) this.networkInfoInterval = setInterval(() => { diff --git a/client/src/assets/player/shared/p2p-media-loader/redundancy-url-manager.ts b/client/src/standalone/player/src/shared/p2p-media-loader/redundancy-url-manager.ts similarity index 67% rename from client/src/assets/player/shared/p2p-media-loader/redundancy-url-manager.ts rename to client/src/standalone/player/src/shared/p2p-media-loader/redundancy-url-manager.ts index ab051ca44..ec7a219b7 100644 --- a/client/src/assets/player/shared/p2p-media-loader/redundancy-url-manager.ts +++ b/client/src/standalone/player/src/shared/p2p-media-loader/redundancy-url-manager.ts @@ -1,22 +1,32 @@ import { logger } from '@root-helpers/logger' class RedundancyUrlManager { + private map = new Map() constructor (private baseUrls: string[] = []) { // empty } - removeBySegmentUrl (segmentUrl: string) { - const baseUrl = getBaseUrl(segmentUrl) + onSegmentError (segmentUrl: string) { + if (!this.map.has(segmentUrl)) return + + const customSegmentUrl = this.map.get(segmentUrl) + this.map.delete(segmentUrl) + + const baseUrl = getBaseUrl(customSegmentUrl) const oldLength = baseUrl.length this.baseUrls = this.baseUrls.filter(u => u !== baseUrl && u !== baseUrl + '/') if (oldLength !== this.baseUrls.length) { - logger.info(`Removed redundancy of segment URL ${segmentUrl}.`) + logger.info(`Removed redundancy of segment URL ${customSegmentUrl}.`) } } + onSegmentSuccess (segmentUrl: string) { + this.map.delete(segmentUrl) + } + buildUrl (url: string) { const max = this.baseUrls.length + 1 const i = this.getRandomInt(max) @@ -26,7 +36,11 @@ class RedundancyUrlManager { const newBaseUrl = this.baseUrls[i] const slashPart = newBaseUrl.endsWith('/') ? '' : '/' - return newBaseUrl + slashPart + getFilename(url) + const newUrl = newBaseUrl + slashPart + getFilename(url) + + this.map.set(url, newUrl) + + return newUrl } countBaseUrls () { diff --git a/client/src/assets/player/shared/p2p-media-loader/segment-url-builder.ts b/client/src/standalone/player/src/shared/p2p-media-loader/segment-url-builder.ts similarity index 84% rename from client/src/assets/player/shared/p2p-media-loader/segment-url-builder.ts rename to client/src/standalone/player/src/shared/p2p-media-loader/segment-url-builder.ts index 8875e5353..6bfd97ca6 100644 --- a/client/src/assets/player/shared/p2p-media-loader/segment-url-builder.ts +++ b/client/src/standalone/player/src/shared/p2p-media-loader/segment-url-builder.ts @@ -1,4 +1,4 @@ -import { Segment } from '@peertube/p2p-media-loader-core' +import type { Segment } from 'p2p-media-loader-core' import { RedundancyUrlManager } from './redundancy-url-manager' export function segmentUrlBuilderFactory (redundancyUrlManager: RedundancyUrlManager | null) { diff --git a/client/src/assets/player/shared/p2p-media-loader/segment-validator.ts b/client/src/standalone/player/src/shared/p2p-media-loader/segment-validator.ts similarity index 76% rename from client/src/assets/player/shared/p2p-media-loader/segment-validator.ts rename to client/src/standalone/player/src/shared/p2p-media-loader/segment-validator.ts index e5f663117..d88ba5ebc 100644 --- a/client/src/assets/player/shared/p2p-media-loader/segment-validator.ts +++ b/client/src/standalone/player/src/shared/p2p-media-loader/segment-validator.ts @@ -1,9 +1,9 @@ -import { Segment } from '@peertube/p2p-media-loader-core' +import type { ByteRange } from 'p2p-media-loader-core' +import { removeQueryParams } from '@peertube/peertube-core-utils' import { logger } from '@root-helpers/logger' import { wait } from '@root-helpers/utils' -import { removeQueryParams } from '@peertube/peertube-core-utils' -import { isSameOrigin } from '../common' import debug from 'debug' +import { isSameOrigin } from '../common' const debugLogger = debug('peertube:player:segment-validator') @@ -12,9 +12,6 @@ type SegmentsJSON = { [filename: string]: string | { [byterange: string]: string const maxRetries = 10 export class SegmentValidator { - - private readonly bytesRangeRegex = /bytes=(\d+)-(\d+)/ - private destroyed = false private segmentJSONPromise: Promise @@ -29,17 +26,18 @@ export class SegmentValidator { }) { } - async validate (segment: Segment, _method: string, _peerId: string, retry = 1) { - if (this.destroyed) return + async validate (url: string, byteRange: ByteRange | undefined, data: ArrayBuffer, retry = 1): Promise { + if (this.destroyed) return false this.loadSha256SegmentsPromiseIfNeeded() - const filename = removeQueryParams(segment.url).split('/').pop() + const filename = removeQueryParams(url).split('/').pop() const segmentValue = (await this.segmentJSONPromise)[filename] if (!segmentValue && retry > maxRetries) { - throw new Error(`Unknown segment name ${filename} in segment validator`) + logger.clientError(`Unknown segment name ${filename} in segment validator`) + return false } if (!segmentValue) { @@ -49,9 +47,7 @@ export class SegmentValidator { this.loadSha256SegmentsPromise() - await this.validate(segment, _method, _peerId, retry + 1) - - return + return this.validate(url, byteRange, data, retry + 1) } let hashShouldBe: string @@ -60,24 +56,25 @@ export class SegmentValidator { if (typeof segmentValue === 'string') { hashShouldBe = segmentValue } else { - const captured = this.bytesRangeRegex.exec(segment.range) - range = captured[1] + '-' + captured[2] + range = byteRange.start + '-' + byteRange.end hashShouldBe = segmentValue[range] } if (hashShouldBe === undefined) { - throw new Error(`Unknown segment name ${filename}/${range} in segment validator`) + logger.clientError(`Unknown segment name ${filename}/${range} in segment validator`) + return false } - debugLogger(`Validating ${filename}` + (segment.range ? ` range ${segment.range}` : '')) + debugLogger(`Validating ${filename}` + (range ? ` range ${range}` : '')) - const calculatedSha = await this.sha256Hex(segment.data) + const calculatedSha = await this.sha256Hex(data) if (calculatedSha !== hashShouldBe) { - throw new Error( - `Hashes does not correspond for segment ${filename}/${range}` + - `(expected: ${hashShouldBe} instead of ${calculatedSha})` + logger.clientError( + `Hashes does not correspond for segment ${filename}/${range} (expected: ${hashShouldBe} instead of ${calculatedSha})` ) + + return true } } @@ -106,7 +103,7 @@ export class SegmentValidator { return fetch(this.options.segmentsSha256Url, { headers }) .then(res => res.json() as Promise) .catch(err => { - logger.error('Cannot get sha256 segments', err) + logger.clientError('Cannot get sha256 segments', err) return {} }) } diff --git a/client/src/assets/player/shared/peertube/index.ts b/client/src/standalone/player/src/shared/peertube/index.ts similarity index 100% rename from client/src/assets/player/shared/peertube/index.ts rename to client/src/standalone/player/src/shared/peertube/index.ts diff --git a/client/src/assets/player/shared/peertube/peertube-plugin.ts b/client/src/standalone/player/src/shared/peertube/peertube-plugin.ts similarity index 100% rename from client/src/assets/player/shared/peertube/peertube-plugin.ts rename to client/src/standalone/player/src/shared/peertube/peertube-plugin.ts diff --git a/client/src/assets/player/shared/player-options-builder/control-bar-options-builder.ts b/client/src/standalone/player/src/shared/player-options-builder/control-bar-options-builder.ts similarity index 100% rename from client/src/assets/player/shared/player-options-builder/control-bar-options-builder.ts rename to client/src/standalone/player/src/shared/player-options-builder/control-bar-options-builder.ts diff --git a/client/src/assets/player/shared/player-options-builder/hls-options-builder.ts b/client/src/standalone/player/src/shared/player-options-builder/hls-options-builder.ts similarity index 66% rename from client/src/assets/player/shared/player-options-builder/hls-options-builder.ts rename to client/src/standalone/player/src/shared/player-options-builder/hls-options-builder.ts index db33c06c3..6a0f0dd92 100644 --- a/client/src/assets/player/shared/player-options-builder/hls-options-builder.ts +++ b/client/src/standalone/player/src/shared/player-options-builder/hls-options-builder.ts @@ -1,13 +1,12 @@ -import { HybridLoaderSettings } from '@peertube/p2p-media-loader-core' -import { Engine, HlsJsEngineSettings } from '@peertube/p2p-media-loader-hlsjs' import { getResolutionAndFPSLabel, getResolutionLabel } from '@peertube/peertube-core-utils' import { LiveVideoLatencyMode } from '@peertube/peertube-models' import { logger } from '@root-helpers/logger' import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' +import debug from 'debug' import { Level } from 'hls.js' +import type { CoreConfig, StreamConfig } from 'p2p-media-loader-core' import { getAverageBandwidthInStore } from '../../peertube-player-local-storage' import { - HLSLoaderClass, HLSPluginOptions, P2PMediaLoaderPluginOptions, PeerTubePlayerConstructorOptions, @@ -15,9 +14,7 @@ import { } from '../../types' import { getRtcConfig, isSameOrigin } from '../common' import { RedundancyUrlManager } from '../p2p-media-loader/redundancy-url-manager' -import { segmentUrlBuilderFactory } from '../p2p-media-loader/segment-url-builder' import { SegmentValidator } from '../p2p-media-loader/segment-validator' -import debug from 'debug' const debugLogger = debug('peertube:player:hls') @@ -58,7 +55,6 @@ export class HLSOptionsBuilder { 'filter:internal.player.p2p-media-loader.options.result', this.getP2PMediaLoaderOptions({ redundancyUrlManager, segmentValidator }) ) - const loaderBuilder = () => new Engine(p2pMediaLoaderConfig).createLoaderClass() as unknown as HLSLoaderClass const p2pMediaLoader: P2PMediaLoaderPluginOptions = { requiresUserAuth: this.options.requiresUserAuth, @@ -73,7 +69,7 @@ export class HLSOptionsBuilder { } const hlsjs = { - hlsjsConfig: this.getHLSJSOptions(loaderBuilder), + hlsjsConfig: this.getHLSJSOptions(p2pMediaLoaderConfig), levelLabelHandler: (level: Level, player: videojs.VideoJsPlayer) => { const resolution = Math.min(level.height || 0, level.width || 0) @@ -99,65 +95,81 @@ export class HLSOptionsBuilder { private getP2PMediaLoaderOptions (options: { redundancyUrlManager: RedundancyUrlManager | null segmentValidator: SegmentValidator | null - }): HlsJsEngineSettings { + }) { const { redundancyUrlManager, segmentValidator } = options - let consumeOnly = false + let isP2PUploadDisabled = false if ( (navigator as any)?.connection?.type === 'cellular' || peertubeLocalStorage.getItem('peertube-videojs-p2p-consume-only') === 'true' // Use for E2E testing ) { logger.info('We are on a cellular connection: disabling seeding.') - consumeOnly = true + isP2PUploadDisabled = true } - const trackerAnnounce = this.options.hls.trackerAnnounce + const announceTrackers = this.options.hls.trackerAnnounce .filter(t => t.startsWith('ws')) const specificLiveOrVODOptions = this.options.isLive ? this.getP2PMediaLoaderLiveOptions() : this.getP2PMediaLoaderVODOptions() - return { - loader: { - trackerAnnounce, - rtcConfig: getRtcConfig(this.options.stunServers), + // TODO: remove validateHTTPSegment typing when p2p-media-loader-core is updated + const loaderOptions: Partial & { validateHTTPSegment: any } = { + announceTrackers, + rtcConfig: getRtcConfig(this.options.stunServers), - simultaneousHttpDownloads: 1, - httpFailedSegmentTimeout: 1000, + httpRequestSetup: (segmentUrlArg, segmentByteRange, requestAbortSignal, requestByteRange) => { + const { requiresUserAuth, requiresPassword } = this.options - xhrSetup: (xhr, url) => { - const { requiresUserAuth, requiresPassword } = this.options + const segmentUrl = redundancyUrlManager + ? redundancyUrlManager.buildUrl(segmentUrlArg) + : segmentUrlArg - if (!(requiresUserAuth || requiresPassword)) return + const headers = new Headers() - if (!isSameOrigin(this.options.serverUrl, url)) return + if (requestByteRange) { + headers.set('Range', `bytes=${requestByteRange.start}-${requestByteRange.end ?? ''}`) + } - if (requiresPassword) xhr.setRequestHeader('x-peertube-video-password', this.options.videoPassword()) - else xhr.setRequestHeader('Authorization', this.options.authorizationHeader()) - }, + if (isSameOrigin(this.options.serverUrl, segmentUrl)) { + if (requiresPassword) { + headers.set('x-peertube-video-password', this.options.videoPassword()) + } else if (requiresUserAuth) { + headers.set('Authorization', this.options.authorizationHeader()) + } + } - segmentValidator: segmentValidator - ? segmentValidator.validate.bind(segmentValidator) - : null, - - segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager), - - useP2P: this.options.p2pEnabled, - consumeOnly, - - ...specificLiveOrVODOptions + return Promise.resolve( + new Request(segmentUrl, { + headers, + signal: requestAbortSignal + }) + ) }, - segments: { - swarmId: this.options.hls.playlistUrl, - forwardSegmentCount: specificLiveOrVODOptions.p2pDownloadMaxPriority ?? 20 - } + + validateP2PSegment: segmentValidator + ? segmentValidator.validate.bind(segmentValidator) + : null, + + validateHTTPSegment: segmentValidator + ? segmentValidator.validate.bind(segmentValidator) + : null, + + isP2PDisabled: !this.options.p2pEnabled, + isP2PUploadDisabled, + + swarmId: this.options.hls.playlistUrl, + + ...specificLiveOrVODOptions } + + return { loader: loaderOptions } } - private getP2PMediaLoaderLiveOptions (): Partial { + private getP2PMediaLoaderLiveOptions (): Partial { const base = { - requiredSegmentsPriority: 1 + highDemandTimeWindow: 4 } const latencyMode = this.options.liveOptions.latencyMode @@ -167,8 +179,7 @@ export class HLSOptionsBuilder { return { ...base, - useP2P: false, - requiredSegmentsPriority: 10 + isP2PDisabled: true } case LiveVideoLatencyMode.HIGH_LATENCY: @@ -179,34 +190,39 @@ export class HLSOptionsBuilder { } } - private getP2PMediaLoaderVODOptions (): Partial { + private getP2PMediaLoaderVODOptions (): Partial { return { - requiredSegmentsPriority: 3, - skipSegmentBuilderPriority: 1, + highDemandTimeWindow: 15, - cachedSegmentExpiration: 86400000, - cachedSegmentsCount: 100, - - httpDownloadMaxPriority: 9, - httpDownloadProbability: 0.06, - httpDownloadProbabilitySkipIfNoPeers: true, - - p2pDownloadMaxPriority: 50 + segmentMemoryStorageLimit: 1024 } } // --------------------------------------------------------------------------- - private getHLSJSOptions (loaderBuilder: () => HLSLoaderClass): HLSPluginOptions { + private getHLSJSOptions (p2pMediaLoaderConfig: { loader: CoreConfig }): HLSPluginOptions { const specificLiveOrVODOptions = this.options.isLive ? this.getHLSLiveOptions() : this.getHLSVODOptions() - const base = { + const base: HLSPluginOptions = { capLevelToPlayerSize: true, autoStartLoad: false, - loaderBuilder, + p2pMediaLoaderOptions: p2pMediaLoaderConfig.loader, + + // p2p-media-loader uses hls.js loader to fetch m3u8 playlists + xhrSetup: (xhr, url) => { + const { requiresUserAuth, requiresPassword } = this.options + + if (isSameOrigin(this.options.serverUrl, url)) { + if (requiresPassword) { + xhr.setRequestHeader('x-peertube-video-password', this.options.videoPassword()) + } else if (requiresUserAuth) { + xhr.setRequestHeader('Authorization', this.options.authorizationHeader()) + } + } + }, ...specificLiveOrVODOptions } diff --git a/client/src/assets/player/shared/player-options-builder/index.ts b/client/src/standalone/player/src/shared/player-options-builder/index.ts similarity index 100% rename from client/src/assets/player/shared/player-options-builder/index.ts rename to client/src/standalone/player/src/shared/player-options-builder/index.ts diff --git a/client/src/assets/player/shared/player-options-builder/web-video-options-builder.ts b/client/src/standalone/player/src/shared/player-options-builder/web-video-options-builder.ts similarity index 100% rename from client/src/assets/player/shared/player-options-builder/web-video-options-builder.ts rename to client/src/standalone/player/src/shared/player-options-builder/web-video-options-builder.ts diff --git a/client/src/assets/player/shared/playlist/index.ts b/client/src/standalone/player/src/shared/playlist/index.ts similarity index 100% rename from client/src/assets/player/shared/playlist/index.ts rename to client/src/standalone/player/src/shared/playlist/index.ts diff --git a/client/src/assets/player/shared/playlist/playlist-button.ts b/client/src/standalone/player/src/shared/playlist/playlist-button.ts similarity index 100% rename from client/src/assets/player/shared/playlist/playlist-button.ts rename to client/src/standalone/player/src/shared/playlist/playlist-button.ts diff --git a/client/src/assets/player/shared/playlist/playlist-menu-item.ts b/client/src/standalone/player/src/shared/playlist/playlist-menu-item.ts similarity index 100% rename from client/src/assets/player/shared/playlist/playlist-menu-item.ts rename to client/src/standalone/player/src/shared/playlist/playlist-menu-item.ts diff --git a/client/src/assets/player/shared/playlist/playlist-menu.ts b/client/src/standalone/player/src/shared/playlist/playlist-menu.ts similarity index 100% rename from client/src/assets/player/shared/playlist/playlist-menu.ts rename to client/src/standalone/player/src/shared/playlist/playlist-menu.ts diff --git a/client/src/assets/player/shared/playlist/playlist-plugin.ts b/client/src/standalone/player/src/shared/playlist/playlist-plugin.ts similarity index 100% rename from client/src/assets/player/shared/playlist/playlist-plugin.ts rename to client/src/standalone/player/src/shared/playlist/playlist-plugin.ts diff --git a/client/src/assets/player/shared/resolutions/index.ts b/client/src/standalone/player/src/shared/resolutions/index.ts similarity index 100% rename from client/src/assets/player/shared/resolutions/index.ts rename to client/src/standalone/player/src/shared/resolutions/index.ts diff --git a/client/src/assets/player/shared/resolutions/peertube-resolutions-plugin.ts b/client/src/standalone/player/src/shared/resolutions/peertube-resolutions-plugin.ts similarity index 100% rename from client/src/assets/player/shared/resolutions/peertube-resolutions-plugin.ts rename to client/src/standalone/player/src/shared/resolutions/peertube-resolutions-plugin.ts diff --git a/client/src/assets/player/shared/settings/index.ts b/client/src/standalone/player/src/shared/settings/index.ts similarity index 100% rename from client/src/assets/player/shared/settings/index.ts rename to client/src/standalone/player/src/shared/settings/index.ts diff --git a/client/src/assets/player/shared/settings/menu-focus-fixed.ts b/client/src/standalone/player/src/shared/settings/menu-focus-fixed.ts similarity index 100% rename from client/src/assets/player/shared/settings/menu-focus-fixed.ts rename to client/src/standalone/player/src/shared/settings/menu-focus-fixed.ts diff --git a/client/src/assets/player/shared/settings/resolution-menu-button.ts b/client/src/standalone/player/src/shared/settings/resolution-menu-button.ts similarity index 100% rename from client/src/assets/player/shared/settings/resolution-menu-button.ts rename to client/src/standalone/player/src/shared/settings/resolution-menu-button.ts diff --git a/client/src/assets/player/shared/settings/resolution-menu-item.ts b/client/src/standalone/player/src/shared/settings/resolution-menu-item.ts similarity index 100% rename from client/src/assets/player/shared/settings/resolution-menu-item.ts rename to client/src/standalone/player/src/shared/settings/resolution-menu-item.ts diff --git a/client/src/assets/player/shared/settings/settings-dialog.ts b/client/src/standalone/player/src/shared/settings/settings-dialog.ts similarity index 100% rename from client/src/assets/player/shared/settings/settings-dialog.ts rename to client/src/standalone/player/src/shared/settings/settings-dialog.ts diff --git a/client/src/assets/player/shared/settings/settings-menu-button.ts b/client/src/standalone/player/src/shared/settings/settings-menu-button.ts similarity index 100% rename from client/src/assets/player/shared/settings/settings-menu-button.ts rename to client/src/standalone/player/src/shared/settings/settings-menu-button.ts diff --git a/client/src/assets/player/shared/settings/settings-menu-item.ts b/client/src/standalone/player/src/shared/settings/settings-menu-item.ts similarity index 100% rename from client/src/assets/player/shared/settings/settings-menu-item.ts rename to client/src/standalone/player/src/shared/settings/settings-menu-item.ts diff --git a/client/src/assets/player/shared/settings/settings-panel-child.ts b/client/src/standalone/player/src/shared/settings/settings-panel-child.ts similarity index 100% rename from client/src/assets/player/shared/settings/settings-panel-child.ts rename to client/src/standalone/player/src/shared/settings/settings-panel-child.ts diff --git a/client/src/assets/player/shared/settings/settings-panel.ts b/client/src/standalone/player/src/shared/settings/settings-panel.ts similarity index 100% rename from client/src/assets/player/shared/settings/settings-panel.ts rename to client/src/standalone/player/src/shared/settings/settings-panel.ts diff --git a/client/src/assets/player/shared/stats/index.ts b/client/src/standalone/player/src/shared/stats/index.ts similarity index 100% rename from client/src/assets/player/shared/stats/index.ts rename to client/src/standalone/player/src/shared/stats/index.ts diff --git a/client/src/assets/player/shared/stats/stats-card.ts b/client/src/standalone/player/src/shared/stats/stats-card.ts similarity index 99% rename from client/src/assets/player/shared/stats/stats-card.ts rename to client/src/standalone/player/src/shared/stats/stats-card.ts index de25cae35..01971c7d0 100644 --- a/client/src/assets/player/shared/stats/stats-card.ts +++ b/client/src/standalone/player/src/shared/stats/stats-card.ts @@ -138,6 +138,8 @@ class StatsCard extends Component { this.containerEl.style.display = 'block' this.updateInterval = setInterval(async () => { + if (!this.mode) return + try { const options = this.mode === 'p2p-media-loader' ? this.buildHLSOptions() diff --git a/client/src/assets/player/shared/stats/stats-plugin.ts b/client/src/standalone/player/src/shared/stats/stats-plugin.ts similarity index 100% rename from client/src/assets/player/shared/stats/stats-plugin.ts rename to client/src/standalone/player/src/shared/stats/stats-plugin.ts diff --git a/client/src/assets/player/shared/upnext/end-card.ts b/client/src/standalone/player/src/shared/upnext/end-card.ts similarity index 100% rename from client/src/assets/player/shared/upnext/end-card.ts rename to client/src/standalone/player/src/shared/upnext/end-card.ts diff --git a/client/src/assets/player/shared/upnext/index.ts b/client/src/standalone/player/src/shared/upnext/index.ts similarity index 100% rename from client/src/assets/player/shared/upnext/index.ts rename to client/src/standalone/player/src/shared/upnext/index.ts diff --git a/client/src/assets/player/shared/upnext/upnext-plugin.ts b/client/src/standalone/player/src/shared/upnext/upnext-plugin.ts similarity index 100% rename from client/src/assets/player/shared/upnext/upnext-plugin.ts rename to client/src/standalone/player/src/shared/upnext/upnext-plugin.ts diff --git a/client/src/assets/player/shared/web-video/web-video-plugin.ts b/client/src/standalone/player/src/shared/web-video/web-video-plugin.ts similarity index 100% rename from client/src/assets/player/shared/web-video/web-video-plugin.ts rename to client/src/standalone/player/src/shared/web-video/web-video-plugin.ts diff --git a/client/src/assets/player/types/index.ts b/client/src/standalone/player/src/types/index.ts similarity index 100% rename from client/src/assets/player/types/index.ts rename to client/src/standalone/player/src/types/index.ts diff --git a/client/src/assets/player/types/peertube-player-options.ts b/client/src/standalone/player/src/types/peertube-player-options.ts similarity index 100% rename from client/src/assets/player/types/peertube-player-options.ts rename to client/src/standalone/player/src/types/peertube-player-options.ts diff --git a/client/src/assets/player/types/peertube-videojs-typings.ts b/client/src/standalone/player/src/types/peertube-videojs-typings.ts similarity index 96% rename from client/src/assets/player/types/peertube-videojs-typings.ts rename to client/src/standalone/player/src/types/peertube-videojs-typings.ts index 671d2f569..b78038e27 100644 --- a/client/src/assets/player/types/peertube-videojs-typings.ts +++ b/client/src/standalone/player/src/types/peertube-videojs-typings.ts @@ -1,6 +1,7 @@ -import { Engine } from '@peertube/p2p-media-loader-hlsjs' import { VideoChapter, VideoFile, VideoPlaylist, VideoPlaylistElement } from '@peertube/peertube-models' import type { HlsConfig, Level, Loader, LoaderContext } from 'hls.js' +import type { CoreConfig } from 'p2p-media-loader-core' +import type { HlsJsP2PEngine } from 'p2p-media-loader-hlsjs' import videojs from 'video.js' import { BezelsPlugin } from '../shared/bezels/bezels-plugin' import { ContextMenuPlugin } from '../shared/context-menu' @@ -215,9 +216,9 @@ export type WebVideoPluginOptions = { export type HLSLoaderClass = { new (confg: HlsConfig): Loader - getEngine(): Engine + getEngine(): HlsJsP2PEngine } -export type HLSPluginOptions = Partial HLSLoaderClass }> +export type HLSPluginOptions = Partial export type P2PMediaLoaderPluginOptions = { redundancyUrlManager: RedundancyUrlManager | null @@ -233,7 +234,7 @@ export type P2PMediaLoaderPluginOptions = { } export type P2PMediaLoader = { - getEngine(): Engine + getEngine(): HlsJsP2PEngine destroy: () => void } diff --git a/client/src/standalone/player/tsconfig.json b/client/src/standalone/player/tsconfig.json new file mode 100644 index 000000000..c2187c8c0 --- /dev/null +++ b/client/src/standalone/player/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../../tsconfig.json", + "include": [ + "./index.ts" + ] +} diff --git a/client/src/standalone/player/vite.config.mjs b/client/src/standalone/player/vite.config.mjs new file mode 100644 index 000000000..1e9a2ae6d --- /dev/null +++ b/client/src/standalone/player/vite.config.mjs @@ -0,0 +1,47 @@ +import { nodePolyfills } from 'vite-plugin-node-polyfills' +import { dirname, resolve } from 'path' +import { fileURLToPath } from 'url' +import { defineConfig } from 'vite' +import checker from 'vite-plugin-checker' + +import { getCSSConfig, getAliasConfig } from '../build-tools/vite-utils.js' + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = resolve(__dirname, '../../../') + +export default defineConfig(() => { + return { + build: { + outDir: resolve(__dirname, 'build'), + emptyOutDir: false, + minify: false, + lib: { + formats: [ 'es' ], + entry: resolve(__dirname, './src/index.ts'), + name: 'PeerTubePlayer', + fileName: 'peertube-player', + cssFilename: 'peertube-player.css' + } + }, + + css: getCSSConfig(root), + + resolve: { + alias: getAliasConfig(root), + + conditions: [ + 'p2pml:core-as-bundle', 'defaultClientConditions' + ] + }, + + plugins: [ + checker({ + typescript: { + tsconfigPath: resolve(__dirname, 'tsconfig.json') + } + }), + + nodePolyfills() + ] + } +}) diff --git a/client/src/standalone/videos/embed.scss b/client/src/standalone/videos/embed.scss index 44082e4a0..8f25b7501 100644 --- a/client/src/standalone/videos/embed.scss +++ b/client/src/standalone/videos/embed.scss @@ -1,11 +1,7 @@ @use '_variables' as *; @use '_mixins' as *; @use '_css-variables' as *; -@use 'video.js/dist/video-js'; - -$assets-path: '../../assets/'; - -@use '../../sass/player/index'; +@use '../player/build/peertube-player'; [hidden] { display: none !important; diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index dbb9478fe..74af84059 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts @@ -1,8 +1,3 @@ -import './embed.scss' -import '../../assets/player/shared/dock/peertube-dock-component' -import '../../assets/player/shared/dock/peertube-dock-plugin' -import { PeerTubeServerError } from 'src/types' -import videojs from 'video.js' import { HTMLServerConfig, ResultList, @@ -12,10 +7,13 @@ import { VideoPlaylistElement, VideoState } from '@peertube/peertube-models' -import { PeerTubePlayer } from '../../assets/player/peertube-player' -import { TranslationsManager } from '../../assets/player/translations-manager' +import type { PeerTubePlayer } from '@peertube/player' +import { TranslationsManager } from '@root-helpers/translations-manager' +import { PeerTubeServerError } from 'src/types' +import type videojs from 'video.js' import { getParamString, logger, videoRequiresFileToken } from '../../root-helpers' import { PeerTubeEmbedApi } from './embed-api' +import './embed.scss' import { AuthHTTP, LiveManager, @@ -37,6 +35,7 @@ export class PeerTubeEmbed { private translationsPromise: Promise<{ [id: string]: string }> private PeerTubePlayerManagerModulePromise: Promise + private videojs: typeof videojs private readonly http: AuthHTTP private readonly videoFetcher: VideoFetcher @@ -94,7 +93,7 @@ export class PeerTubeEmbed { async init () { this.translationsPromise = TranslationsManager.getServerTranslations(getBackendUrl(), navigator.language) - this.PeerTubePlayerManagerModulePromise = import('../../assets/player/peertube-player') + this.PeerTubePlayerManagerModulePromise = import('@peertube/player') // Issue when we parsed config from HTML, fallback to API if (!this.config) { @@ -334,7 +333,11 @@ export class PeerTubeEmbed { } } - this.peertubePlugin.getPluginsManager().runHook('action:embed.player.loaded', undefined, { player: this.player, videojs, video }) + this.peertubePlugin.getPluginsManager().runHook( + 'action:embed.player.loaded', + undefined, + { player: this.player, videojs: this.videojs, video } + ) } private buildCSS () { @@ -430,11 +433,13 @@ export class PeerTubeEmbed { this.playerHTML.setInitVideoEl(playerElement) this.playerHTML.addInitVideoElToDOM() - const [ { PeerTubePlayer } ] = await Promise.all([ + const [ { PeerTubePlayer, videojs } ] = await Promise.all([ this.PeerTubePlayerManagerModulePromise, this.peertubePlugin.loadPlugins(this.config, await this.translationsPromise) ]) + this.videojs = videojs + const constructorOptions = this.playerOptionsBuilder.getPlayerConstructorOptions({ serverConfig: this.config, authorizationHeader: () => this.http.getHeaderTokenValue() diff --git a/client/src/standalone/videos/shared/peertube-plugin.ts b/client/src/standalone/videos/shared/peertube-plugin.ts index 1643ebc9b..154593946 100644 --- a/client/src/standalone/videos/shared/peertube-plugin.ts +++ b/client/src/standalone/videos/shared/peertube-plugin.ts @@ -19,7 +19,8 @@ export class PeerTubePlugin { peertubeHelpersFactory: pluginInfo => this.buildPeerTubeHelpers({ pluginInfo, translations - }) + }), + backendUrl: getBackendUrl() }) this.pluginsManager.loadPluginsList(config) diff --git a/client/src/standalone/videos/shared/player-options-builder.ts b/client/src/standalone/videos/shared/player-options-builder.ts index 4e3daec57..3bd0c1995 100644 --- a/client/src/standalone/videos/shared/player-options-builder.ts +++ b/client/src/standalone/videos/shared/player-options-builder.ts @@ -11,7 +11,6 @@ import { VideoState, VideoStreamingPlaylistType } from '@peertube/peertube-models' -import { HLSOptions, PeerTubePlayerConstructorOptions, PeerTubePlayerLoadOptions, PlayerMode, VideoJSCaption } from '../../../assets/player' import { getBoolOrDefault, getParamString, @@ -22,12 +21,13 @@ import { UserLocalStorageKeys, videoRequiresUserAuth } from '../../../root-helpers' +import { HLSOptions, PeerTubePlayerConstructorOptions, PeerTubePlayerLoadOptions, PlayerMode, VideoJSCaption } from '../../player' import { PeerTubePlugin } from './peertube-plugin' import { PlayerHTML } from './player-html' import { PlaylistTracker } from './playlist-tracker' import { Translations } from './translations' -import { VideoFetcher } from './video-fetcher' import { getBackendUrl } from './url' +import { VideoFetcher } from './video-fetcher' export class PlayerOptionsBuilder { private autoplay: boolean diff --git a/client/src/standalone/videos/vite.config.mjs b/client/src/standalone/videos/vite.config.mjs index 7c69fd114..f74230128 100644 --- a/client/src/standalone/videos/vite.config.mjs +++ b/client/src/standalone/videos/vite.config.mjs @@ -5,8 +5,9 @@ import { dirname } from 'path' import { fileURLToPath } from 'url' import checker from 'vite-plugin-checker' -const __dirname = dirname(fileURLToPath(import.meta.url)) +import { getCSSConfig, getAliasConfig } from '../build-tools/vite-utils.js' +const __dirname = dirname(fileURLToPath(import.meta.url)) const root = resolve(__dirname, '../../../') export default defineConfig(({ mode }) => { @@ -41,26 +42,17 @@ export default defineConfig(({ mode }) => { }, resolve: { - alias: [ - { find: /^video.js$/, replacement: resolve(root, './node_modules/video.js/core.js') }, - { find: '@root-helpers', replacement: resolve(root, './src/root-helpers') } - ], + alias: getAliasConfig(root), }, - css: { - preprocessorOptions: { - scss: { - includePaths: [resolve(root, './src/sass/include')] - } - } - }, + css: getCSSConfig(root), build: { outDir: resolve(root, 'dist', 'standalone', 'videos'), emptyOutDir: true, sourcemap: mode === 'development', - target: [ 'firefox78', 'ios12' ], + target: [ 'firefox78', 'ios14' ], rollupOptions: { input: { diff --git a/client/yarn.lock b/client/yarn.lock index 0ef355373..9d736b04a 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -454,6 +454,11 @@ axios "^1.7.4" uuid "9.0.1" +"@bufbuild/protobuf@^2.0.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-2.2.3.tgz#9cd136f6b687e63e9b517b3a54211ece942897ee" + integrity sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg== + "@colors/colors@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" @@ -500,171 +505,86 @@ esquery "^1.6.0" jsdoc-type-pratt-parser "~4.0.0" -"@esbuild/aix-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== - "@esbuild/aix-ppc64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461" integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== - "@esbuild/android-arm64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894" integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== - "@esbuild/android-arm@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3" integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== -"@esbuild/android-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== - "@esbuild/android-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb" integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw== -"@esbuild/darwin-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== - "@esbuild/darwin-arm64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936" integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== -"@esbuild/darwin-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== - "@esbuild/darwin-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9" integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA== -"@esbuild/freebsd-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== - "@esbuild/freebsd-arm64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00" integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg== -"@esbuild/freebsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== - "@esbuild/freebsd-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f" integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== - "@esbuild/linux-arm64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43" integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== - "@esbuild/linux-arm@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736" integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== -"@esbuild/linux-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== - "@esbuild/linux-ia32@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5" integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw== -"@esbuild/linux-loong64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== - "@esbuild/linux-loong64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc" integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ== -"@esbuild/linux-mips64el@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== - "@esbuild/linux-mips64el@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb" integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw== -"@esbuild/linux-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== - "@esbuild/linux-ppc64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412" integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw== -"@esbuild/linux-riscv64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== - "@esbuild/linux-riscv64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694" integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q== -"@esbuild/linux-s390x@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== - "@esbuild/linux-s390x@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577" integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw== -"@esbuild/linux-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== - "@esbuild/linux-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f" @@ -675,11 +595,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6" integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw== -"@esbuild/netbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== - "@esbuild/netbsd-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40" @@ -690,51 +605,26 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f" integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A== -"@esbuild/openbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== - "@esbuild/openbsd-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205" integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA== -"@esbuild/sunos-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== - "@esbuild/sunos-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6" integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig== -"@esbuild/win32-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== - "@esbuild/win32-arm64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85" integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ== -"@esbuild/win32-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== - "@esbuild/win32-ia32@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2" integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA== -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== - "@esbuild/win32-x64@0.24.2": version "0.24.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b" @@ -1495,29 +1385,6 @@ smtp-server "^3.9.0" wildstring "1.0.9" -"@peertube/p2p-media-loader-core@^1.0.20": - version "1.0.20" - resolved "https://registry.yarnpkg.com/@peertube/p2p-media-loader-core/-/p2p-media-loader-core-1.0.20.tgz#8e786dd52471a03fc00006d14b150b38fe7c8211" - integrity sha512-t6yYFcBTqDZSp3U0HqOI9fJzxFgb2C4PoiRI4FPGd28baUbsilO1PQBRwQzvu6wt8zwjzOE8FBpzYa+1gv1Sqg== - dependencies: - bittorrent-tracker "^11.1.0" - debug "^4.3.5" - esbuild "^0.21.5" - events "^3.3.0" - sha.js "^2.4.11" - simple-peer "^9.11.1" - -"@peertube/p2p-media-loader-hlsjs@^1.0.20": - version "1.0.20" - resolved "https://registry.yarnpkg.com/@peertube/p2p-media-loader-hlsjs/-/p2p-media-loader-hlsjs-1.0.20.tgz#b6330d5331a70fa3a65ef3c32546b8d88c065749" - integrity sha512-PZS9h+txV+BX3t5lsh5PZ0ZtOogPJv4GmheQ5etceQZHxRAx2UxcAchMBJsa/sQ5c4CSMsN61Megs9iZ3gWauQ== - dependencies: - "@peertube/p2p-media-loader-core" "^1.0.20" - debug "^4.3.5" - esbuild "^0.21.5" - events "^3.3.0" - m3u8-parser "~4.7.1" - "@peertube/xliffmerge@^2.0.3": version "2.0.4" resolved "https://registry.yarnpkg.com/@peertube/xliffmerge/-/xliffmerge-2.0.4.tgz#5a80c263ab6f1b15a8b8c3e54317077f0d98e611" @@ -1609,9 +1476,9 @@ magic-string "^0.30.3" "@rollup/pluginutils@^5.0.1": - version "5.1.4" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" - integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== + version "5.1.3" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.3.tgz#3001bf1a03f3ad24457591f2c259c8e514e0dbdf" + integrity sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A== dependencies: "@types/estree" "^1.0.0" estree-walker "^2.0.2" @@ -1989,7 +1856,7 @@ resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.8.tgz#d5c6ec44f2f3328653dce385ae586bd8261f8e85" integrity sha512-VgnAj6tIAhJhZdJ8/IpxdatM8G4OD3VWGlp6xIxUGENZlpbob9Ty4VVdC1FIEp0aK6DBscDDjyzy5FB60TuNqg== -"@types/debug@^4.1.5": +"@types/debug@^4.1.12", "@types/debug@^4.1.5": version "4.1.12" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== @@ -2997,7 +2864,7 @@ bittorrent-peerid@^1.3.6: resolved "https://registry.yarnpkg.com/bittorrent-peerid/-/bittorrent-peerid-1.3.6.tgz#3688705a64937a8176ac2ded1178fc7bd91b61db" integrity sha512-VyLcUjVMEOdSpHaCG/7odvCdLbAB1y3l9A2V6WIje24uV7FkJPrQrH/RrlFmKxP89pFVDEnE+YlHaFujlFIZsg== -bittorrent-tracker@^11.1.0: +bittorrent-tracker@^11.2.1: version "11.2.1" resolved "https://registry.yarnpkg.com/bittorrent-tracker/-/bittorrent-tracker-11.2.1.tgz#b45ff4bd70c2c582bc60d4a8bb6b5bdcb487df9a" integrity sha512-SffBgHzNrhn+HBwdRD2st+TYJOs2LhF3ljJFPCYGv592LpGtPxw41UZHTUeY5muWnQl+wopcU8qXM9UEk2WKrA== @@ -3184,6 +3051,11 @@ browserstack-local@^1.5.1: ps-tree "=1.2.0" temp-fs "^0.9.9" +buffer-builder@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/buffer-builder/-/buffer-builder-0.2.0.tgz#3322cd307d8296dab1f604618593b261a3fade8f" + integrity sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg== + buffer-crc32@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-1.0.0.tgz#a10993b9055081d55304bd9feb4a072de179f405" @@ -3544,6 +3416,11 @@ colorette@^2.0.20: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== +colorjs.io@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/colorjs.io/-/colorjs.io-0.5.2.tgz#63b20139b007591ebc3359932bef84628eb3fcef" + integrity sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -3811,7 +3688,7 @@ data-view-byte-offset@^1.0.1: es-errors "^1.3.0" is-data-view "^1.0.1" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.6, debug@^4.3.7: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.6, debug@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== @@ -3832,7 +3709,7 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@~4.3.1, debug@~4.3.2: +debug@^4.3.7, debug@~4.3.1, debug@~4.3.2: version "4.3.7" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== @@ -4022,10 +3899,10 @@ dom-walk@^0.1.0: resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== -domain-browser@4.22.0: - version "4.22.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.22.0.tgz#6ddd34220ec281f9a65d3386d267ddd35c491f9f" - integrity sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw== +domain-browser@^4.22.0: + version "4.23.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.23.0.tgz#427ebb91efcb070f05cffdfb8a4e9a6c25f8c94b" + integrity sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA== domelementtype@^2.3.0: version "2.3.0" @@ -4129,9 +4006,9 @@ electron-to-chromium@^1.5.73: integrity sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug== elliptic@^6.5.3, elliptic@^6.5.5: - version "6.6.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" - integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + version "6.6.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" + integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -4354,35 +4231,6 @@ esbuild@0.24.2, esbuild@^0.24.2: "@esbuild/win32-ia32" "0.24.2" "@esbuild/win32-x64" "0.24.2" -esbuild@^0.21.3, esbuild@^0.21.5: - version "0.21.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== - optionalDependencies: - "@esbuild/aix-ppc64" "0.21.5" - "@esbuild/android-arm" "0.21.5" - "@esbuild/android-arm64" "0.21.5" - "@esbuild/android-x64" "0.21.5" - "@esbuild/darwin-arm64" "0.21.5" - "@esbuild/darwin-x64" "0.21.5" - "@esbuild/freebsd-arm64" "0.21.5" - "@esbuild/freebsd-x64" "0.21.5" - "@esbuild/linux-arm" "0.21.5" - "@esbuild/linux-arm64" "0.21.5" - "@esbuild/linux-ia32" "0.21.5" - "@esbuild/linux-loong64" "0.21.5" - "@esbuild/linux-mips64el" "0.21.5" - "@esbuild/linux-ppc64" "0.21.5" - "@esbuild/linux-riscv64" "0.21.5" - "@esbuild/linux-s390x" "0.21.5" - "@esbuild/linux-x64" "0.21.5" - "@esbuild/netbsd-x64" "0.21.5" - "@esbuild/openbsd-x64" "0.21.5" - "@esbuild/sunos-x64" "0.21.5" - "@esbuild/win32-arm64" "0.21.5" - "@esbuild/win32-ia32" "0.21.5" - "@esbuild/win32-x64" "0.21.5" - escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" @@ -5031,11 +4879,6 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-browser-rtc@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz#d1494e299b00f33fc8e9d6d3343ba4ba99711a2c" - integrity sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ== - get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -5356,12 +5199,12 @@ hash-base@^3.0.0: safe-buffer "^5.2.0" hash-base@~3.0, hash-base@~3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" - integrity sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg== + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow== dependencies: - inherits "^2.0.4" - safe-buffer "^5.2.1" + inherits "^2.0.1" + safe-buffer "^5.0.1" hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" @@ -6427,22 +6270,20 @@ m3u8-parser@4.8.0: "@videojs/vhs-utils" "^3.0.5" global "^4.4.0" -m3u8-parser@~4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/m3u8-parser/-/m3u8-parser-4.7.1.tgz#d6df2c940bb19a01112a04ccc4ff44886a945305" - integrity sha512-pbrQwiMiq+MmI9bl7UjtPT3AK603PV9bogNlr83uC+X9IoxqL5E4k7kU7fMQ0dpRgxgeSMygqUa0IMLQNXLBNA== - dependencies: - "@babel/runtime" "^7.12.5" - "@videojs/vhs-utils" "^3.0.5" - global "^4.4.0" - -magic-string@0.30.17, magic-string@^0.30.12, magic-string@^0.30.3: +magic-string@0.30.17, magic-string@^0.30.12: version "0.30.17" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" +magic-string@^0.30.3: + version "0.30.12" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60" + integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + mailparser-mit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mailparser-mit/-/mailparser-mit-1.0.0.tgz#19df8436c2a02e1d34a03ec518a2eb065e0a94a4" @@ -6855,6 +6696,11 @@ mux.js@6.0.1: "@babel/runtime" "^7.11.2" global "^4.4.0" +nano-md5@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nano-md5/-/nano-md5-1.0.5.tgz#99d155e95ccaadc4096a309292a0df1b5190514e" + integrity sha512-1VAOX0EiuwAdCMGpnglxp9r6ylm+gXwQi+UPAnc/Oj1tLLJ8D1I8rLZeiO4MWsUAqH8tuBAHweT1LYSrDfJlPg== + nanoid@^3.3.8: version "3.3.8" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" @@ -6888,9 +6734,9 @@ ngx-uploadx@^7.0.0: tslib "^2.3.0" node-abi@^3.3.0: - version "3.74.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.74.0.tgz#5bfb4424264eaeb91432d2adb9da23c63a301ed0" - integrity sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w== + version "3.71.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.71.0.tgz#52d84bbcd8575efb71468fbaa1f9a49b2c242038" + integrity sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw== dependencies: semver "^7.3.5" @@ -6946,9 +6792,9 @@ node-gyp-build-optional-packages@5.2.2: detect-libc "^2.0.1" node-gyp-build@^4.3.0: - version "4.8.4" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" - integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== + version "4.8.3" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.3.tgz#9187216d24dbee29e44eb20d2ebf62a296bbea1a" + integrity sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw== node-gyp@^11.0.0: version "11.0.0" @@ -6982,9 +6828,9 @@ node-request-interceptor@^0.6.3: strict-event-emitter "^0.1.0" node-stdlib-browser@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-stdlib-browser/-/node-stdlib-browser-1.3.0.tgz#6e04d149f9abfc345a2271b2820a75df0f9cd7de" - integrity sha512-g/koYzOr9Fb1Jc+tHUHlFd5gODjGn48tHexUK8q6iqOVriEgSnd3/1T7myBYc+0KBVze/7F7n65ec9rW6OD7xw== + version "1.2.1" + resolved "https://registry.yarnpkg.com/node-stdlib-browser/-/node-stdlib-browser-1.2.1.tgz#888fa104914af94143ca4d8a8980fe0ed242d2d1" + integrity sha512-dZezG3D88Lg22DwyjsDuUs7cCT/XGr8WwJgg/S3ZnkcWuPet2Tt/W1d2Eytb1Z73JpZv+XVCDI5TWv6UMRq0Gg== dependencies: assert "^2.0.0" browser-resolve "^2.0.0" @@ -6994,7 +6840,7 @@ node-stdlib-browser@^1.2.0: constants-browserify "^1.0.0" create-require "^1.1.1" crypto-browserify "^3.11.0" - domain-browser "4.22.0" + domain-browser "^4.22.0" events "^3.0.0" https-browserify "^1.0.0" isomorphic-timers-promises "^1.0.1" @@ -7321,6 +7167,23 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +p2p-media-loader-core@2.1.2, p2p-media-loader-core@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/p2p-media-loader-core/-/p2p-media-loader-core-2.1.2.tgz#27bcb7b95cba76d00a681ce21bffaf41f418514e" + integrity sha512-fAeoXANKFRnHF17a706Bd6WtMdi5a9Ac78b39TBaGBWLFGfNWVj249ysuY8c5beLlgpGNnl5J4w9VH+I1UH2nQ== + dependencies: + "@types/debug" "^4.1.12" + bittorrent-tracker "^11.2.1" + debug "^4.4.0" + nano-md5 "^1.0.5" + +p2p-media-loader-hlsjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/p2p-media-loader-hlsjs/-/p2p-media-loader-hlsjs-2.1.2.tgz#a476cce7e196426b45c30a3669c62b0d21f1616e" + integrity sha512-97iCj6qlyHbBDTDHpbyuKejBdljA0gahq0Fa2B7GhiIJNqPN4nJe0KzycE1Yket8JpDKqGGE1747PpTSz2qLaA== + dependencies: + p2p-media-loader-core "2.1.2" + pac-proxy-agent@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz#da7c3b5c4cccc6655aaafb701ae140fb23f15df2" @@ -7620,7 +7483,7 @@ postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.32, postcss@^8.4.43, postcss@^8.4.49, postcss@^8.5.1: +postcss@^8.4.32, postcss@^8.4.49, postcss@^8.5.1: version "8.5.1" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.1.tgz#e2272a1f8a807fafa413218245630b5db10a3214" integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ== @@ -7812,6 +7675,11 @@ queue-microtask@^1.2.2, queue-microtask@^1.2.3: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue-tick@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" + integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== + quick-lru@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" @@ -8119,7 +7987,7 @@ rollup@4.30.1: "@rollup/rollup-win32-x64-msvc" "4.30.1" fsevents "~2.3.2" -rollup@^4.20.0, rollup@^4.23.0: +rollup@^4.23.0: version "4.34.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.34.1.tgz#dcc318abee12e23dae4003af733c1987d7baca8e" integrity sha512-iYZ/+PcdLYSGfH3S+dGahlW/RWmsqDhLgj1BT9DH/xXJ0ggZN7xkdP9wipPNjjNLczI+fmMLmTB9pye+d2r4GQ== @@ -8171,7 +8039,7 @@ rust-result@^1.0.0: dependencies: individual "^2.0.0" -rxjs@7.8.1, rxjs@^7.3.0, rxjs@^7.8.1: +rxjs@7.8.1, rxjs@^7.3.0, rxjs@^7.4.0, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -8238,6 +8106,141 @@ safe-stable-stringify@^2.3.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sass-embedded-android-arm64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.83.4.tgz#60af9d787e74276af95e4a1a1507567435bc61d2" + integrity sha512-tgX4FzmbVqnQmD67ZxQDvI+qFNABrboOQgwsG05E5bA/US42zGajW9AxpECJYiMXVOHmg+d81ICbjb0fsVHskw== + +sass-embedded-android-arm@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-android-arm/-/sass-embedded-android-arm-1.83.4.tgz#960953d094bf28c3e10a2e0ebd14459d4ec6e2d2" + integrity sha512-9Z4pJAOgEkXa3VDY/o+U6l5XvV0mZTJcSl0l/mSPHihjAHSpLYnOW6+KOWeM8dxqrsqTYcd6COzhanI/a++5Gw== + +sass-embedded-android-ia32@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.83.4.tgz#2293cb9920181094edfa477ba503f1f187d21624" + integrity sha512-RsFOziFqPcfZXdFRULC4Ayzy9aK6R6FwQ411broCjlOBX+b0gurjRadkue3cfUEUR5mmy0KeCbp7zVKPLTK+5Q== + +sass-embedded-android-riscv64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.83.4.tgz#84f86f2e96955a415343a2f24bae1af7bde26e5f" + integrity sha512-EHwh0nmQarBBrMRU928eTZkFGx19k/XW2YwbPR4gBVdWLkbTgCA5aGe8hTE6/1zStyx++3nDGvTZ78+b/VvvLg== + +sass-embedded-android-x64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-android-x64/-/sass-embedded-android-x64-1.83.4.tgz#8db3bb08b941889918f8435a97487cd84e7fd748" + integrity sha512-0PgQNuPWYy1jEOEPDVsV89KfqOsMLIp9CSbjBY7jRcwRhyVAcigqrUG6bDeNtojHUYKA1kU+Eh/85WxOHUOgBw== + +sass-embedded-darwin-arm64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.83.4.tgz#d0f3d82eea999ab0ae7ec8abd7fa364f0defc75e" + integrity sha512-rp2ywymWc3nymnSnAFG5R/8hvxWCsuhK3wOnD10IDlmNB7o4rzKby1c+2ZfpQGowlYGWsWWTgz8FW2qzmZsQRw== + +sass-embedded-darwin-x64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.83.4.tgz#cd2ac7f209fe823a8a5fc1a064cdfe2833680034" + integrity sha512-kLkN2lXz9PCgGfDS8Ev5YVcl/V2173L6379en/CaFuJJi7WiyPgBymW7hOmfCt4uO4R1y7CP2Uc08DRtZsBlAA== + +sass-embedded-linux-arm64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.83.4.tgz#057adf6e337357787331d40714cb8bba4a96dafe" + integrity sha512-E0zjsZX2HgESwyqw31EHtI39DKa7RgK7nvIhIRco1d0QEw227WnoR9pjH3M/ZQy4gQj3GKilOFHM5Krs/omeIA== + +sass-embedded-linux-arm@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.83.4.tgz#aea8b56f3844633f0bfaf13e0694c79511218fc0" + integrity sha512-nL90ryxX2lNmFucr9jYUyHHx21AoAgdCL1O5Ltx2rKg2xTdytAGHYo2MT5S0LIeKLa/yKP/hjuSvrbICYNDvtA== + +sass-embedded-linux-ia32@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.83.4.tgz#2cedba9f41be61ded3cede5abd16f8ec163d7f46" + integrity sha512-ew5HpchSzgAYbQoriRh8QhlWn5Kw2nQ2jHoV9YLwGKe3fwwOWA0KDedssvDv7FWnY/FCqXyymhLd6Bxae4Xquw== + +sass-embedded-linux-musl-arm64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.83.4.tgz#1c5f50c9df93abce7d5ffb4d86eed65b8ffba2f4" + integrity sha512-IzMgalf6MZOxgp4AVCgsaWAFDP/IVWOrgVXxkyhw29fyAEoSWBJH4k87wyPhEtxSuzVHLxKNbc8k3UzdWmlBFg== + +sass-embedded-linux-musl-arm@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.83.4.tgz#00f241dbc750ee73242bfde1ec5d64ef2d5d7956" + integrity sha512-0RrJRwMrmm+gG0VOB5b5Cjs7Sd+lhqpQJa6EJNEaZHljJokEfpE5GejZsGMRMIQLxEvVphZnnxl6sonCGFE/QQ== + +sass-embedded-linux-musl-ia32@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.83.4.tgz#27537a309d39f8e35a7dba34a3edc29a3ee16adf" + integrity sha512-LLb4lYbcxPzX4UaJymYXC+WwokxUlfTJEFUv5VF0OTuSsHAGNRs/rslPtzVBTvMeG9TtlOQDhku1F7G6iaDotA== + +sass-embedded-linux-musl-riscv64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.83.4.tgz#a32edf2ddb7f7d9b526e971e80cadef1e025cce8" + integrity sha512-zoKlPzD5Z13HKin1UGR74QkEy+kZEk2AkGX5RelRG494mi+IWwRuWCppXIovor9+BQb9eDWPYPoMVahwN5F7VA== + +sass-embedded-linux-musl-x64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.83.4.tgz#668b90b80bf35830c2f1ea2a47557d5e60842598" + integrity sha512-hB8+/PYhfEf2zTIcidO5Bpof9trK6WJjZ4T8g2MrxQh8REVtdPcgIkoxczRynqybf9+fbqbUwzXtiUao2GV+vQ== + +sass-embedded-linux-riscv64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.83.4.tgz#b7718df2adf1cbcb4c26609215018dd2e8bab595" + integrity sha512-83fL4n+oeDJ0Y4KjASmZ9jHS1Vl9ESVQYHMhJE0i4xDi/P3BNarm2rsKljq/QtrwGpbqwn8ujzOu7DsNCMDSHA== + +sass-embedded-linux-x64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.83.4.tgz#52e61bd582dfc56b8f638f2b9cfdb8a53db1e57e" + integrity sha512-NlnGdvCmTD5PK+LKXlK3sAuxOgbRIEoZfnHvxd157imCm/s2SYF/R28D0DAAjEViyI8DovIWghgbcqwuertXsA== + +sass-embedded-win32-arm64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.83.4.tgz#b6ca8f65177e24770e87e43ffea5868fea34de27" + integrity sha512-J2BFKrEaeSrVazU2qTjyQdAk+MvbzJeTuCET0uAJEXSKtvQ3AzxvzndS7LqkDPbF32eXAHLw8GVpwcBwKbB3Uw== + +sass-embedded-win32-ia32@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.83.4.tgz#94f8da72e253532f8d857516b99e1caf61e7b08f" + integrity sha512-uPAe9T/5sANFhJS5dcfAOhOJy8/l2TRYG4r+UO3Wp4yhqbN7bggPvY9c7zMYS0OC8tU/bCvfYUDFHYMCl91FgA== + +sass-embedded-win32-x64@1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.83.4.tgz#2179d4e2fc2f9086aecd64209a2d84f7d8e9edbe" + integrity sha512-C9fkDY0jKITdJFij4UbfPFswxoXN9O/Dr79v17fJnstVwtUojzVJWKHUXvF0Zg2LIR7TCc4ju3adejKFxj7ueA== + +sass-embedded@^1.83.4: + version "1.83.4" + resolved "https://registry.yarnpkg.com/sass-embedded/-/sass-embedded-1.83.4.tgz#9b05cdc22ae71a1b27b5996a39054ba59bebc04a" + integrity sha512-Hf2burRA/y5PGxsg6jB9UpoK/xZ6g/pgrkOcdl6j+rRg1Zj8XhGKZ1MTysZGtTPUUmiiErqzkP5+Kzp95yv9GQ== + dependencies: + "@bufbuild/protobuf" "^2.0.0" + buffer-builder "^0.2.0" + colorjs.io "^0.5.0" + immutable "^5.0.2" + rxjs "^7.4.0" + supports-color "^8.1.1" + sync-child-process "^1.0.2" + varint "^6.0.0" + optionalDependencies: + sass-embedded-android-arm "1.83.4" + sass-embedded-android-arm64 "1.83.4" + sass-embedded-android-ia32 "1.83.4" + sass-embedded-android-riscv64 "1.83.4" + sass-embedded-android-x64 "1.83.4" + sass-embedded-darwin-arm64 "1.83.4" + sass-embedded-darwin-x64 "1.83.4" + sass-embedded-linux-arm "1.83.4" + sass-embedded-linux-arm64 "1.83.4" + sass-embedded-linux-ia32 "1.83.4" + sass-embedded-linux-musl-arm "1.83.4" + sass-embedded-linux-musl-arm64 "1.83.4" + sass-embedded-linux-musl-ia32 "1.83.4" + sass-embedded-linux-musl-riscv64 "1.83.4" + sass-embedded-linux-musl-x64 "1.83.4" + sass-embedded-linux-riscv64 "1.83.4" + sass-embedded-linux-x64 "1.83.4" + sass-embedded-win32-arm64 "1.83.4" + sass-embedded-win32-ia32 "1.83.4" + sass-embedded-win32-x64 "1.83.4" + sass@1.83.1: version "1.83.1" resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.1.tgz#dee1ab94b47a6f9993d3195d36f556bcbda64846" @@ -8415,19 +8418,6 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" -simple-peer@^9.11.1: - version "9.11.1" - resolved "https://registry.yarnpkg.com/simple-peer/-/simple-peer-9.11.1.tgz#9814d5723f821b778b7fb011bdefcbd1e788e6cc" - integrity sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw== - dependencies: - buffer "^6.0.3" - debug "^4.3.2" - err-code "^3.0.1" - get-browser-rtc "^1.1.0" - queue-microtask "^1.2.3" - randombytes "^2.1.0" - readable-stream "^3.6.0" - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -8628,7 +8618,29 @@ stream-http@^3.2.0: readable-stream "^3.6.0" xtend "^4.0.2" -streamx@^2.15.0, streamx@^2.17.0, streamx@^2.20.1, streamx@^2.21.0: +streamx@^2.15.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.18.0.tgz#5bc1a51eb412a667ebfdcd4e6cf6a6fc65721ac7" + integrity sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ== + dependencies: + fast-fifo "^1.3.2" + queue-tick "^1.0.1" + text-decoder "^1.1.0" + optionalDependencies: + bare-events "^2.2.0" + +streamx@^2.17.0, streamx@^2.20.1: + version "2.20.2" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.20.2.tgz#6a8911959d6f307c19781a1d19ecd94b5f042d78" + integrity sha512-aDGDLU+j9tJcUdPGOaHmVF1u/hhI+CsGkT02V3OKlHDV7IukOI+nTWAGkiZEKCO35rWN1wIr4tS7YFr1f4qSvA== + dependencies: + fast-fifo "^1.3.2" + queue-tick "^1.0.1" + text-decoder "^1.1.0" + optionalDependencies: + bare-events "^2.2.0" + +streamx@^2.21.0: version "2.22.0" resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.0.tgz#cd7b5e57c95aaef0ff9b2aef7905afa62ec6e4a7" integrity sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw== @@ -8897,6 +8909,18 @@ symbol-observable@4.0.0: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== +sync-child-process@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/sync-child-process/-/sync-child-process-1.0.2.tgz#45e7c72e756d1243e80b547ea2e17957ab9e367f" + integrity sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA== + dependencies: + sync-message-port "^1.0.0" + +sync-message-port@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sync-message-port/-/sync-message-port-1.1.3.tgz#6055c565ee8c81d2f9ee5aae7db757e6d9088c0c" + integrity sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg== + synckit@^0.9.1: version "0.9.2" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.2.tgz#a3a935eca7922d48b9e7d6c61822ee6c3ae4ec62" @@ -9406,6 +9430,11 @@ validate-npm-package-name@^6.0.0: resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-6.0.0.tgz#3add966c853cfe36e0e8e6a762edd72ae6f1d6ac" integrity sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg== +varint@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== + "video.js@^6 || ^7", video.js@^7.19.2: version "7.21.6" resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.21.6.tgz#a42d817c42d8d91538b72197a0874aeb01c76ce9" @@ -9437,10 +9466,10 @@ videojs-vtt.js@^0.15.5: dependencies: global "^4.3.1" -vite-plugin-checker@^0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/vite-plugin-checker/-/vite-plugin-checker-0.7.2.tgz#093ffdf9ccf51b2c9eab7101480bd0217ae99536" - integrity sha512-xeYeJbG0gaCaT0QcUC4B2Zo4y5NR8ZhYenc5gPbttrZvraRFwkEADCYwq+BfEHl9zYz7yf85TxsiGoYwyyIjhw== +vite-plugin-checker@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/vite-plugin-checker/-/vite-plugin-checker-0.8.0.tgz#33419857a623b35c9483e4f603d4ca8b6984acde" + integrity sha512-UA5uzOGm97UvZRTdZHiQVYFnd86AVn8EVaD4L3PoVzxH+IZSfaAw14WGFwX9QS23UW3lV/5bVKZn6l0w+q9P0g== dependencies: "@babel/code-frame" "^7.12.13" ansi-escapes "^4.3.0" @@ -9457,15 +9486,15 @@ vite-plugin-checker@^0.7.2: vscode-languageserver-textdocument "^1.0.1" vscode-uri "^3.0.2" -vite-plugin-node-polyfills@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz#d0afcf82eb985fc02244620d7cec1ddd1c6e0864" - integrity sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA== +vite-plugin-node-polyfills@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.23.0.tgz#99d0d1524fa75ce5c7bb1fc8af30283379e9c684" + integrity sha512-4n+Ys+2bKHQohPBKigFlndwWQ5fFKwaGY6muNDMTb0fSQLyBzS+jjUNRZG9sKF0S/Go4ApG6LFnUGopjkILg3w== dependencies: "@rollup/plugin-inject" "^5.0.5" node-stdlib-browser "^1.2.0" -vite@6.0.11: +vite@6.0.11, vite@^6.0.11: version "6.0.11" resolved "https://registry.yarnpkg.com/vite/-/vite-6.0.11.tgz#224497e93e940b34c3357c9ebf2ec20803091ed8" integrity sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg== @@ -9476,17 +9505,6 @@ vite@6.0.11: optionalDependencies: fsevents "~2.3.3" -vite@^5.3.1: - version "5.4.14" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.14.tgz#ff8255edb02134df180dcfca1916c37a6abe8408" - integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA== - dependencies: - esbuild "^0.21.3" - postcss "^8.4.43" - rollup "^4.20.0" - optionalDependencies: - fsevents "~2.3.3" - vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" diff --git a/packages/node-utils/src/crypto.ts b/packages/node-utils/src/crypto.ts index 388d75574..ecab03457 100644 --- a/packages/node-utils/src/crypto.ts +++ b/packages/node-utils/src/crypto.ts @@ -7,3 +7,7 @@ export function sha256 (str: string | Buffer, encoding: BinaryToTextEncoding = ' export function sha1 (str: string | Buffer, encoding: BinaryToTextEncoding = 'hex') { return createHash('sha1').update(str).digest(encoding) } + +export function md5 (str: string | Buffer) { + return createHash('md5').update(str).digest() +} diff --git a/packages/node-utils/src/index.ts b/packages/node-utils/src/index.ts index 89f22e7d3..415293474 100644 --- a/packages/node-utils/src/index.ts +++ b/packages/node-utils/src/index.ts @@ -1,5 +1,6 @@ export * from './crypto.js' export * from './env.js' export * from './file.js' +export * from './p2p.js' export * from './path.js' export * from './uuid.js' diff --git a/packages/node-utils/src/p2p.ts b/packages/node-utils/src/p2p.ts new file mode 100644 index 000000000..ca6f909e9 --- /dev/null +++ b/packages/node-utils/src/p2p.ts @@ -0,0 +1,7 @@ +import { md5 } from './crypto.js' + +export function generateP2PMediaLoaderHash (input: string) { + // Create a string of 15 bytes, converted to base64 and then to ascii to have 20 characters + // See https://github.com/Novage/p2p-media-loader/issues/427 + return Buffer.from(md5(input).subarray(1).toString('base64'), 'utf-8').toString('hex') +} diff --git a/packages/tests/src/api/object-storage/videos.ts b/packages/tests/src/api/object-storage/videos.ts index bbfaab3eb..3c9e89e1a 100644 --- a/packages/tests/src/api/object-storage/videos.ts +++ b/packages/tests/src/api/object-storage/videos.ts @@ -20,7 +20,7 @@ import { generateHighBitrateVideo } from '@tests/shared/generate.js' import { MockObjectStorageProxy } from '@tests/shared/mock-servers/mock-object-storage.js' import { SQLCommand } from '@tests/shared/sql-command.js' import { checkPlaylistInfohash } from '@tests/shared/streaming-playlists.js' -import { checkWebTorrentWorks } from '@tests/shared/webtorrent.js' +import { checkWebTorrentWorks } from '@tests/shared/p2p.js' import bytes from 'bytes' import { expect } from 'chai' import { stat } from 'fs/promises' diff --git a/packages/tests/src/api/server/tracker.ts b/packages/tests/src/api/server/tracker.ts index 58e99ff65..9f703e6c3 100644 --- a/packages/tests/src/api/server/tracker.ts +++ b/packages/tests/src/api/server/tracker.ts @@ -7,7 +7,7 @@ import { PeerTubeServer, setAccessTokensToServers } from '@peertube/peertube-server-commands' -import { magnetUriDecode, magnetUriEncode } from '@tests/shared/webtorrent.js' +import { magnetUriDecode, magnetUriEncode } from '@tests/shared/p2p.js' import WebTorrent from 'webtorrent' describe('Test tracker', function () { diff --git a/packages/tests/src/api/transcoding/transcoder.ts b/packages/tests/src/api/transcoding/transcoder.ts index fb8099fd8..e1f9e05e9 100644 --- a/packages/tests/src/api/transcoding/transcoder.ts +++ b/packages/tests/src/api/transcoding/transcoder.ts @@ -18,7 +18,7 @@ import { waitJobs } from '@peertube/peertube-server-commands' import { canDoQuickTranscode } from '@peertube/peertube-server/core/lib/transcoding/transcoding-quick-transcode.js' -import { checkWebTorrentWorks } from '@tests/shared/webtorrent.js' +import { checkWebTorrentWorks } from '@tests/shared/p2p.js' import { expect } from 'chai' describe('Test video transcoding', function () { diff --git a/packages/tests/src/api/videos/multiple-servers.ts b/packages/tests/src/api/videos/multiple-servers.ts index f2fd483a7..de021dcf9 100644 --- a/packages/tests/src/api/videos/multiple-servers.ts +++ b/packages/tests/src/api/videos/multiple-servers.ts @@ -17,7 +17,7 @@ import { import { dateIsValid, testImageGeneratedByFFmpeg } from '@tests/shared/checks.js' import { checkTmpIsEmpty } from '@tests/shared/directories.js' import { checkVideoFilesWereRemoved, completeVideoCheck, saveVideoInServers } from '@tests/shared/videos.js' -import { checkWebTorrentWorks } from '@tests/shared/webtorrent.js' +import { checkWebTorrentWorks } from '@tests/shared/p2p.js' import Bluebird from 'bluebird' import { expect } from 'chai' import request from 'supertest' diff --git a/packages/tests/src/api/videos/video-static-file-privacy.ts b/packages/tests/src/api/videos/video-static-file-privacy.ts index 5577dfdb5..0b5c3f27b 100644 --- a/packages/tests/src/api/videos/video-static-file-privacy.ts +++ b/packages/tests/src/api/videos/video-static-file-privacy.ts @@ -16,7 +16,7 @@ import { } from '@peertube/peertube-server-commands' import { expectStartWith } from '@tests/shared/checks.js' import { checkVideoFileTokenReinjection } from '@tests/shared/streaming-playlists.js' -import { magnetUriDecode, parseTorrentVideo } from '@tests/shared/webtorrent.js' +import { magnetUriDecode, parseTorrentVideo } from '@tests/shared/p2p.js' import { expect } from 'chai' describe('Test video static file privacy', function () { diff --git a/packages/tests/src/cli/update-host.ts b/packages/tests/src/cli/update-host.ts index 30a7b17e4..10022086f 100644 --- a/packages/tests/src/cli/update-host.ts +++ b/packages/tests/src/cli/update-host.ts @@ -12,7 +12,7 @@ import { setDefaultVideoChannel, waitJobs } from '@peertube/peertube-server-commands' -import { parseTorrentVideo } from '@tests/shared/webtorrent.js' +import { parseTorrentVideo } from '@tests/shared/p2p.js' import { VideoPlaylistPrivacy } from '@peertube/peertube-models' describe('Test update host CLI', function () { diff --git a/packages/tests/src/shared/live.ts b/packages/tests/src/shared/live.ts index 179e49336..7507098e8 100644 --- a/packages/tests/src/shared/live.ts +++ b/packages/tests/src/shared/live.ts @@ -2,14 +2,13 @@ import { getVideoStreamDimensionsInfo, getVideoStreamFPS } from '@peertube/peertube-ffmpeg' import { LiveVideo, VideoResolution, VideoStreamingPlaylistType } from '@peertube/peertube-models' -import { sha1 } from '@peertube/peertube-node-utils' import { ObjectStorageCommand, PeerTubeServer } from '@peertube/peertube-server-commands' import { expect } from 'chai' import { pathExists } from 'fs-extra/esm' import { readdir } from 'fs/promises' import { join } from 'path' import { SQLCommand } from './sql-command.js' -import { checkLiveSegmentHash, checkResolutionsInMasterPlaylist } from './streaming-playlists.js' +import { checkLiveSegmentHash, checkPlaylistInfohash, checkResolutionsInMasterPlaylist } from './streaming-playlists.js' async function checkLiveCleanup (options: { server: PeerTubeServer @@ -169,13 +168,10 @@ async function testLiveVideoResolutions (options: { hlsPlaylist, withRetry: !!objectStorage // With object storage, the request may fail because of inconsistent data in S3 }) + } - if (originServer.internalServerNumber === server.internalServerNumber) { - const infohash = sha1(`2${hlsPlaylist.playlistUrl}+V${i}`) - const dbInfohashes = await sqlCommand.getPlaylistInfohash(hlsPlaylist.id) - - expect(dbInfohashes).to.include(infohash) - } + if (originServer.internalServerNumber === server.internalServerNumber) { + await checkPlaylistInfohash({ video, sqlCommand, files: resolutions.map(r => ({ resolution: { id: r } })) }) } } } diff --git a/packages/tests/src/shared/webtorrent.ts b/packages/tests/src/shared/p2p.ts similarity index 100% rename from packages/tests/src/shared/webtorrent.ts rename to packages/tests/src/shared/p2p.ts diff --git a/packages/tests/src/shared/streaming-playlists.ts b/packages/tests/src/shared/streaming-playlists.ts index 35229db86..62acaebd7 100644 --- a/packages/tests/src/shared/streaming-playlists.ts +++ b/packages/tests/src/shared/streaming-playlists.ts @@ -10,14 +10,14 @@ import { VideoStreamingPlaylist, VideoStreamingPlaylistType } from '@peertube/peertube-models' -import { sha1, sha256 } from '@peertube/peertube-node-utils' +import { generateP2PMediaLoaderHash, sha256 } from '@peertube/peertube-node-utils' import { makeRawRequest, PeerTubeServer } from '@peertube/peertube-server-commands' import { expect } from 'chai' import { basename, dirname, join } from 'path' import { expectStartWith } from './checks.js' +import { checkWebTorrentWorks } from './p2p.js' import { SQLCommand } from './sql-command.js' -import { hlsInfohashExist } from './tracker.js' -import { checkWebTorrentWorks } from './webtorrent.js' +import { checkTrackerInfohash } from './tracker.js' export async function checkSegmentHash (options: { server: PeerTubeServer @@ -72,16 +72,24 @@ export async function checkLiveSegmentHash (options: { export async function checkPlaylistInfohash (options: { video: VideoDetails sqlCommand: SQLCommand - files: unknown[] + files: { resolution: { id: number } }[] }) { const { sqlCommand, video, files } = options const hls = getHLS(video) + const version = 2 + for (let i = 0; i < files.length; i++) { - const infohash = sha1(`${2 + hls.playlistUrl}+V${i}`) + const str = files[0].resolution.id === VideoResolution.H_NOVIDEO && files.length !== 0 + ? `v${version}-${hls.playlistUrl}-secondary-0` + : `v${version}-${hls.playlistUrl}-main-${i}` + + const infohash = generateP2PMediaLoaderHash(str) const dbInfohashes = await sqlCommand.getPlaylistInfohash(hls.id) expect(dbInfohashes).to.include(infohash) + + await checkTrackerInfohash(video.account.host, infohash) } } @@ -298,40 +306,33 @@ export async function completeCheckHlsPlaylist (options: { const masterPlaylist = await server.streamingPlaylists.get({ url: hlsPlaylist.playlistUrl, token }) - let i = 0 for (const resolution of hlsResolutions) { expect(masterPlaylist).to.contain(`${resolution}.m3u8`) expect(masterPlaylist).to.contain(`${resolution}.m3u8`) - - const url = 'http://' + videoDetails.account.host - await hlsInfohashExist(url, hlsPlaylist.playlistUrl, i) - - i++ } } // Check resolution playlists - { - for (const resolution of hlsResolutions) { - const file = hlsFiles.find(f => f.resolution.id === resolution) - const playlistName = removeFragmentedMP4Ext(basename(file.fileUrl)) + '.m3u8' + for (const resolution of hlsResolutions) { + const file = hlsFiles.find(f => f.resolution.id === resolution) + const playlistName = removeFragmentedMP4Ext(basename(file.fileUrl)) + '.m3u8' - let url: string - if (objectStorageBaseUrl && requiresAuth) { - url = `${baseUrl}/object-storage-proxy/streaming-playlists/hls/${privatePath}${videoUUID}/${playlistName}` - } else if (objectStorageBaseUrl) { - url = `${objectStorageBaseUrl}hls/${videoUUID}/${playlistName}` - } else { - url = `${baseUrl}/static/streaming-playlists/hls/${privatePath}${videoUUID}/${playlistName}` - } - - const subPlaylist = await server.streamingPlaylists.get({ url, token }) - - expect(subPlaylist).to.match(new RegExp(`${uuidRegex}-${resolution}-fragmented.mp4`)) - expect(subPlaylist).to.contain(basename(file.fileUrl)) + let url: string + if (objectStorageBaseUrl && requiresAuth) { + url = `${baseUrl}/object-storage-proxy/streaming-playlists/hls/${privatePath}${videoUUID}/${playlistName}` + } else if (objectStorageBaseUrl) { + url = `${objectStorageBaseUrl}hls/${videoUUID}/${playlistName}` + } else { + url = `${baseUrl}/static/streaming-playlists/hls/${privatePath}${videoUUID}/${playlistName}` } + + const subPlaylist = await server.streamingPlaylists.get({ url, token }) + + expect(subPlaylist).to.match(new RegExp(`${uuidRegex}-${resolution}-fragmented.mp4`)) + expect(subPlaylist).to.contain(basename(file.fileUrl)) } + // Segment hash { let baseUrlAndPath: string if (objectStorageBaseUrl && requiresAuth) { @@ -353,6 +354,14 @@ export async function completeCheckHlsPlaylist (options: { }) } } + + // Info hashed + if (isOrigin) { + const sqlCommand = new SQLCommand(server) + + await checkPlaylistInfohash({ video: videoDetails, sqlCommand, files: hlsFiles }) + await sqlCommand.cleanup() + } } } diff --git a/packages/tests/src/shared/tracker.ts b/packages/tests/src/shared/tracker.ts index 6ab430456..8129dc387 100644 --- a/packages/tests/src/shared/tracker.ts +++ b/packages/tests/src/shared/tracker.ts @@ -1,12 +1,9 @@ -import { expect } from 'chai' -import { sha1 } from '@peertube/peertube-node-utils' import { makeGetRequest } from '@peertube/peertube-server-commands' +import { expect } from 'chai' -async function hlsInfohashExist (serverUrl: string, masterPlaylistUrl: string, fileNumber: number) { +export async function checkTrackerInfohash (serverUrl: string, infohash: string) { const path = '/tracker/announce' - const infohash = sha1(`2${masterPlaylistUrl}+V${fileNumber}`) - // From bittorrent-tracker const infohashBinary = escape(Buffer.from(infohash, 'hex').toString('binary')).replace(/[@*/+]/g, function (char) { return '%' + char.charCodeAt(0).toString(16).toUpperCase() @@ -21,7 +18,3 @@ async function hlsInfohashExist (serverUrl: string, masterPlaylistUrl: string, f expect(res.text).to.not.contain('failure') } - -export { - hlsInfohashExist -} diff --git a/packages/tests/src/shared/videos.ts b/packages/tests/src/shared/videos.ts index 723e169bd..6a66962d3 100644 --- a/packages/tests/src/shared/videos.ts +++ b/packages/tests/src/shared/videos.ts @@ -29,7 +29,7 @@ import { tmpdir } from 'os' import { basename, join } from 'path' import { dateIsValid, expectStartWith, testImageGeneratedByFFmpeg } from './checks.js' import { completeCheckHlsPlaylist } from './streaming-playlists.js' -import { checkWebTorrentWorks } from './webtorrent.js' +import { checkWebTorrentWorks } from './p2p.js' export async function completeWebVideoFilesCheck (options: { server: PeerTubeServer diff --git a/scripts/build/client.sh b/scripts/build/client.sh index 357925e7f..41ab8b847 100755 --- a/scripts/build/client.sh +++ b/scripts/build/client.sh @@ -47,9 +47,12 @@ languages=( ["kab"]="kab" ) -cd client -rm -rf ./dist +rm -rf ./client/dist + +npm run build:embed + +cd client # Don't build other languages if --light arg is provided if [ -z ${1+x} ] || ([ "$1" != "--light" ] && [ "$1" != "--analyze-bundle" ]); then @@ -88,7 +91,5 @@ else --configuration production --stats-json $additionalParams fi -cd ../ && npm run build:embed && cd client/ - # Copy runtime locales cp -r "./src/locale" "./dist/locale" diff --git a/scripts/build/embed.sh b/scripts/build/embed.sh index 70c5fc4cf..6c88f7505 100755 --- a/scripts/build/embed.sh +++ b/scripts/build/embed.sh @@ -2,4 +2,6 @@ set -eu +(cd client/src/standalone/player && npm run build) + cd client && ./node_modules/.bin/vite -c ./src/standalone/videos/vite.config.mjs build --mode=production diff --git a/scripts/client-report.sh b/scripts/client-report.sh index c41e00150..5ecb71124 100755 --- a/scripts/client-report.sh +++ b/scripts/client-report.sh @@ -3,5 +3,6 @@ set -eu npm run concurrently -- -k \ + "cd client/src/standalone/player/ && npx vite-bundle-visualizer" \ "cd client/src/standalone/videos/ && npx vite-bundle-visualizer" \ "cd client && npx esbuild-visualizer --metadata ./dist/en-US/stats.json --open" diff --git a/scripts/dev/client.sh b/scripts/dev/client.sh index 2f0b367d4..854bedec7 100755 --- a/scripts/dev/client.sh +++ b/scripts/dev/client.sh @@ -2,21 +2,27 @@ set -eu +(cd client/src/standalone/player && npm run build) + clientConfiguration="hmr" if [ ! -z ${2+x} ] && [ "$2" = "--ar-locale" ]; then clientConfiguration="ar-locale" fi +embedCommand="cd client/src/standalone/player && npm run dev" clientCommand="cd client && node --max_old_space_size=4096 node_modules/.bin/ng serve --proxy-config proxy.config.json --hmr --configuration $clientConfiguration --host 0.0.0.0 --port 3000" serverCommand="NODE_ENV=dev node dist/server" if [ ! -z ${1+x} ] && [ "$1" = "--skip-server" ]; then - eval $clientCommand + node node_modules/.bin/concurrently -k \ + "$embedCommand" \ + "$clientCommand" else npm run build:server node node_modules/.bin/concurrently -k \ + "$embedCommand" \ "$clientCommand" \ "$serverCommand" fi diff --git a/scripts/dev/embed.sh b/scripts/dev/embed.sh index 845036eff..b13db57aa 100755 --- a/scripts/dev/embed.sh +++ b/scripts/dev/embed.sh @@ -3,7 +3,9 @@ set -eu npm run build:server -- --incremental +(cd client/src/standalone/player && npm run build) npm run concurrently -- -k \ + "cd client/src/standalone/player && npm run dev" \ "cd client && ./node_modules/.bin/vite -c ./src/standalone/videos/vite.config.mjs dev" \ "NODE_ENV=dev npm start" diff --git a/server/core/controllers/tracker.ts b/server/core/controllers/tracker.ts index dbcc884d2..ea6dc3706 100644 --- a/server/core/controllers/tracker.ts +++ b/server/core/controllers/tracker.ts @@ -10,7 +10,7 @@ import { LRU_CACHE, TRACKER_RATE_LIMITS } from '../initializers/constants.js' import { VideoFileModel } from '../models/video/video-file.js' import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist.js' -const trackerRouter = express.Router() +export const trackerRouter = express.Router() const blockedIPs = new LRUCache({ max: LRU_CACHE.TRACKER_IPS.MAX_SIZE, @@ -30,13 +30,9 @@ const trackerServer = new TrackerServer({ return cb(new Error('Tracker is disabled on this instance.')) } - let ip: string - - if (params.type === 'ws') { - ip = params.ip - } else { - ip = params.httpReq.ip - } + const ip = params.type === 'ws' + ? params.ip + : params.httpReq.ip const key = ip + '-' + infoHash @@ -50,12 +46,13 @@ const trackerServer = new TrackerServer({ try { if (CONFIG.TRACKER.PRIVATE === false) return cb() - const videoFileExists = await VideoFileModel.doesInfohashExistCached(infoHash) - if (videoFileExists === true) return cb() - const playlistExists = await VideoStreamingPlaylistModel.doesInfohashExistCached(infoHash) if (playlistExists === true) return cb() + // Classic infohash (not p2p-media-loader custom one), use arg directly + const videoFileExists = await VideoFileModel.doesInfohashExistCached(infoHash) + if (videoFileExists === true) return cb() + cb(new Error(`Unknown infoHash ${infoHash} requested by ip ${ip}`)) // Close socket connection and block IP for a few time @@ -92,7 +89,7 @@ const onHttpRequest = trackerServer.onHttpRequest.bind(trackerServer) trackerRouter.get('/tracker/announce', (req, res) => onHttpRequest(req, res, { action: 'announce' })) trackerRouter.get('/tracker/scrape', (req, res) => onHttpRequest(req, res, { action: 'scrape' })) -function createWebsocketTrackerServer (app: express.Application) { +export function createWebsocketTrackerServer (app: express.Application) { const server = createServer(app) const wss = new WebSocketServer({ noServer: true }) @@ -124,12 +121,7 @@ function createWebsocketTrackerServer (app: express.Application) { } // --------------------------------------------------------------------------- - -export { - trackerRouter, - createWebsocketTrackerServer -} - +// Private // --------------------------------------------------------------------------- function runPeersChecker () { diff --git a/server/core/initializers/constants.ts b/server/core/initializers/constants.ts index d748a1f1c..8c86281d2 100644 --- a/server/core/initializers/constants.ts +++ b/server/core/initializers/constants.ts @@ -423,7 +423,7 @@ export const CONSTRAINTS_FIELDS = { } }, EXTNAME: [] as string[], - INFO_HASH: { min: 40, max: 40 }, // Length, info hash is 20 bytes length but we represent it in hexadecimal so 20 * 2 + INFO_HASH: { min: 10, max: 100 }, DURATION: { min: 0 }, // Number TAGS: { min: 0, max: 5 }, // Number of total tags TAG: { min: 2, max: 30 }, // Length @@ -1112,7 +1112,9 @@ export const TRACKER_RATE_LIMITS = { BLOCK_IP_LIFETIME: parseDurationToMs('3 minutes') } -export const P2P_MEDIA_LOADER_PEER_VERSION = 2 +// We use -2 instead of 2 because of historical reason +// When p2p-media-loader bumps to v3, we'll be able to switch to it +export const P2P_MEDIA_LOADER_PEER_VERSION = -2 // --------------------------------------------------------------------------- diff --git a/server/core/lib/activitypub/videos/shared/object-to-model-attributes.ts b/server/core/lib/activitypub/videos/shared/object-to-model-attributes.ts index 7d6279b81..1e23216d0 100644 --- a/server/core/lib/activitypub/videos/shared/object-to-model-attributes.ts +++ b/server/core/lib/activitypub/videos/shared/object-to-model-attributes.ts @@ -167,7 +167,7 @@ export function getStreamingPlaylistAttributesFromObject (video: MVideoId, video for (const playlistUrlObject of playlistUrls) { const segmentsSha256UrlObject = playlistUrlObject.tag.find(isAPPlaylistSegmentHashesUrlObject) - const files: unknown[] = playlistUrlObject.tag.filter(u => isAPVideoUrlObject(u)) + const files = playlistUrlObject.tag.filter(u => isAPVideoUrlObject(u)) const attribute = { type: VideoStreamingPlaylistType.HLS, diff --git a/server/core/lib/hls.ts b/server/core/lib/hls.ts index 87f503eea..7e3cb8b26 100644 --- a/server/core/lib/hls.ts +++ b/server/core/lib/hls.ts @@ -24,18 +24,23 @@ import { VideoPathManager } from './video-path-manager.js' const lTags = loggerTagsFactory('hls') export async function updateStreamingPlaylistsInfohashesIfNeeded () { - const playlistsToUpdate = await VideoStreamingPlaylistModel.listByIncorrectPeerVersion() + const playlistsToUpdateIds = await VideoStreamingPlaylistModel.listByIncorrectPeerVersion() // Use separate SQL queries, because we could have many videos to update - for (const playlist of playlistsToUpdate) { - await sequelizeTypescript.transaction(async t => { - const videoFiles = await VideoFileModel.listByStreamingPlaylist(playlist.id, t) + for (const playlistId of playlistsToUpdateIds) { + try { + await sequelizeTypescript.transaction(async t => { + const playlist = await VideoStreamingPlaylistModel.loadWithVideo(playlistId, t) + const videoFiles = await VideoFileModel.listByStreamingPlaylist(playlistId, t) - playlist.assignP2PMediaLoaderInfoHashes(playlist.Video, videoFiles) - playlist.p2pMediaLoaderPeerVersion = P2P_MEDIA_LOADER_PEER_VERSION + playlist.assignP2PMediaLoaderInfoHashes(playlist.Video, videoFiles) + playlist.p2pMediaLoaderPeerVersion = P2P_MEDIA_LOADER_PEER_VERSION - await playlist.save({ transaction: t }) - }) + await playlist.save({ transaction: t }) + }) + } catch (err) { + logger.error(`Cannot update streaming playlist infohash of playlist id ${playlistId}`, { err }) + } } } diff --git a/server/core/lib/live/shared/muxing-session.ts b/server/core/lib/live/shared/muxing-session.ts index ca6743103..45d37cf5f 100644 --- a/server/core/lib/live/shared/muxing-session.ts +++ b/server/core/lib/live/shared/muxing-session.ts @@ -227,7 +227,7 @@ class MuxingSession extends EventEmitter { this.streamingPlaylist.playlistUrl = url } - this.streamingPlaylist.assignP2PMediaLoaderInfoHashes(this.videoLive.Video, this.allResolutions) + this.streamingPlaylist.assignP2PMediaLoaderInfoHashes(this.videoLive.Video, this.allResolutions.map(r => ({ height: r }))) await this.streamingPlaylist.save() } catch (err) { diff --git a/server/core/models/video/video-file.ts b/server/core/models/video/video-file.ts index 9979078ec..2e9ce534f 100644 --- a/server/core/models/video/video-file.ts +++ b/server/core/models/video/video-file.ts @@ -354,23 +354,17 @@ export class VideoFileModel extends SequelizeModel { const query = { include: [ { - model: VideoModel.unscoped(), + model: VideoStreamingPlaylistModel.unscoped(), required: true, - include: [ - { - model: VideoStreamingPlaylistModel.unscoped(), - required: true, - where: { - id: streamingPlaylistId - } - } - ] + where: { + id: streamingPlaylistId + } } ], transaction } - return VideoFileModel.findAll(query) + return VideoFileModel.findAll(query) } static getStats () { diff --git a/server/core/models/video/video-streaming-playlist.ts b/server/core/models/video/video-streaming-playlist.ts index 0f463969b..61b7a250a 100644 --- a/server/core/models/video/video-streaming-playlist.ts +++ b/server/core/models/video/video-streaming-playlist.ts @@ -5,7 +5,7 @@ import { type FileStorageType, type VideoStreamingPlaylistType_Type } from '@peertube/peertube-models' -import { sha1 } from '@peertube/peertube-node-utils' +import { generateP2PMediaLoaderHash } from '@peertube/peertube-node-utils' import { logger } from '@server/helpers/logger.js' import { CONFIG } from '@server/initializers/config.js' import { getHLSPrivateFileUrl, getObjectStoragePublicFileUrl } from '@server/lib/object-storage/index.js' @@ -141,12 +141,19 @@ export class VideoStreamingPlaylistModel extends SequelizeModel f.height === 0)) { + hashes.push(generateP2PMediaLoaderHash(`v${version}-${playlistUrl}-secondary-0`)) } logger.debug('Assigned P2P Media Loader info hashes', { playlistUrl, hashes }) @@ -154,22 +161,18 @@ export class VideoStreamingPlaylistModel extends SequelizeModel r.id) } static loadWithVideoAndFiles (id: number) { @@ -188,14 +191,15 @@ export class VideoStreamingPlaylistModel extends SequelizeModel(id, options) } - static loadWithVideo (id: number) { + static loadWithVideo (id: number, transaction?: Transaction) { const options = { include: [ { model: VideoModel.unscoped(), required: true } - ] + ], + transaction } return VideoStreamingPlaylistModel.findByPk(id, options) @@ -242,7 +246,7 @@ export class VideoStreamingPlaylistModel extends SequelizeModel