yt metadata

This commit is contained in:
2026-07-15 19:12:28 +02:00
parent ca0f6f19cc
commit 2338858254

View File

@@ -357,16 +357,18 @@ export default router => {
? cfg.main.socks.replace(/^socks5:\/\//, 'socks5h://') ? cfg.main.socks.replace(/^socks5:\/\//, 'socks5h://')
: null; : null;
// 1. YouTube: go straight to oEmbed — faster and more reliable than yt-dlp for these // 1. YouTube: try oEmbed first (fast), then fall through to yt-dlp on failure
if (isYouTube) { if (isYouTube) {
try { try {
const oembedUrl = `https://www.youtube.com/oembed?url=${encodeURIComponent(url)}&format=json`; const oembedUrl = `https://www.youtube.com/oembed?url=${encodeURIComponent(url)}&format=json`;
// Do NOT use --fail: non-2xx responses (e.g. age-restricted/private videos) still
// return valid JSON we can attempt to parse. Use ignoreExitCode so we always get output.
const { stdout: oembedOut } = await queue.spawn('curl', [ const { stdout: oembedOut } = await queue.spawn('curl', [
'-s', '--max-time', '10', '--fail', '-s', '--max-time', '15',
'--user-agent', 'Mozilla/5.0 (compatible; oEmbed)', '--user-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
...(socksH ? ['--proxy', socksH] : []), ...(socksH ? ['--proxy', socksH] : []),
oembedUrl oembedUrl
]); ], { ignoreExitCode: true });
if (oembedOut && oembedOut.trim()) { if (oembedOut && oembedOut.trim()) {
const data = JSON.parse(oembedOut); const data = JSON.parse(oembedOut);
if (data.title) { if (data.title) {
@@ -376,15 +378,43 @@ export default router => {
author: data.author_name || 'Unknown' author: data.author_name || 'Unknown'
}; };
await setCache(url, meta); await setCache(url, meta);
return res.json({ return res.json({ success: true, meta });
success: true,
meta
});
} }
} }
} catch (oembedErr) { } catch (oembedErr) {
console.error(`[META-FETCH] YouTube oEmbed failed:`, oembedErr.message || oembedErr); console.error(`[META-FETCH] YouTube oEmbed failed, will try yt-dlp:`, oembedErr.message || oembedErr);
} }
// oEmbed failed — fall back to yt-dlp for YouTube (handles age-restricted, private, etc.)
for (let attempt = 1; attempt <= 2; attempt++) {
try {
const { stdout: ytOut } = await queue.spawn('yt-dlp', [
...proxyArgs,
'--quiet',
'--no-warnings',
'--js-runtimes', 'node',
'--print', '%(title)s',
'--print', '%(uploader)s',
'--skip-download',
url
]);
const ytLines = ytOut.trim().split('\n');
const ytTitle = ytLines[0] ? ytLines[0].trim() : '';
if (ytTitle) {
const meta = {
title: ytTitle,
site_name: 'youtube.com',
author: ytLines[1] ? ytLines[1].trim() : 'Unknown'
};
await setCache(url, meta);
return res.json({ success: true, meta });
}
} catch (ytErr) {
if (attempt < 2) { await sleep(1000); continue; }
console.error(`[META-FETCH] YouTube yt-dlp fallback failed:`, ytErr.message || ytErr);
}
}
return res.json({ success: false, msg: 'Failed to extract YouTube metadata' }, 500); return res.json({ success: false, msg: 'Failed to extract YouTube metadata' }, 500);
} }