Fix muxing
This commit is contained in:
110
dist/server/services/ytDlp.js
vendored
110
dist/server/services/ytDlp.js
vendored
@@ -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
|
||||
Reference in New Issue
Block a user