More progress
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user