Express.js + ytdl-core下载的MP3文件无法打开求助
问题原因
你在后端的progress事件中直接用res.write()输出了进度文本(比如progress:XX%),这些文本会混入返回的音频流。下载后的MP3文件包含了这些非音频字符串,破坏了MP3的文件结构,导致播放器无法识别。注释掉progress逻辑后,响应流只有纯音频数据,文件就能正常播放。
解决方案
移除后端中往响应流写入进度文本的代码,前端的onDownloadProgress可以通过后端设置的Content-Length头自动计算下载进度,无需后端额外发送进度信息。
修改后的后端代码
export const downloadVideoFromUrl = async (videoUrl: string, res: Response) => { console.log("Processing video URL:", videoUrl); if (!ytdl.validateURL(videoUrl)) { throw new Error("Invalid YouTube URL"); } try { const videoInfo = await ytdl.getInfo(videoUrl); const title = videoInfo.videoDetails.title.replace(/[^\w\s]/gi, "_"); const format = ytdl.chooseFormat(videoInfo.formats, { quality: "highestaudio", filter: "audio" }); if (!format) { throw new Error("No suitable format found"); } res.header("Content-Disposition", `attachment; filename="${title}.mp3"`); res.header("Content-Type", "audio/mp3"); const contentLength = format.hasOwnProperty("contentLength") ? format.contentLength : null; if (contentLength) { res.header("Content-Length", contentLength.toString()); } const videoStream = ytdl(videoUrl, { format }); // 仅在后端日志打印进度,不写入响应流 videoStream.on("progress", (_, downloaded, total) => { const progress = (downloaded / total) * 100; console.log(`Download progress: ${progress.toFixed(2)}%`); }); videoStream .pipe(res) .on("finish", () => { console.log("Download complete"); res.end(); }) .on("error", (err) => { console.error("Error during download:", err); res.status(500).send("Download failed"); }); } catch (err) { console.error("Error fetching video information:", err); res.status(500).send("Error fetching video information"); } };
前端代码无需修改
前端的onDownloadProgress会根据响应头中的Content-Length自动计算下载进度,原有代码可正常显示进度条。
内容的提问来源于stack exchange,提问作者Zirek
相关产品推荐
相关产品推荐

