From c67080bf55bd0e2da29870b0c56e525c2768bf3e Mon Sep 17 00:00:00 2001 From: WardPearce Date: Tue, 19 Aug 2025 18:10:26 +1200 Subject: [PATCH] Fix for companion use on Android --- materialious/src/lib/android/youtube/dash.ts | 35 +++++++++++++------ materialious/src/lib/components/Player.svelte | 6 +++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/materialious/src/lib/android/youtube/dash.ts b/materialious/src/lib/android/youtube/dash.ts index 1ba89832..a17d0d02 100644 --- a/materialious/src/lib/android/youtube/dash.ts +++ b/materialious/src/lib/android/youtube/dash.ts @@ -1,22 +1,37 @@ export async function dashManifestDomainInclusion(manifestUrl: string): Promise { /* If on android, must manually format dash manifest to include URL. */ - const response = await fetch(manifestUrl, { + // Must fetch the headers of the request + // using our custom android proxy logic + const respIvg = await fetch(manifestUrl, { method: 'GET', - redirect: 'follow' + headers: { + __custom_return: 'json-headers', + __redirect: 'manual' + } }); - if (!response.ok) { - throw Error('Unable to fetch manifest'); + if (!respIvg.ok) { + throw Error('Unable to make request to Invidious'); } - const finalUrl = response.url; - const manifestText = await response.text(); + const ivgHeaders = await respIvg.json(); + // If location isn't present, then use base manifest URL. + const companionUrl = 'location' in ivgHeaders ? ivgHeaders['location'] : manifestUrl; + + const respCompanion = await fetch(companionUrl, { + method: 'GET' + }); + + if (!respCompanion.ok) { + throw Error('Unable to make request to Companion'); + } + + const manifestText = await respCompanion.text(); const parser = new DOMParser(); const xmlDoc = parser.parseFromString(manifestText, 'application/xml'); - // Find all BaseURL elements const baseUrlElements = xmlDoc.getElementsByTagName('BaseURL'); for (let i = 0; i < baseUrlElements.length; i++) { @@ -24,8 +39,8 @@ export async function dashManifestDomainInclusion(manifestUrl: string): Promise< const baseUrlValue = baseUrlElement.textContent; if (baseUrlValue && (baseUrlValue.startsWith('/') || !baseUrlValue.includes('://'))) { - const finalUrlObj = new URL(finalUrl); - const baseDomain = `${finalUrlObj.protocol}//${finalUrlObj.host}`; + const companionUrlObj = new URL(companionUrl); + const baseDomain = `${companionUrlObj.protocol}//${companionUrlObj.host}`; const resolvedUrl = new URL(baseUrlValue, baseDomain).href; baseUrlElement.textContent = resolvedUrl; } @@ -34,7 +49,5 @@ export async function dashManifestDomainInclusion(manifestUrl: string): Promise< const serializer = new XMLSerializer(); const updatedManifest = serializer.serializeToString(xmlDoc); - console.log(updatedManifest); - return `data:application/dash+xml;base64,${btoa(updatedManifest)}`; } diff --git a/materialious/src/lib/components/Player.svelte b/materialious/src/lib/components/Player.svelte index c5a89631..d5ec5a24 100644 --- a/materialious/src/lib/components/Player.svelte +++ b/materialious/src/lib/components/Player.svelte @@ -401,7 +401,11 @@ dashUrl += '?local=true'; } - if (Capacitor.getPlatform() === 'android' && $playerProxyVideosStore) { + if ( + Capacitor.getPlatform() === 'android' && + $playerProxyVideosStore && + !data.video.fallbackPatch + ) { const manifest = await dashManifestDomainInclusion(dashUrl); await player.load(manifest, await getLastPlayPos()); } else {