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

View File

@ -1,7 +1,56 @@
import youtubedl from 'youtube-dl-exec'; import youtubedl from 'youtube-dl-exec';
import { env } from '../../config.js'; 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) { 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 { try {
const output = await youtubedl(`https://www.youtube.com/watch?v=${o.id}`, { const output = await youtubedl(`https://www.youtube.com/watch?v=${o.id}`, {
dumpSingleJson: true, dumpSingleJson: true,
@ -13,6 +62,7 @@ export default async function(o) {
], ],
downloader: 'ffmpeg', downloader: 'ffmpeg',
hlsUseMpegts: true, hlsUseMpegts: true,
//getUrl: true,
}); });
const { is_live, duration, formats, title } = output; const { is_live, duration, formats, title } = output;
@ -29,25 +79,53 @@ export default async function(o) {
return { error: "youtube.no_matching_format" }; return { error: "youtube.no_matching_format" };
} }
const qualityDict = formats.reduce((acc, format) => { const matchHlsCodec = codecs => (
const qualityLabel = format.height ? `${format.height}p` : "unknown"; codecs.includes(hlsCodecList[codec]?.videoCodec || codecList.h264.videoCodec)
acc[qualityLabel] = { );
const variants = formats.map(format => ({
url: format.url, url: format.url,
extension: format.ext, codecs: format.vcodec,
resolution: format.height ? `${format.height}p` : "unknown", resolution: { width: format.width, height: format.height }
youtubeFormat: format.ext }));
};
return acc; 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 { return {
type: "redirect", type: "video",
urls: qualityDict, urls: [selected.url],
filenameAttributes: { filenameAttributes: {
title, service: 'youtube',
title: title,
id: o.id,
extension: hlsCodecList[codec]?.container || 'mp4'
}, },
fileMetadata: {}, fileMetadata: {
isHLS: true, codecs: selected.codecs,
resolution: selected.resolution
},
isHLS: false,
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);