已登录带Cookie环境下如何下载HLS/m3u8视频?
针对方法1:强制浏览器下载.ts文件
浏览器直接打开.ts文件是因为MIME类型识别逻辑,可通过拦截请求并修改响应头的方式强制触发下载,结合Puppeteer的CDP(Chrome DevTools Protocol)实现:
const client = await page.target().createCDPSession(); // 设置全局下载行为 await client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: '/your/target/download/path', eventsEnabled: true }); // 拦截所有.ts格式的媒体请求 await client.send('Network.setRequestInterception', { patterns: [{ urlPattern: '*.ts', resourceType: 'Media' }] }); client.on('Network.requestIntercepted', async (event) => { // 继续请求并添加强制下载的响应头 const fileName = new URL(event.request.url).pathname.split('/').pop(); await client.send('Network.continueInterceptedRequest', { interceptionId: event.interceptionId, headers: { ...event.request.headers, 'Content-Disposition': `attachment; filename="${fileName}"` } }); }); // 触发m3u8文件的加载,自动拉取分片 await page.evaluate((link) => { location.href = link; }, link);
此方法会让浏览器将所有.ts分片识别为可下载文件,而非直接播放。
针对方法2:解决请求拦截卡顿问题
原代码卡顿的核心原因是仅处理了第一个请求,未关闭请求拦截也未放行其他请求,导致页面请求阻塞。修改后的实现:
await page.setRequestInterception(true); const targetRequests = []; page.on('request', async (interceptedRequest) => { const url = interceptedRequest.url(); // 只收集m3u8和ts文件请求,其他请求正常放行 if (url.endsWith('.m3u8') || url.endsWith('.ts')) { targetRequests.push(interceptedRequest); interceptedRequest.abort(); } else { interceptedRequest.continue(); } }); await page.goto('https://eedols.com/m3u8/20221205130402-SiBOhsUsJbTdZLP-DfqGGLn5cF-6-l.m3u8'); // 等待分片请求收集完成(可根据实际情况调整超时时间) await new Promise(resolve => setTimeout(resolve, 2000)); // 关闭请求拦截,避免阻塞后续操作 await page.setRequestInterception(false); // 批量处理收集到的请求 const fs = require('fs').promises; for (const req of targetRequests) { const options = { encoding: null, method: req.method(), uri: req.url(), body: req.postData(), headers: req.headers() }; // 注入登录Cookie const cookies = await page.cookies(); options.headers.Cookie = cookies.map(ck => `${ck.name}=${ck.value}`).join(';'); // 重发请求并保存文件 const response = await request(options); const fileName = new URL(req.url()).pathname.split('/').pop(); await fs.writeFile(`/your/target/download/path/${fileName}`, response.body); }
更高效的替代方案
直接使用专业HLS工具(如ffmpeg)配合Cookie下载,无需依赖浏览器,稳定性和效率更高:
- 从Puppeteer中导出Cookie字符串:
const cookies = await page.cookies(); const cookieStr = cookies.map(ck => `${ck.name}=${ck.value}`).join('; ');
- 用ffmpeg命令下载并合并分片:
ffmpeg -headers "Cookie: ${cookieStr}" -i "https://your.target.m3u8.url" -c copy output.mp4
内容的提问来源于stack exchange,提问作者yarek
相关产品推荐
相关产品推荐

