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

如何让YouTube单视频下载完成后再执行下一次循环迭代?

解决队列式批量下载YouTube播放列表的问题

你的代码里核心问题是:downloadVideo虽然标记为async,但没有等待yt-dlp子进程执行完成就直接返回了,导致循环中的await无法生效,所有下载任务会同时启动。

修复方案:让downloadVideo返回Promise

要实现队列式等待,必须让downloadVideo返回一个Promise,只有当子进程完成(或失败)时才resolve/reject该Promise。修改后的代码如下:

async function downloadVideo(videoId, videoTitle) {
  return new Promise((resolve, reject) => {
    // 修正路径引号,避免转义问题
    const mp3String = `yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "./music/reggae/%(title)s.%(ext)s" ${videoId}`;
    console.log(`Download started. videoname: ${videoTitle}`);
    
    const child = exec(mp3String);

    // 监听子进程错误(比如启动失败)
    child.on('error', (err) => {
      console.error(`Failed to start download for ${videoTitle}:`, err);
      reject(err);
    });

    // 监听子进程退出事件
    child.on('exit', (code) => {
      if (code === 0) {
        console.log(`Download finished at: ./music/reggae/${videoTitle}.mp3`);
        resolve();
      } else {
        reject(new Error(`Download failed for ${videoTitle} with exit code ${code}`));
      }
    });
  });
}

优化批量下载循环

downloadEntirePlaylist可以保持原逻辑,或者改用更简洁的for...of循环:

async function downloadEntirePlaylist(playlistID) {
  const playlistData = await fetchPlaylist(playlistID);
  
  for (const [idx, videoId] of playlistData.idList.entries()) {
    const videoTitle = playlistData.videoTitles[idx];
    await downloadVideo(videoId, videoTitle);
  }

  console.log("All videos in playlist downloaded!");
}

关键修改说明

  • 用Promise包裹子进程生命周期,确保await能正确等待下载完成
  • 增加了error事件监听,处理子进程启动失败的场景
  • 修正了输出路径的错误(原代码中输出路径少了music/reggae/前缀)
  • 通过exit事件的退出码判断下载是否成功,失败时会reject,方便后续捕获错误

这样修改后,循环会严格等待当前视频下载完成后,再启动下一个下载任务,避免同时运行大量进程导致的负载过高问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:25:13