hutatools / lib /ytdl.js
fullpwerr's picture
Update lib/ytdl.js
ab80cff verified
const { spawn } = require("child_process");
const path = require("path");
const fs = require("fs");
const tmp = path.join(__dirname, "../tmp"); // path to your tmp folder
const ytdlp = "yt-dlp"; // Assume yt-dlp is installed globally inside the Docker container
const cookiesPath = path.join(__dirname, "./cookies/yt.txt");
function runYtDlp(args) {
return new Promise((resolve, reject) => {
const process = spawn(ytdlp, args, { stdio: ["ignore", "pipe", "pipe"] });
let stdout = "";
let stderr = "";
process.stdout.on("data", (data) => (stdout += data.toString()));
process.stderr.on("data", (data) => (stderr += data.toString()));
process.on("close", (code) => {
if (code === 0) resolve(stdout.trim());
else reject(new Error(stderr.trim() || `yt-dlp exited with code ${code}`));
});
});
}
async function getInfo(url) {
try {
const result = await runYtDlp(["-j", "--cookies", cookiesPath, url]);
const info = JSON.parse(result);
return {
id: info.id,
title: info.title,
thumbnail: `https://i.ytimg.com/vi/${info.id}/maxresdefault.jpg`,
description: info.description,
duration: info.duration,
views: info.view_count,
likes: info.like_count,
comments: info.comment_count,
uploaded: info.timestamp,
channel: {
id: info.channel_id,
handle: info.uploader_id,
name: info.uploader,
picture: info.channel_thumbnail || "",
subscribers: info.channel_follower_count,
verified: !!info.channel_is_verified,
},
videos: [...new Set(info.formats.filter(v => v.video_ext === "mp4").map(v => v.height + "p"))],
};
} catch (err) {
throw new Error(`Failed to get video info: ${err.message}`);
}
}
async function getVideo(url, quality = "480p") {
const ts = Date.now();
const outputFile = `${tmp}/${ts}.mp4`;
try {
await runYtDlp(["--cookies", cookiesPath, "-f", `ba[ext=m4a]+bv[height=${quality.slice(0, -1)}]`, "--merge-output-format", "mp4", "-o", outputFile, url]);
const result = fs.readFileSync(outputFile);
fs.unlinkSync(outputFile);
return result;
} catch (err) {
throw new Error(`Failed to download video: ${err.message}`);
}
}
async function getAudio(url) {
const ts = Date.now();
const outputFile = `${tmp}/${ts}.mp3`;
try {
await runYtDlp(["--cookies", cookiesPath,"-f", "ba", "-o", outputFile, url]);
const result = fs.readFileSync(outputFile);
fs.unlinkSync(outputFile);
return result;
} catch (err) {
throw new Error(`Failed to download audio: ${err.message}`);
}
}
module.exports = {
getInfo,
getAudio,
getVideo,
};