From 7af58dd9e842c96571c8f1c7bc852fd7a706b5bf Mon Sep 17 00:00:00 2001 From: Jorrin <43169049+JorrinKievit@users.noreply.github.com> Date: Tue, 27 Feb 2024 23:19:40 +0100 Subject: [PATCH 1/2] prepare stream for all domains in a hls playlist --- pnpm-lock.yaml | 1 + src/backend/extension/messaging.ts | 5 ++++ src/backend/extension/streams.ts | 4 +-- src/components/player/display/base.ts | 28 +++++++++++++++++-- .../player/utils/convertRunoutputToSource.ts | 2 ++ src/stores/player/utils/qualities.ts | 3 ++ 6 files changed, 39 insertions(+), 4 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2ded1fb4..0e19baec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7359,6 +7359,7 @@ packages: /workbox-google-analytics@7.0.0: resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained dependencies: workbox-background-sync: 7.0.0 workbox-core: 7.0.0 diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index 3204d541..c280f9bd 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -6,6 +6,11 @@ import { import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; import { ExtensionMakeRequestResponse } from "@/backend/extension/plasmo"; +export const RULE_IDS = { + PREPARE_STREAM: 1, + SET_DOMAINS_HLS: 2, +}; + // for some reason, about 500 ms is needed after // page load before the extension starts responding properly const isExtensionReady = new Promise((resolve) => { diff --git a/src/backend/extension/streams.ts b/src/backend/extension/streams.ts index 588718af..af535f38 100644 --- a/src/backend/extension/streams.ts +++ b/src/backend/extension/streams.ts @@ -1,6 +1,6 @@ import { Stream } from "@movie-web/providers"; -import { setDomainRule } from "@/backend/extension/messaging"; +import { RULE_IDS, setDomainRule } from "@/backend/extension/messaging"; function extractDomain(url: string): string | null { try { @@ -36,7 +36,7 @@ function buildHeadersFromStream(stream: Stream): Record { export async function prepareStream(stream: Stream) { await setDomainRule({ - ruleId: 1, + ruleId: RULE_IDS.PREPARE_STREAM, targetDomains: extractDomainsFromStream(stream), requestHeaders: buildHeadersFromStream(stream), }); diff --git a/src/components/player/display/base.ts b/src/components/player/display/base.ts index 9b163363..4d850923 100644 --- a/src/components/player/display/base.ts +++ b/src/components/player/display/base.ts @@ -1,6 +1,11 @@ import fscreen from "fscreen"; import Hls, { Level } from "hls.js"; +import { + RULE_IDS, + isExtensionActiveCached, + setDomainRule, +} from "@/backend/extension/messaging"; import { DisplayInterface, DisplayInterfaceEvents, @@ -31,8 +36,8 @@ const levelConversionMap: Record = { 480: "480", }; -function hlsLevelToQuality(level: Level): SourceQuality | null { - return levelConversionMap[level.height] ?? null; +function hlsLevelToQuality(level?: Level): SourceQuality | null { + return levelConversionMap[level?.height ?? 0] ?? null; } function qualityToHlsLevel(quality: SourceQuality): number | null { @@ -144,6 +149,25 @@ export function makeVideoElementDisplayInterface(): DisplayInterface { if (!hls) return; reportLevels(); setupQualityForHls(); + + if (isExtensionActiveCached()) { + hls.on(Hls.Events.LEVEL_LOADED, async (_, data) => { + console.log(data); + const chunkUrlsDomains = data.details.fragments + .map((v) => v.url) + .map((v) => new URL(v).hostname); + const chunkUrls = [...new Set(chunkUrlsDomains)]; + + await setDomainRule({ + ruleId: RULE_IDS.SET_DOMAINS_HLS, + targetDomains: chunkUrls, + requestHeaders: { + ...src.preferredHeaders, + ...src.headers, + }, + }); + }); + } }); hls.on(Hls.Events.LEVEL_SWITCHED, () => { if (!hls) return; diff --git a/src/components/player/utils/convertRunoutputToSource.ts b/src/components/player/utils/convertRunoutputToSource.ts index f54c5396..3fd07232 100644 --- a/src/components/player/utils/convertRunoutputToSource.ts +++ b/src/components/player/utils/convertRunoutputToSource.ts @@ -28,6 +28,7 @@ export function convertRunoutputToSource(out: { return { type: "hls", url: out.stream.playlist, + headers: out.stream.headers, preferredHeaders: out.stream.preferredHeaders, }; } @@ -50,6 +51,7 @@ export function convertRunoutputToSource(out: { return { type: "file", qualities, + headers: out.stream.headers, preferredHeaders: out.stream.preferredHeaders, }; } diff --git a/src/stores/player/utils/qualities.ts b/src/stores/player/utils/qualities.ts index e5140d53..afd90d25 100644 --- a/src/stores/player/utils/qualities.ts +++ b/src/stores/player/utils/qualities.ts @@ -14,6 +14,7 @@ export type SourceFileStream = { export type LoadableSource = { type: StreamType; url: string; + headers?: Stream["headers"]; preferredHeaders?: Stream["preferredHeaders"]; }; @@ -21,11 +22,13 @@ export type SourceSliceSource = | { type: "file"; qualities: Partial>; + headers?: Stream["headers"]; preferredHeaders?: Stream["preferredHeaders"]; } | { type: "hls"; url: string; + headers?: Stream["headers"]; preferredHeaders?: Stream["preferredHeaders"]; }; From d20ab4be08ba25b1b5b23018faa5440a53edbeb1 Mon Sep 17 00:00:00 2001 From: Jorrin <43169049+JorrinKievit@users.noreply.github.com> Date: Tue, 27 Feb 2024 23:30:00 +0100 Subject: [PATCH 2/2] double map into one --- src/components/player/display/base.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/player/display/base.ts b/src/components/player/display/base.ts index 4d850923..a12661ab 100644 --- a/src/components/player/display/base.ts +++ b/src/components/player/display/base.ts @@ -152,10 +152,9 @@ export function makeVideoElementDisplayInterface(): DisplayInterface { if (isExtensionActiveCached()) { hls.on(Hls.Events.LEVEL_LOADED, async (_, data) => { - console.log(data); - const chunkUrlsDomains = data.details.fragments - .map((v) => v.url) - .map((v) => new URL(v).hostname); + const chunkUrlsDomains = data.details.fragments.map( + (v) => new URL(v.url).hostname, + ); const chunkUrls = [...new Set(chunkUrlsDomains)]; await setDomainRule({