add retrying for video list

This commit is contained in:
localhost 2026-04-29 12:32:58 +02:00
parent 27fb185b45
commit ae25cb3c0d
3 changed files with 29 additions and 19 deletions

View File

@ -1,5 +1,6 @@
{ {
"lockfileVersion": 1, "lockfileVersion": 1,
"configVersion": 0,
"workspaces": { "workspaces": {
"": { "": {
"name": "preservetube-metadata-rewrite", "name": "preservetube-metadata-rewrite",
@ -14,7 +15,7 @@
"fluent-ffmpeg": "^2.1.3", "fluent-ffmpeg": "^2.1.3",
"googlevideo": "^4.0.4", "googlevideo": "^4.0.4",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"youtubei.js": "^16.0.1", "youtubei.js": "^17.0.1",
}, },
"devDependencies": { "devDependencies": {
"@types/bun": "latest", "@types/bun": "latest",
@ -315,7 +316,7 @@
"xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="], "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="],
"youtubei.js": ["youtubei.js@16.0.1", "", { "dependencies": { "@bufbuild/protobuf": "^2.0.0", "meriyah": "^6.1.4" } }, "sha512-3802bCAGkBc2/G5WUTc0l/bO5mPYJbQAHL04d9hE9PnrDHoBUT8MN721Yqt4RCNncAXdHcfee9VdJy3Fhq1r5g=="], "youtubei.js": ["youtubei.js@17.0.1", "", { "dependencies": { "@bufbuild/protobuf": "^2.0.0", "meriyah": "^6.1.4" } }, "sha512-1lO4b8UqMDzE0oh2qEGzbBOd4UYRdxn/4PdpRM7BGTHxM6ddsEsKZTu90jp8V9FHVgC2h1UirQyqoqLiKwl+Zg=="],
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],

View File

@ -91,25 +91,34 @@ app.get('/channel/:id', async (req, res) => {
app.get('/videos/:id', async (req, res) => { app.get('/videos/:id', async (req, res) => {
try { try {
const videos = []; let videos: any[] = [];
const yt = await Innertube.create();
const channel = await yt.getChannel(req.params.id);
let json = await channel.getVideos();
videos.push(...json.videos); for (let attempt = 0; attempt < 3; attempt++) {
videos = [];
while (json.has_continuation && videos.length < 60) { const yt = await Innertube.create();
json = await getNextPage(json); const channel = await yt.getChannel(req.params.id);
let json = await channel.getVideos();
videos.push(...json.videos); videos.push(...json.videos);
while (json.has_continuation && videos.length < 60) {
json = await getNextPage(json);
videos.push(...json.videos);
}
if (videos.length) break;
} }
return res.json(videos) return res.json(videos);
} catch (e:any) { } catch (e: any) {
console.log(e);
if (e.message.includes('Tab "videos" not found')) { if (e.message.includes('Tab "videos" not found')) {
return res.json([]) return res.json([]);
} }
res.json(false) return res.json(false);
} }
async function getNextPage(json: any) { async function getNextPage(json: any) {
@ -134,7 +143,7 @@ app.ws('/download/:id', async (ws, req) => {
ws.send(`This video is not available for download (${info.playabilityStatus.errorScreen.playerErrorMessageRenderer.subreason.simpleText}).`); ws.send(`This video is not available for download (${info.playabilityStatus.errorScreen.playerErrorMessageRenderer.subreason.simpleText}).`);
return ws.close() return ws.close()
} }
if (!info || info.videoDetails.lengthSeconds == undefined) { if (!info || info.videoDetails.lengthSeconds == undefined) {
ws.send('Unable to retrieve video info from YouTube. Please try again later.'); ws.send('Unable to retrieve video info from YouTube. Please try again later.');
return ws.close() return ws.close()
@ -149,7 +158,7 @@ app.ws('/download/:id', async (ws, req) => {
} else if (info.videoDetails.videoId != req.params.id) { } else if (info.videoDetails.videoId != req.params.id) {
ws.send('This video is not available for download. Youtube is serving a different video.'); ws.send('This video is not available for download. Youtube is serving a different video.');
return ws.close() return ws.close()
} }
if (parseInt(info.videoDetails.lengthSeconds) >= 900) quality = '360p' // 15min if (parseInt(info.videoDetails.lengthSeconds) >= 900) quality = '360p' // 15min
quality = getVideoQuality(info, quality) quality = getVideoQuality(info, quality)
@ -170,7 +179,7 @@ app.ws('/download/:id', async (ws, req) => {
const { videoStreamUrl, audioStreamUrl, selectedFormats } = streamResults; const { videoStreamUrl, audioStreamUrl, selectedFormats } = streamResults;
const videoSizeTotal = (parseInt(selectedFormats.audioFormat.contentLength) || 0) const videoSizeTotal = (parseInt(selectedFormats.audioFormat.contentLength) || 0)
+ (parseInt(selectedFormats.videoFormat.contentLength) || 0) + (parseInt(selectedFormats.videoFormat.contentLength) || 0)
if (videoSizeTotal > (1_048_576 * config.maxVideoSize) && !config.whitelist.includes(req.params.id)) { if (videoSizeTotal > (1_048_576 * config.maxVideoSize) && !config.whitelist.includes(req.params.id)) {
@ -200,7 +209,7 @@ app.ws('/download/:id', async (ws, req) => {
const { streamResults } = await createSabrStream(req.params.id, streamOptions); const { streamResults } = await createSabrStream(req.params.id, streamOptions);
const { videoStream, audioStream, selectedFormats } = streamResults; const { videoStream, audioStream, selectedFormats } = streamResults;
const videoSizeTotal = (selectedFormats.audioFormat.contentLength || 0) const videoSizeTotal = (selectedFormats.audioFormat.contentLength || 0)
+ (selectedFormats.videoFormat.contentLength || 0) + (selectedFormats.videoFormat.contentLength || 0)
if (videoSizeTotal > (1_048_576 * config.maxVideoSize) && !config.whitelist.includes(req.params.id)) { if (videoSizeTotal > (1_048_576 * config.maxVideoSize) && !config.whitelist.includes(req.params.id)) {

View File

@ -20,6 +20,6 @@
"fluent-ffmpeg": "^2.1.3", "fluent-ffmpeg": "^2.1.3",
"googlevideo": "^4.0.4", "googlevideo": "^4.0.4",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"youtubei.js": "^16.0.1" "youtubei.js": "^17.0.1"
} }
} }