mirror of
https://github.com/imputnet/cobalt.git
synced 2025-07-14 17:28:27 +00:00
api: add in yt downloader quality
This commit is contained in:
parent
3ee7273b92
commit
4feb93612a
@ -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})
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user