如何让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
相关产品推荐
相关产品推荐

