Fix muxing

This commit is contained in:
2026-05-15 04:10:06 +02:00
parent 05faf1ce3b
commit 6deb883472
26 changed files with 662 additions and 169 deletions

View File

@@ -17,22 +17,98 @@ function isYtDlpAvailable() {
return false;
}
}
function downloadVideo(url, outputDir) {
if (!fs_1.default.existsSync(outputDir)) {
fs_1.default.mkdirSync(outputDir, { recursive: true });
}
const outputTemplate = path_1.default.join(outputDir, '%(title)s.%(ext)s');
const result = (0, child_process_1.execSync)(`yt-dlp -f "best[ext=mp4]/best" -o "${outputTemplate}" --print filename --print title "${url}"`, { encoding: 'utf-8', timeout: 600000 });
const lines = result.trim().split('\n');
const filename = lines[0]?.trim();
const title = lines[1]?.trim() || filename;
if (!filename) {
throw new Error('yt-dlp: Failed to parse downloaded filename');
}
const filePath = path_1.default.resolve(outputDir, filename);
if (!fs_1.default.existsSync(filePath)) {
throw new Error(`yt-dlp: Downloaded file not found at ${filePath}`);
}
return { filePath, filename, title };
const PROGRESS_PREFIX = 'PROG ';
function downloadVideo(url, outputDir, onProgress) {
return new Promise((resolve, reject) => {
if (!fs_1.default.existsSync(outputDir)) {
fs_1.default.mkdirSync(outputDir, { recursive: true });
}
const outputTemplate = path_1.default.join(outputDir, '%(title)s.%(ext)s');
// Pass arguments as an array — no shell, no quoting issues, no truncation
// on URLs containing & | % ^ etc. (the original execSync bug on Windows).
const args = [
'-f', 'best[ext=mp4]/best',
'-o', outputTemplate,
'--newline',
'--progress-template', `${PROGRESS_PREFIX}%(progress._percent_str)s`,
'--print', 'after_move:filepath',
'--print', 'title',
'--no-simulate',
url,
];
const child = (0, child_process_1.spawn)('yt-dlp', args, { shell: false });
const stderrLines = [];
const outputLines = [];
let stdoutBuf = '';
let stderrBuf = '';
const handleStdoutLine = (line) => {
if (!line)
return;
if (line.startsWith(PROGRESS_PREFIX)) {
const m = line.slice(PROGRESS_PREFIX.length).match(/([\d.]+)\s*%/);
if (m && onProgress) {
const pct = parseFloat(m[1]);
if (!isNaN(pct))
onProgress(pct);
}
return;
}
outputLines.push(line);
};
child.stdout.on('data', (chunk) => {
stdoutBuf += chunk.toString('utf-8');
let nl;
while ((nl = stdoutBuf.indexOf('\n')) !== -1) {
const line = stdoutBuf.slice(0, nl).replace(/\r$/, '');
stdoutBuf = stdoutBuf.slice(nl + 1);
handleStdoutLine(line.trim());
}
});
child.stderr.on('data', (chunk) => {
stderrBuf += chunk.toString('utf-8');
let nl;
while ((nl = stderrBuf.indexOf('\n')) !== -1) {
const line = stderrBuf.slice(0, nl).replace(/\r$/, '').trim();
stderrBuf = stderrBuf.slice(nl + 1);
if (line)
stderrLines.push(line);
}
});
child.on('error', (err) => {
reject(new Error(`yt-dlp failed to start: ${err.message}`));
});
const timeoutMs = 600000;
const timer = setTimeout(() => {
child.kill();
reject(new Error(`yt-dlp timed out after ${timeoutMs / 1000}s`));
}, timeoutMs);
child.on('close', (code) => {
clearTimeout(timer);
if (stdoutBuf.trim())
handleStdoutLine(stdoutBuf.trim());
if (stderrBuf.trim())
stderrLines.push(stderrBuf.trim());
if (code !== 0) {
const tail = stderrLines.slice(-3).join(' | ') || `exit code ${code}`;
reject(new Error(tail));
return;
}
const filePath = outputLines[0];
const title = outputLines[1] || (filePath ? path_1.default.basename(filePath) : '');
if (!filePath) {
reject(new Error('yt-dlp completed but did not report a filename'));
return;
}
if (!fs_1.default.existsSync(filePath)) {
reject(new Error(`yt-dlp reported success but file not found: ${filePath}`));
return;
}
resolve({
filePath: path_1.default.resolve(filePath),
filename: path_1.default.basename(filePath),
title,
});
});
});
}
//# sourceMappingURL=ytDlp.js.map