Started youtube js backup

This commit is contained in:
WardPearce
2024-09-17 19:01:49 +12:00
parent 3864b2aab0
commit 7d4a98c475
4 changed files with 2724 additions and 14 deletions
+2632 -7
View File
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -26,16 +26,20 @@
"@typescript-eslint/eslint-plugin": "^7.16.0",
"@typescript-eslint/parser": "^7.18.0",
"@vite-pwa/sveltekit": "^0.6.5",
"buffer": "^6.0.3",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.44.0",
"i": "^0.3.7",
"npm": "^10.8.3",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.6",
"svelte": "^4.2.19",
"svelte-check": "^3.8.6",
"tslib": "^2.7.0",
"typescript": "^5.5.4",
"vite": "^5.4.5"
"vite": "^5.4.5",
"youtubei.js": "^10.4.0"
},
"type": "module",
"dependencies": {
@@ -62,4 +66,4 @@
"svelte-persisted-store": "^0.11.0",
"vidstack": "^1.12.9"
}
}
}
+82 -1
View File
@@ -1,3 +1,5 @@
import { numberWithCommas } from '$lib/misc';
import { Capacitor } from '@capacitor/core';
import { get } from 'svelte/store';
import {
authStore,
@@ -16,13 +18,16 @@ import type {
Comments,
DeArrow,
Feed,
Image,
Playlist,
PlaylistPage,
ReturnYTDislikes,
SearchSuggestion,
Subscription,
SynciousProgressModel,
Thumbnail,
Video,
VideoBase,
VideoPlay
} from './model';
@@ -68,7 +73,83 @@ export async function getPopular(): Promise<Video[]> {
}
export async function getVideo(videoId: string, local: boolean = false): Promise<VideoPlay> {
const resp = await fetchErrorHandle(await fetch(setRegion(buildPath(`videos/${videoId}?local=${local}`))));
const resp = await fetch(setRegion(buildPath(`videos/${videoId}?local=${local}`)));
if (!resp.ok && Capacitor.getPlatform() !== 'web') {
const innertube = (await import('youtubei.js')).Innertube;
const youtube = await innertube.create();
const video = await youtube.getInfo(videoId);
if (!video.primary_info || !video.secondary_info) {
throw new Error('Unable to pull video info from youtube.js');
}
const manifest = await video.toDash();
const dashUri = URL.createObjectURL(new Blob([manifest], { type: 'application/dash+xml;charset=utf8' }));
const descString = video.secondary_info.description.toString();
let authorThumbnails: Image[];
if (video.basic_info.channel_id) {
authorThumbnails = (await youtube.getChannel(video.basic_info.channel_id)).metadata.avatar as Image[];
} else {
authorThumbnails = [];
}
let recommendedVideos: VideoBase[] = [];
video.watch_next_feed?.forEach((recommended: Record<string, any>) => {
recommendedVideos.push({
videoThumbnails: recommended?.thumbnails as Thumbnail[] || [],
videoId: recommended?.id || '',
title: recommended?.title.toString() || '',
viewCountText: numberWithCommas(Number(recommended?.view_count.toString().replace(/\D/g, '') || 0)) || '',
lengthSeconds: recommended?.duration?.seconds || 0,
author: recommended?.author.name || '',
authorId: recommended?.author.id || ''
});
});
return {
type: 'video',
title: video.primary_info.title.toString(),
viewCount: Number(video.primary_info.view_count.toString().replace(/\D/g, '')),
viewCountText: video.primary_info.view_count.toString(),
likeCount: video.basic_info.like_count || 0,
dislikeCount: 0,
allowRatings: false,
rating: 0,
isListed: 0,
isFamilyFriendly: video.basic_info.is_family_safe || true,
genre: video.basic_info.category || '',
genreUrl: '',
dashUrl: dashUri,
adaptiveFormats: [],
formatStreams: [],
recommendedVideos: recommendedVideos,
authorThumbnails: authorThumbnails,
captions: [],
authorId: video.basic_info.channel_id || '',
authorUrl: `/channel/${video.basic_info.channel_id}`,
authorVerified: false,
description: descString,
descriptionHtml: video.secondary_info.description.toHTML() || descString,
published: 0,
publishedText: video.primary_info.published.toString(),
premiereTimestamp: 0,
liveNow: false,
premium: false,
isUpcoming: false,
videoId: videoId,
videoThumbnails: video.basic_info.thumbnail as Thumbnail[],
author: video.basic_info.author || 'Unknown',
lengthSeconds: video.basic_info.duration || 0,
subCountText: '',
keywords: video.basic_info.keywords || [],
allowedRegions: []
};
} else {
await fetchErrorHandle(resp);
}
return await resp.json();
}
+4 -4
View File
@@ -234,15 +234,15 @@ export function getBestThumbnail(
maxHeightDimension = 360
): string {
if (images && images.length > 0) {
images = images.filter(
const imagesFiltered = images.filter(
(image) => image.width < maxWidthDimension && image.height < maxHeightDimension
);
if (images.length === 0) {
return '';
if (imagesFiltered.length === 0) {
return images[0].url;
}
images.sort((a, b) => {
imagesFiltered.sort((a, b) => {
return b.width * b.height - a.width * a.height;
});