fullpwerr commited on
Commit
c90a7ee
·
1 Parent(s): 6689845
Files changed (1) hide show
  1. lib/ytdl.js +56 -33
lib/ytdl.js CHANGED
@@ -1,18 +1,20 @@
1
  const { spawn } = require("child_process");
2
  const path = require("path");
 
3
 
4
- const ytdlp = "yt-dlp"; // Asumsi yt-dlp sudah terinstall global di Docker
5
- const cookiesPath = path.join(__dirname, "./cookies/twt.txt");
 
6
 
7
  function runYtDlp(args) {
8
  return new Promise((resolve, reject) => {
9
  const process = spawn(ytdlp, args, { stdio: ["ignore", "pipe", "pipe"] });
10
  let stdout = "";
11
  let stderr = "";
12
-
13
  process.stdout.on("data", (data) => (stdout += data.toString()));
14
  process.stderr.on("data", (data) => (stderr += data.toString()));
15
-
16
  process.on("close", (code) => {
17
  if (code === 0) resolve(stdout.trim());
18
  else reject(new Error(stderr.trim() || `yt-dlp exited with code ${code}`));
@@ -20,42 +22,63 @@ function runYtDlp(args) {
20
  });
21
  }
22
 
23
- /**
24
- * Mengambil metadata video Twitter menggunakan yt-dlp.
25
- * @param {string} url - URL tweet yang berisi video.
26
- * @returns {Promise<Object>} - Metadata video dalam format JSON.
27
- */
28
- async function getTwitterVideoInfo(url) {
29
  try {
30
  const result = await runYtDlp(["-j", "--cookies", cookiesPath, url]);
31
  const info = JSON.parse(result);
32
-
33
- // Pastikan `formats` ada, jika tidak buat array kosong
34
- const videoFormats = (info.formats || []).filter(
35
- (f) => (f.video_ext !== "none" && f.audio_ext !== "none") || f.url.includes(".mp4")
36
- );
37
-
38
- const audioFormats = (info.formats || []).filter((f) => f.video_ext === "none" && f.audio_ext !== "none");
39
-
40
  return {
41
- status: 200,
42
- title: info.title || "No Title",
43
- description: info.description || "",
44
- thumbnail: info.thumbnail || "",
45
- video: videoFormats.map((v) => ({
46
- format_id: v.format_id,
47
- resolution: v.resolution || `${v.width}x${v.height}`,
48
- url: v.url,
49
- })),
50
- audio: audioFormats.map((a) => ({
51
- format_id: a.format_id,
52
- bitrate: a.abr,
53
- url: a.url,
54
- })),
 
 
 
 
55
  };
56
  } catch (err) {
57
  throw new Error(`Failed to get video info: ${err.message}`);
58
  }
59
  }
60
 
61
- module.exports = getTwitterVideoInfo;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  const { spawn } = require("child_process");
2
  const path = require("path");
3
+ const fs = require("fs");
4
 
5
+ const tmp = path.join(__dirname, "../tmp"); // path to your tmp folder
6
+ const ytdlp = "yt-dlp"; // Assume yt-dlp is installed globally inside the Docker container
7
+ const cookiesPath = path.join(__dirname, "./cookies/yt.txt");
8
 
9
  function runYtDlp(args) {
10
  return new Promise((resolve, reject) => {
11
  const process = spawn(ytdlp, args, { stdio: ["ignore", "pipe", "pipe"] });
12
  let stdout = "";
13
  let stderr = "";
14
+
15
  process.stdout.on("data", (data) => (stdout += data.toString()));
16
  process.stderr.on("data", (data) => (stderr += data.toString()));
17
+
18
  process.on("close", (code) => {
19
  if (code === 0) resolve(stdout.trim());
20
  else reject(new Error(stderr.trim() || `yt-dlp exited with code ${code}`));
 
22
  });
23
  }
24
 
25
+ async function getInfo(url) {
 
 
 
 
 
26
  try {
27
  const result = await runYtDlp(["-j", "--cookies", cookiesPath, url]);
28
  const info = JSON.parse(result);
 
 
 
 
 
 
 
 
29
  return {
30
+ id: info.id,
31
+ title: info.title,
32
+ thumbnail: `https://i.ytimg.com/vi/${info.id}/maxresdefault.jpg`,
33
+ description: info.description,
34
+ duration: info.duration,
35
+ views: info.view_count,
36
+ likes: info.like_count,
37
+ comments: info.comment_count,
38
+ uploaded: info.timestamp,
39
+ channel: {
40
+ id: info.channel_id,
41
+ handle: info.uploader_id,
42
+ name: info.uploader,
43
+ picture: info.channel_thumbnail || "",
44
+ subscribers: info.channel_follower_count,
45
+ verified: !!info.channel_is_verified,
46
+ },
47
+ videos: [...new Set(info.formats.filter(v => v.video_ext === "mp4").map(v => v.height + "p"))],
48
  };
49
  } catch (err) {
50
  throw new Error(`Failed to get video info: ${err.message}`);
51
  }
52
  }
53
 
54
+ async function getVideo(url, quality = "480p") {
55
+ const ts = Date.now();
56
+ const outputFile = `${tmp}/${ts}.mp4`;
57
+ try {
58
+ await runYtDlp(["-f", `ba[ext=m4a]+bv[height=${quality.slice(0, -1)}]`, "--merge-output-format", "mp4", "-o", outputFile, url]);
59
+ const result = fs.readFileSync(outputFile);
60
+ fs.unlinkSync(outputFile);
61
+ return result;
62
+ } catch (err) {
63
+ throw new Error(`Failed to download video: ${err.message}`);
64
+ }
65
+ }
66
+
67
+ async function getAudio(url) {
68
+ const ts = Date.now();
69
+ const outputFile = `${tmp}/${ts}.mp3`;
70
+ try {
71
+ await runYtDlp(["-f", "ba", "-o", outputFile, url]);
72
+ const result = fs.readFileSync(outputFile);
73
+ fs.unlinkSync(outputFile);
74
+ return result;
75
+ } catch (err) {
76
+ throw new Error(`Failed to download audio: ${err.message}`);
77
+ }
78
+ }
79
+
80
+ module.exports = {
81
+ getInfo,
82
+ getAudio,
83
+ getVideo,
84
+ };