Skip to content

Instantly share code, notes, and snippets.

@astrarudra
Last active April 15, 2024 20:51
Show Gist options
  • Save astrarudra/59da1dbb42bddff3460a74fe5170ac37 to your computer and use it in GitHub Desktop.
Save astrarudra/59da1dbb42bddff3460a74fe5170ac37 to your computer and use it in GitHub Desktop.
yt-dlp - Compute approx file size
const filterYTVideoFormats = (info) => {
const { formats, requested_formats } = info
let bestAudio = requested_formats.find(o => o.vcodec === "none")
const filteredFormats = Object.values(formats.reduce((acc, curr) => {
if(!curr.height || curr.height < 480 || curr.format_note === "Premium") return acc
curr.vcodec = curr.vcodec.split('.')[0]
const selected = acc[curr.height]
// Already there is a selecton for this height - Select Better, use approx if filesize not available
if(selected){
let better = false
if(curr.vcodec === "av01") { // Best Codec.
if(selected.vcodec === "av01") better = curr.vbr > selected.vbr
else better = true
} else if(selected.vcodec !== "av01" && curr.vcodec === "vp09") {
if(selected.vcodec === "vp09") better = curr.vbr > selected.vbr
else better = true
}
if(!better) better = curr.vbr > selected.vbr
if(!better){ // if curr is not better, we will see if we can use it's file size
const useForApprox = !selected.size && curr.filesize
if(useForApprox){
selected.size = (curr.filesize / curr.vbr) * selected.vbr
selected.approx = true
}
return acc
}
// if curr is better and dont have file size, we will use existing file size if available.
if(selected.size && !curr.filesize){
curr.filesize = (selected.size / selected.vbr) * curr.vbr
curr.approx = true
}
}
const { height, width, filesize, vbr, resolution, approx, audio_channels, format_id, vcodec } = curr
acc[curr.height] = {
id: format_id, h: height, w: width, res: resolution, size: filesize,
approx, vbr, vcodec,
hasAudio: !!audio_channels,
}
return acc;
}, {}));
filteredFormats.forEach(o => {
o.size = parseFloat((( !o.hasAudio ? (o.size + bestAudio.filesize) : o.size) / 1048576).toFixed(2))
})
const { id, title, acodec, aspect_ratio, asr, audio_channels, duration_string, fps, language } = info
const response = {
id,
formats: filteredFormats.sort((a, b) => b.h - a.h),
info: {
title,
aid: bestAudio.format_id,
acodec, asr, fps, language,
ratio: aspect_ratio,
audioChannels: audio_channels,
duration: duration_string,
},
}
return response
}
const ytDetails = (ytHash) => {
return new Promise((resolve, reject) => {
console.log("INPUT YT-INFO: ", ytHash)
exec(`yt-dlp -j ${ytHash}`, (error, stdout, stderr) => {
console.log("YT-INFO RAW JSON: ", info);
try {
const info = JSON.parse(stdout);
resolve(response);
} catch (parseError) {
console.error('Error parsing JSON:', parseError);
reject(parseError);
}
})
})
}
// Usage
ytDetails(ytHash).then(info => {
const data = filterYTVideoFormats(info)
console.log(data)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment