Files
ytplayer/scripts/setup-ytdlp.js
2026-06-21 16:15:30 +08:00

90 lines
3.1 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Downloads the standalone yt-dlp binary into ./bin so the app never depends on
* a system-wide install. The Linux/macOS builds are self-contained (no Python
* required). Run automatically on `npm install`, or manually with `npm run setup`.
*/
const fs = require('fs');
const path = require('path');
const https = require('https');
const BIN_DIR = path.join(__dirname, '..', 'bin');
const force = process.argv.includes('--force');
function assetForPlatform() {
switch (process.platform) {
case 'win32':
return { asset: 'yt-dlp.exe', out: 'yt-dlp.exe' };
case 'darwin':
return { asset: 'yt-dlp_macos', out: 'yt-dlp' };
default:
// Linux (incl. WSL). yt-dlp_linux is a self-contained build.
return { asset: 'yt-dlp_linux', out: 'yt-dlp' };
}
}
function download(url, dest) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(dest);
const get = (u, redirects = 0) => {
if (redirects > 10) return reject(new Error('Too many redirects'));
https
.get(u, { headers: { 'User-Agent': 'ytplayer-setup' } }, (res) => {
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
res.resume();
return get(res.headers.location, redirects + 1);
}
if (res.statusCode !== 200) {
res.resume();
return reject(new Error(`HTTP ${res.statusCode} for ${u}`));
}
const total = parseInt(res.headers['content-length'] || '0', 10);
let received = 0;
res.on('data', (chunk) => {
received += chunk.length;
if (total) {
const pct = ((received / total) * 100).toFixed(0);
process.stdout.write(`\r downloading yt-dlp… ${pct}%`);
}
});
res.pipe(file);
file.on('finish', () => file.close(() => {
process.stdout.write('\r downloading yt-dlp… done \n');
resolve();
}));
})
.on('error', (err) => {
fs.unlink(dest, () => reject(err));
});
};
get(url);
});
}
async function main() {
const { asset, out } = assetForPlatform();
const dest = path.join(BIN_DIR, out);
if (!fs.existsSync(BIN_DIR)) fs.mkdirSync(BIN_DIR, { recursive: true });
if (fs.existsSync(dest) && !force) {
console.log(`yt-dlp already present at ${dest} (use "npm run update-ytdlp" to refresh).`);
return;
}
const url = `https://github.com/yt-dlp/yt-dlp/releases/latest/download/${asset}`;
console.log(`Fetching ${asset} from latest yt-dlp release…`);
try {
await download(url, dest);
if (process.platform !== 'win32') fs.chmodSync(dest, 0o755);
console.log(`yt-dlp installed at ${dest}`);
} catch (err) {
console.error('\nFailed to download yt-dlp automatically:', err.message);
console.error('You can place a yt-dlp binary manually in the ./bin folder, or ensure');
console.error('yt-dlp is on your PATH — the app will fall back to PATH if ./bin is empty.');
process.exitCode = 1;
}
}
main();