使用ytdl-core、Express与Next.js下载视频:文件无法播放
解决ytdl-core下载视频后无法播放的问题
核心问题:Axios默认会将响应解析为文本/JSON格式,而视频是二进制流数据,这种解析会导致原始二进制数据损坏,最终下载的文件无法正常播放。
方案1:修改Axios请求配置,接收二进制Blob数据
在Axios请求中添加responseType: 'blob'配置,让Axios直接接收二进制Blob数据,避免解析损坏:
Axios.post("http://localhost:3030/ytdonwload", { url: url }, { responseType: 'blob' // 关键配置:指定接收二进制Blob }).then((response) => { fileDownload(response.data, `video.mp4`); });
方案2:优化后端响应,设置正确的Content-Type(可选但更严谨)
ytdl-core返回的视频格式可能不是mp4(比如webm),如果强制命名为mp4会导致播放器识别错误。可以先获取视频的格式信息,设置对应的Content-Type和文件名:
app.post("/ytdonwload", async (req, res) => { try { const videoInfo = await ytdl.getInfo(req.body.url); // 选择合适的视频格式(这里选最高画质) const videoFormat = ytdl.chooseFormat(videoInfo.formats, { quality: 'highestvideo' }); // 设置正确的MIME类型 res.header('Content-Type', videoFormat.mimeType); // 用视频原标题+格式后缀作为文件名 res.header('Content-Disposition', `attachment; filename="${videoInfo.videoDetails.title}.${videoFormat.container}"`); ytdl(req.body.url, { format: videoFormat }).pipe(res); } catch (error) { res.status(500).send(`下载失败:${error.message}`); } });
方案3:改用GET请求+前端a标签下载(更简单可靠)
POST请求处理二进制流容易出现兼容性问题,改用GET请求配合a标签直接触发浏览器下载,绕过Axios的解析逻辑:
后端修改为GET接口
app.get("/ytdonwload", async (req, res) => { try { const videoUrl = req.query.url; const videoInfo = await ytdl.getInfo(videoUrl); const videoFormat = ytdl.chooseFormat(videoInfo.formats, { quality: 'highestvideo' }); res.header('Content-Type', videoFormat.mimeType); res.header('Content-Disposition', `attachment; filename="${videoInfo.videoDetails.title}.${videoFormat.container}"`); ytdl(videoUrl, { format: videoFormat }).pipe(res); } catch (error) { res.status(500).send(`下载失败:${error.message}`); } });
前端触发下载
const handleDownload = (videoUrl) => { const downloadLink = document.createElement('a'); // 对视频URL进行编码,避免特殊字符问题 downloadLink.href = `http://localhost:3030/ytdonwload?url=${encodeURIComponent(videoUrl)}`; downloadLink.click(); };
内容的提问来源于stack exchange,提问作者Ever Loser
相关产品推荐
相关产品推荐

