api: add in yt downloader quality

This commit is contained in:
Всеволод О. 2025-01-04 15:28:25 +03:00
parent 3ee7273b92
commit 4feb93612a
2 changed files with 96 additions and 18 deletions

View File

@ -59,9 +59,6 @@ export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disab
type: Array.isArray(r.urls) ? "merge" : "remux",
isHLS: true,
}
if (r.type === 'redirect') {
responseType = "redirect";
}
break;
case "muteVideo":
@ -119,6 +116,7 @@ export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disab
case "youtube":
params = { type: r.type };
responseType = "redirect";
break;
case "reddit":
@ -215,5 +213,7 @@ export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disab
params.type = "proxy";
}
//console.log(responseType, {...defaultParams, ...params});
return createResponse(responseType, {...defaultParams, ...params})
}

View File

@ -1,7 +1,56 @@
import youtubedl from 'youtube-dl-exec';
import { env } from '../../config.js';
import * as fs from 'fs';
const videoQualities = [144, 240, 360, 480, 720, 1080, 1440, 2160, 4320];
const codecList = {
h264: {
videoCodec: "avc1",
audioCodec: "mp4a",
container: "mp4"
},
av1: {
videoCodec: "av01",
audioCodec: "opus",
container: "webm"
},
vp9: {
videoCodec: "vp9",
audioCodec: "opus",
container: "webm"
}
};
const hlsCodecList = {
h264: {
videoCodec: "avc1",
audioCodec: "mp4a",
container: "mp4"
},
vp9: {
videoCodec: "vp09",
audioCodec: "mp4a",
container: "webm"
}
};
export default async function(o) {
let useHLS = o.youtubeHLS;
if (useHLS && o.format === "av1") {
useHLS = false;
}
const quality = o.quality === "max" ? 9000 : Number(o.quality);
const normalizeQuality = res => {
const shortestSide = res.height > res.width ? res.width : res.height;
return videoQualities.find(qual => qual >= shortestSide);
};
let codec = o.format || "h264";
try {
const output = await youtubedl(`https://www.youtube.com/watch?v=${o.id}`, {
dumpSingleJson: true,
@ -13,6 +62,7 @@ export default async function(o) {
],
downloader: 'ffmpeg',
hlsUseMpegts: true,
//getUrl: true,
});
const { is_live, duration, formats, title } = output;
@ -29,25 +79,53 @@ export default async function(o) {
return { error: "youtube.no_matching_format" };
}
const qualityDict = formats.reduce((acc, format) => {
const qualityLabel = format.height ? `${format.height}p` : "unknown";
acc[qualityLabel] = {
const matchHlsCodec = codecs => (
codecs.includes(hlsCodecList[codec]?.videoCodec || codecList.h264.videoCodec)
);
const variants = formats.map(format => ({
url: format.url,
extension: format.ext,
resolution: format.height ? `${format.height}p` : "unknown",
youtubeFormat: format.ext
};
return acc;
}, {});
codecs: format.vcodec,
resolution: { width: format.width, height: format.height }
}));
const best = variants.find(i => matchHlsCodec(i.codecs));
const preferred = variants.find(i =>
matchHlsCodec(i.codecs) && normalizeQuality(i.resolution) === quality
);
let selected = preferred || best;
if (!selected) {
codec = "h264";
selected = variants.find(i => matchHlsCodec(i.codecs));
}
if (!selected) {
return { error: "youtube.no_matching_format" };
}
// download
// youtubedl(selected.url, {
// output: `${title}.${hlsCodecList[codec]?.container || 'mp4'}`,
// format: 'best'
// });
return {
type: "redirect",
urls: qualityDict,
type: "video",
urls: [selected.url],
filenameAttributes: {
title,
service: 'youtube',
title: title,
id: o.id,
extension: hlsCodecList[codec]?.container || 'mp4'
},
fileMetadata: {},
isHLS: true,
fileMetadata: {
codecs: selected.codecs,
resolution: selected.resolution
},
isHLS: false,
};
} catch (e) {
console.error(e);