You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ytdl-core+Express下载YouTube视频失败问题排查求助

嘿,我帮你排查了下这段代码里的问题,主要是前端请求方式不对,加上缺少错误处理导致的无响应,咱们一步步来修复:

问题根源

  • 你前端用了同步XMLHttpRequest(req.open('get', ..., false)),这种方式会卡死浏览器主线程,而且浏览器不会自动识别响应里的Content-Disposition: attachment头,自然不会弹出下载窗口。
  • 不管是前端还是后端,都没做错误处理——比如输入空链接、无效YouTube地址、下载失败时,完全没有提示,看起来就像“没反应”。
  • 后端的app.listen放在了路由定义之前,虽然Express允许这么做,但不符合最佳实践,容易搞混顺序。

修复后的完整代码

前端 script.js

把同步XHR换成更靠谱的触发方式:用隐藏的<a>标签发起请求,让浏览器自动处理下载逻辑,同时增加基础校验:

const confirmText = "Downloading videos from YouTube is against the YouTube Policy.\n" + "The only videos that you're allowed to download is your own.";

function downloadVideo() {
  if (confirm(confirmText)) {
    const URLinput = document.getElementById("URL-input").value.trim();
    // 先校验输入是否为空
    if (!URLinput) {
      alert("请输入有效的YouTube链接!");
      return;
    }
    // 创建隐藏a标签触发下载
    const downloadLink = document.createElement('a');
    // 用encodeURIComponent处理参数,避免特殊字符破坏请求
    downloadLink.href = `/download?url=${encodeURIComponent(URLinput)}`;
    downloadLink.target = '_blank'; // 新开标签处理下载,不阻塞当前页面
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  }
}

后端 index.js

增加错误处理、URL校验,优化文件名,同时调整路由顺序:

const express = require('express');
const path = require('path');
const cors = require('cors');
const ytdl = require('ytdl-core');
const app = express();

// 中间件先加载
app.use(cors());
app.use(express.static("public"));

// 定义路由
app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.get('/download', async (req, res) => {
  try {
    const urlInput = req.query.url;
    // 先校验URL是否合法
    if (!urlInput || !ytdl.validateURL(urlInput)) {
      return res.status(400).send("无效的YouTube链接,请检查输入!");
    }
    console.log('开始处理下载请求:', urlInput);
    // 获取视频标题作为下载文件名,清理非法字符
    const videoInfo = await ytdl.getInfo(urlInput);
    const cleanTitle = videoInfo.videoDetails.title.replace(/[^\w\s-]/gi, '');
    res.header('Content-Disposition', `attachment; filename="${cleanTitle}.mp4"`);
    // 创建下载流并监听错误
    const videoStream = ytdl(urlInput, { format: 'mp4' });
    videoStream.on('error', (err) => {
      console.error('下载出错:', err);
      res.status(500).send("视频下载失败,请稍后重试!");
    });
    // 把流pipe给响应
    videoStream.pipe(res);
  } catch (err) {
    console.error('请求处理出错:', err);
    res.status(500).send("服务器内部错误,请稍后重试!");
  }
});

// 404页面路由
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', '404.html'));
});

// 最后启动服务器
app.listen(4000, () => {
  console.log('Server Works !!! At port 4000');
});

额外提醒

  1. 确保你已经安装了所有依赖:npm install express cors ytdl-core
  2. 记得定期更新ytdl-core,因为YouTube的接口经常变,旧版本可能会失效:npm update ytdl-core
  3. 你保留的合规提示很重要,一定要继续保留,避免违反YouTube的服务条款

内容的提问来源于stack exchange,提问作者Kodak3993

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:07:52