media-dl 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/cli.js +51 -103
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -8,7 +8,7 @@ const os = require('os');
8
8
 
9
9
  const rl = readline.createInterface({
10
10
  input: process.stdin,
11
- output: process.stdout,
11
+ output: process.stdout
12
12
  });
13
13
 
14
14
  const TOOLS_DIR = path.join(os.homedir(), '.media-dl');
@@ -21,66 +21,48 @@ const FFMPEG_PATH = path.join(TOOLS_DIR, isWindows ? 'ffmpeg.exe' : 'ffmpeg');
21
21
  if (!fs.existsSync(TOOLS_DIR)) fs.mkdirSync(TOOLS_DIR, { recursive: true });
22
22
 
23
23
  function askQuestion(query) {
24
- return new Promise((resolve) => rl.question(query, resolve));
24
+ return new Promise(resolve => rl.question(query, resolve));
25
25
  }
26
26
 
27
27
  function checkTools() {
28
28
  return {
29
29
  ytExists: fs.existsSync(YTDLP_PATH),
30
- ffExists: fs.existsSync(FFMPEG_PATH),
30
+ ffExists: fs.existsSync(FFMPEG_PATH)
31
31
  };
32
32
  }
33
33
 
34
34
  async function installYtdlp() {
35
35
  console.log('\n⏳ Mengunduh yt-dlp...');
36
- const url = isWindows
36
+ const url = isWindows
37
37
  ? 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe'
38
38
  : 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp';
39
-
40
39
  try {
41
40
  if (isWindows) {
42
- execSync(
43
- `powershell -Command "Invoke-WebRequest -Uri ${url} -OutFile '${YTDLP_PATH}'"`,
44
- { stdio: 'inherit' }
45
- );
41
+ execSync(`powershell -Command "Invoke-WebRequest -Uri ${url} -OutFile '${YTDLP_PATH}'"`, { stdio: 'inherit' });
46
42
  } else {
47
43
  execSync(`curl -L -# "${url}" -o "${YTDLP_PATH}"`, { stdio: 'inherit' });
48
44
  execSync(`chmod a+rx "${YTDLP_PATH}"`);
49
45
  }
50
46
  console.log('✅ yt-dlp berhasil diinstal.');
51
- } catch (e) {
52
- console.error('❌ Gagal mengunduh yt-dlp.');
53
- }
47
+ } catch (e) { console.error('❌ Gagal mengunduh yt-dlp.'); }
54
48
  }
55
49
 
56
50
  async function installFfmpeg() {
57
- console.log('\n⏳ Mengunduh FFmpeg (Diperlukan untuk kualitas HD)...');
51
+ console.log('\n⏳ Mengunduh FFmpeg (Diperlukan untuk konversi)...');
58
52
  try {
59
53
  if (isMac) {
60
54
  const zipPath = path.join(TOOLS_DIR, 'ffmpeg.zip');
61
- execSync(
62
- `curl -L -# "https://evermeet.cx/ffmpeg/getrelease/ffmpeg/zip" -o "${zipPath}"`,
63
- { stdio: 'inherit' }
64
- );
65
- console.log('📦 Mengekstrak FFmpeg...');
55
+ execSync(`curl -L -# "https://evermeet.cx/ffmpeg/getrelease/ffmpeg/zip" -o "${zipPath}"`, { stdio: 'inherit' });
66
56
  execSync(`unzip -o "${zipPath}" -d "${TOOLS_DIR}"`, { stdio: 'inherit' });
67
57
  execSync(`rm "${zipPath}"`);
68
58
  execSync(`chmod a+rx "${FFMPEG_PATH}"`);
69
59
  console.log('✅ FFmpeg berhasil disiapkan.');
70
- } else {
71
- console.log(
72
- '📝 Untuk Windows, silakan unduh manual dan letakkan ffmpeg.exe di: ' +
73
- TOOLS_DIR
74
- );
75
60
  }
76
- } catch (e) {
77
- console.error('❌ Gagal mengunduh FFmpeg secara otomatis.');
78
- }
61
+ } catch (e) { console.error('❌ Gagal instal FFmpeg.'); }
79
62
  }
80
63
 
81
64
  async function startDownload() {
82
65
  let { ytExists, ffExists } = checkTools();
83
-
84
66
  if (!ytExists) {
85
67
  console.log('\n⚠️ yt-dlp belum terpasang.');
86
68
  const ans = await askQuestion('Instal sekarang? (y/n): ');
@@ -89,80 +71,53 @@ async function startDownload() {
89
71
  }
90
72
 
91
73
  const videoURL = await askQuestion('\n🔗 Masukkan Link: ');
92
-
93
74
  console.log('\n[PILIH FORMAT]');
94
- console.log('1. Audio (MP3) ' + (ffExists ? '✅' : '❌ (Butuh FFmpeg)'));
95
- console.log('2. Video MP4 (Pilih Resolusi)');
75
+ console.log('1. Audio (MP3)');
76
+ console.log('2. Video MP4 (Sangat Kompatibel Mac/QuickTime)');
96
77
  const mode = await askQuestion('Pilihan: ');
97
78
 
98
- const outputDir = path.join(process.cwd(), 'downloads');
99
- if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
79
+ const baseDir = path.join(os.homedir(), 'Downloads', 'media-dl');
80
+ const subFolder = (mode === '1') ? 'audio' : 'video';
81
+ const finalOutputDir = path.join(baseDir, subFolder);
82
+ if (!fs.existsSync(finalOutputDir)) fs.mkdirSync(finalOutputDir, { recursive: true });
100
83
 
101
- // PERBAIKAN: Menggunakan %(title).100s untuk membatasi panjang nama file agar tidak Error 63
102
- let args = [
103
- '--ffmpeg-location',
104
- FFMPEG_PATH,
105
- '-o',
106
- `${outputDir}/%(title).100s.%(ext)s`,
107
- videoURL,
108
- ];
84
+ // Filter Format: Prioritaskan AVC1 + AAC
85
+ const qtFormat = 'bestvideo[vcodec^=avc1]+bestaudio[acodec^=mp4a]/best[vcodec^=avc1]/best';
86
+
87
+ let args = ['--ffmpeg-location', FFMPEG_PATH, '-o', `${finalOutputDir}/%(title).100s.%(ext)s`, videoURL];
109
88
 
110
89
  if (mode === '1') {
111
- if (!ffExists) {
112
- console.log(
113
- '❌ MP3 butuh FFmpeg. Silakan instal FFmpeg terlebih dahulu.'
114
- );
115
- return mainMenu();
116
- }
90
+ if (!ffExists) { console.log('❌ Butuh FFmpeg.'); return mainMenu(); }
117
91
  args.unshift('-x', '--audio-format', 'mp3');
118
92
  } else {
119
- console.log('\n[PILIH RESOLUSI]');
120
- console.log('1. Terbaik (Best Quality)');
121
- console.log('2. 1080p (Jika ada)');
122
- console.log('3. 720p');
123
- console.log('4. 480p');
124
- const resChoice = await askQuestion('Pilih resolusi: ');
125
-
126
- let formatCode = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best';
127
- if (resChoice === '2')
128
- formatCode =
129
- 'bestvideo[height<=1080][ext=mp4]+bestaudio[ext=m4a]/best[height<=1080][ext=mp4]/best';
130
- if (resChoice === '3')
131
- formatCode =
132
- 'bestvideo[height<=720][ext=mp4]+bestaudio[ext=m4a]/best[height<=720][ext=mp4]/best';
133
- if (resChoice === '4')
134
- formatCode =
135
- 'bestvideo[height<=480][ext=mp4]+bestaudio[ext=m4a]/best[height<=480][ext=mp4]/best';
136
-
137
- args.unshift('-f', formatCode);
138
-
139
- if (!ffExists) {
140
- console.log(
141
- '⚠️ FFmpeg tidak terdeteksi. Hanya bisa mengunduh kualitas standar.'
142
- );
143
- args = [
144
- '-f',
145
- 'best[ext=mp4]',
146
- '-o',
147
- `${outputDir}/%(title).100s.%(ext)s`,
148
- videoURL,
149
- ];
93
+ console.log('\n[PILIH KUALITAS]');
94
+ console.log('1. Terbaik (Auto-Conversion ke MP4)');
95
+ console.log('2. 1080p (Pasti MP4)');
96
+ console.log('3. 720p (Pasti MP4)');
97
+ const res = await askQuestion('Pilih: ');
98
+
99
+ let fCode = qtFormat;
100
+ if (res === '2') fCode = 'bestvideo[height<=1080][vcodec^=avc1]+bestaudio[acodec^=mp4a]/best[height<=1080]/best';
101
+ if (res === '3') fCode = 'bestvideo[height<=720][vcodec^=avc1]+bestaudio[acodec^=mp4a]/best[height<=720]/best';
102
+
103
+ args.unshift('-f', fCode);
104
+
105
+ // FITUR BARU: Jika FFmpeg ada, paksa konversi ke MP4 agar pasti bisa dibuka QuickTime
106
+ if (ffExists) {
107
+ args.unshift('--recode-video', 'mp4');
150
108
  }
151
109
  }
152
110
 
153
- console.log('\n🚀 Memulai proses...');
111
+ console.log('\n🚀 Memulai proses (dan konversi jika perlu)...');
154
112
  const download = spawn(YTDLP_PATH, args);
155
-
156
113
  download.stdout.on('data', (data) => process.stdout.write(data));
157
114
  download.stderr.on('data', (data) => process.stderr.write(data));
158
115
 
159
116
  download.on('close', (code) => {
160
117
  if (code === 0) {
161
- console.log(`\n✅ SELESAI! Folder: ${outputDir}`);
162
- execSync(isMac ? `open "${outputDir}"` : `explorer "${outputDir}"`);
163
- } else {
164
- console.log('\n❌ Terjadi kesalahan selama proses download.');
165
- }
118
+ console.log(`\n✅ BERHASIL! File tersimpan di: ${finalOutputDir}`);
119
+ execSync(isMac ? `open "${finalOutputDir}"` : `explorer "${finalOutputDir}"`);
120
+ } else { console.log('\n❌ Gagal saat mendownload atau mengonversi.'); }
166
121
  mainMenu();
167
122
  });
168
123
  }
@@ -172,33 +127,26 @@ async function mainMenu() {
172
127
  console.log('\n====================================');
173
128
  console.log(' MEDIA-DL MANAGER 2026 ');
174
129
  console.log('====================================');
175
- console.log(` OS : ${process.platform}`);
176
- console.log(` yt-dlp : ${ytExists ? '✅' : '❌'}`);
177
- console.log(` ffmpeg : ${ffExists ? '✅' : '❌'}`);
130
+ console.log(` OS : ${process.platform} | yt-dlp: ${ytExists?'✅':'❌'} | ffmpeg: ${ffExists?'✅':'❌'}`);
178
131
  console.log('------------------------------------');
179
132
  console.log(' 1. 📥 Download Media');
180
133
  console.log(' 2. ⚙️ Update yt-dlp');
181
134
  console.log(' 3. 🔨 Instal FFmpeg (macOS)');
182
135
  console.log(' 4. 🗑️ Uninstall & Hapus Data');
183
136
  console.log(' 5. 🚪 Keluar');
184
-
137
+
185
138
  const choice = await askQuestion('\nPilih menu: ');
186
139
  if (choice === '1') await startDownload();
187
- else if (choice === '2') {
188
- await installYtdlp();
189
- mainMenu();
190
- } else if (choice === '3') {
191
- await installFfmpeg();
192
- mainMenu();
193
- } else if (choice === '4') {
194
- const confirm = await askQuestion('Hapus semua data? (y/n): ');
195
- if (confirm.toLowerCase() === 'y')
196
- fs.rmSync(TOOLS_DIR, { recursive: true, force: true });
140
+ else if (choice === '2') { await installYtdlp(); mainMenu(); }
141
+ else if (choice === '3') { await installFfmpeg(); mainMenu(); }
142
+ else if (choice === '4') {
143
+ const confirm = await askQuestion('Hapus semua? (y/n): ');
144
+ if (confirm.toLowerCase() === 'y') {
145
+ fs.rmSync(TOOLS_DIR, { recursive: true, force: true });
146
+ console.log('✅ Folder tools dibersihkan.');
147
+ }
197
148
  mainMenu();
198
- } else {
199
- rl.close();
200
- process.exit(0);
201
- }
149
+ } else { rl.close(); process.exit(0); }
202
150
  }
203
151
 
204
- mainMenu();
152
+ mainMenu();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "media-dl",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "CLI Downloader video/audio lintas platform menggunakan yt-dlp.",
5
5
  "main": "bin/cli.js",
6
6
  "scripts": {