More progress

This commit is contained in:
WardPearce
2025-02-23 23:55:29 +13:00
parent d3fd0dd71f
commit 3e1b3fc0c4
4 changed files with 63 additions and 47 deletions
@@ -1,21 +1,41 @@
import { goto } from "$app/navigation";
import { Capacitor } from "@capacitor/core";
import { capacitorFetch } from "./capacitorFetch";
export const localProxy = 'http://localhost:3000/';
if (Capacitor.getPlatform() === 'android') {
const originalFetch = window.fetch;
window.fetch = async (
requestInput: string | URL | Request, requestOptions?: RequestInit
): Promise<Response> => {
if (requestInput.toString().startsWith(localProxy)) {
return originalFetch(requestInput, requestOptions);
const corsProxyUrl: string = 'http://localhost:3000/';
window.fetch = async (requestInput: string | URL | Request, requestOptions?: RequestInit): Promise<Response> => {
let requestUrl: string;
if (typeof requestInput === 'string') {
requestUrl = requestInput;
} else if ('url' in requestInput) {
requestUrl = requestInput.url;
} else {
requestUrl = requestInput.toString();
}
return capacitorFetch(requestInput, requestOptions);
if (!requestUrl.startsWith(corsProxyUrl) && !requestUrl.startsWith('/') && !requestUrl.startsWith('blob:')) {
requestInput = corsProxyUrl + requestUrl;
}
// Use the original fetch with the proxied URL and options
return originalFetch(requestInput, requestOptions);
};
const currentOrigin: string = window.location.protocol + '//' + window.location.host;
const originalXhrOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (...args: any[]): void {
const targetOriginMatch = /^https?:\/\/([^\/]+)/i.exec(args[1]);
if (targetOriginMatch && targetOriginMatch[0].toLowerCase() !== currentOrigin) {
args[1] = corsProxyUrl + args[1];
}
/* @ts-ignore */
return originalXhrOpen.apply(this, args);
};
setTimeout(() => goto('/', { replaceState: true }), 10);
}
}
-2
View File
@@ -1,4 +1,3 @@
import type { YT } from "youtubei.js";
export interface Image {
url: string;
@@ -101,7 +100,6 @@ export interface VideoPlay extends Video {
captions: Captions[];
storyboards?: StoryBoard[];
fallbackPatch?: 'youtubejs' | 'piped';
youtubeJsPatchInfo?: YT.VideoInfo;
}
export interface StoryBoard {
+27 -31
View File
@@ -1,6 +1,5 @@
<script lang="ts">
import { page } from '$app/stores';
import { localProxy } from '$lib/android/http/androidRequests';
import { getBestThumbnail } from '$lib/images';
import { padTime, videoLength } from '$lib/time';
import { Capacitor } from '@capacitor/core';
@@ -25,6 +24,7 @@
playerDefaultLanguage,
playerProxyVideosStore,
playerSavePlaybackPositionStore,
poTokenCacheStore,
sponsorBlockCategoriesStore,
sponsorBlockDisplayToastStore,
sponsorBlockStore,
@@ -80,34 +80,31 @@
await player.attach(playerElement);
if (data.video.youtubeJsPatchInfo) {
player.configure({
streaming: {
bufferingGoal:
(data.video.youtubeJsPatchInfo.page[0].player_config?.media_common_config
.dynamic_readahead_config.max_read_ahead_media_time_ms || 0) / 1000,
rebufferingGoal:
(data.video.youtubeJsPatchInfo.page[0].player_config?.media_common_config
.dynamic_readahead_config.read_ahead_growth_rate_ms || 0) / 1000,
bufferBehind: 300,
autoLowLatencyMode: true
},
abr: {
enabled: true,
restrictions: {
maxBandwidth: Number(
data.video.youtubeJsPatchInfo.page[0].player_config?.stream_selection_config
.max_bitrate
)
}
}
});
player.configure({
streaming: {
bufferingGoal: 180,
rebufferingGoal: 0.02,
bufferBehind: 300
},
manifest: {
// disableVideo: format === 'audio',
segmentRelativeVttTiming: true
},
abr: {
enabled: false,
restrictToElementSize: true
},
autoShowText: shaka.config.AutoShowText.NEVER,
preferredDecodingAttributes: !data.video.hlsUrl ? ['smooth', 'powerEfficient'] : []
});
if (data.video.fallbackPatch === 'youtubejs') {
const networkingEngine = player.getNetworkingEngine();
if (!networkingEngine) return;
// Nased off the following
// Based off the following
// https://github.com/FreeTubeApp/FreeTube/blob/d270c9e251a433f1e4246a3f6a37acef707d22aa/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js#L1206
// https://github.com/LuanRT/BgUtils/blob/6b121166be1ccb0b952dee1bdac488808365ae6b/examples/browser/web/src/main.ts#L293
@@ -117,18 +114,17 @@
if (url.hostname.endsWith('.googlevideo.com') && url.pathname === '/videoplayback') {
request.method = 'POST';
request.body = new Uint8Array([0x78, 0]);
request.body = new Uint8Array([120, 0]);
if (request.headers.Range) {
request.uris[0] += `&range=${request.headers.Range.split('=')[1]}`;
url.searchParams.set('range', request.headers.Range.split('=')[1]);
url.searchParams.set('pot', get(poTokenCacheStore));
url.searchParams.set('ump', '1');
url.searchParams.set('srfvp', '1');
delete request.headers.Range;
}
if (Capacitor.getPlatform() === 'android') {
request.uris[0] = localProxy + url.toString();
}
request.uris[0] += '&alr=yes';
request.uris[0] = url.toString();
}
}
});
+6 -4
View File
@@ -1,3 +1,4 @@
import { capacitorFetch } from '$lib/android/http/capacitorFetch';
import type { AdaptiveFormats, Captions, Image, StoryBoard, Thumbnail, VideoBase, VideoPlay } from '$lib/api/model';
import { interfaceRegionStore, poTokenCacheStore } from '$lib/store';
import { numberWithCommas } from '$lib/time';
@@ -13,10 +14,12 @@ type WebPoMinter = {
botguardClient?: BG.BotGuardClient;
};
const fetchClient = Capacitor.getPlatform() === 'android' ? capacitorFetch : fetch;
async function getWebPoMinter(): Promise<WebPoMinter> {
const requestKey = 'O43z0dpjhgX20SCx4KAo';
const challengeResponse = await fetch(buildURL('Create', true), {
const challengeResponse = await fetchClient(buildURL('Create', true), {
method: 'POST',
headers: {
'content-type': 'application/json+protobuf',
@@ -53,7 +56,7 @@ async function getWebPoMinter(): Promise<WebPoMinter> {
const webPoSignalOutput: WebPoSignalOutput = [];
const botguardResponse = await botguardClient.snapshot({ webPoSignalOutput });
const integrityTokenResponse = await fetch(buildURL('GenerateIT', true), {
const integrityTokenResponse = await fetchClient(buildURL('GenerateIT', true), {
method: 'POST',
headers: {
'content-type': 'application/json+protobuf',
@@ -88,7 +91,7 @@ export async function patchYoutubeJs(videoId: string): Promise<VideoPlay> {
}
const youtube = await Innertube.create({
fetch: fetch,
fetch: fetchClient,
generate_session_locally: true,
cache: new UniversalCache(false),
location: get(interfaceRegionStore)
@@ -252,6 +255,5 @@ export async function patchYoutubeJs(videoId: string): Promise<VideoPlay> {
keywords: video.basic_info.keywords || [],
allowedRegions: [],
fallbackPatch: 'youtubejs',
youtubeJsPatchInfo: video
};
}