一、基本介绍
1.1 是什么
视频收割机(VideoHarvester) 是一款 Chrome 浏览器扩展(MV3),面向普通用户,在不破解任何加密、不绕过任何鉴权的前提下,从网页中识别并下载视频与 PDF 文档。
它的核心理念只有一句话:
不破解加密,只采集与续期。
对每一个目标站点,插件不去猜测、不去反推签名算法,而是在用户正常浏览时由浏览器替用户把真实的请求头与视频地址完整捕获下来 。当签名/令牌过期导致下载失败时,插件自动以一个真实的"打开页面"动作重置服务端会话、换发新地址,再续传。
1.2 解决什么问题
- 视频地址在网络层需要 Referer、Cookie 甚至 Authorization: Bearer 才能拿到字节,任何脱离浏览器上下文的下载工具都会 401。
- 视频地址经常带有时效签名 (Secure Token、微信 auth_key、私有 CDN Bearer 令牌等),过几分钟/几十分钟就 403。
- 视频常常分散在 <video> 元素、HLS .m3u8 切片流、XHR/fetch 加载的网路请求里,单一来源抓不到全部。
- 视频片段需要合成为完整 mp4 ,下载中途 SW 休眠/浏览器关闭要能断点续传。
- PDF 文档同样有私有 CDN 鉴权(401),下载时文件名与扩展名容易被 blob 嗅探错乱。
1.3 目标用户
- 公众号/新闻/视频平台的内容运营、记者、研究者,需要本地保存素材。
- 经常需要下载 PDF 公开/半公开文档(教育/行业资料)的用户。
- 对工具有插件偏好的个人用户。
1.4 技术形态
|--------|------------------------------------------------------------------|
| 维度 | 选择 |
| 浏览器 | Chrome(MV3 最低 116+),Edge 兼容 |
| 构建 | **无**(无 webpack/vite/tsc),直接 `chrome://extensions` 加载已解压目录 |
| 第三方依赖 | **零**(连 yaml/markdown 解析都自写) |
| 打包 | `video-harvester-vX.Y.Z.zip`(内含 `video-harvester/` 子目录) |
| 测试 | 175+ 例单测,managed Node 22 直跑 |
| 体积 | zip ≈ 119 KB,源码 ≈ 2000 行 |
1.5 架构总览

图:架构总览示意
五大组件:
- background/service-worker.js ------ 队列调度、落盘、chrome.declarativeNetRequest 头注入、chrome.cookies 会话获取、webRequest.onBeforeSendHeaders 捕获、签名续期触发器。
- content/detector.js ------ 注入到所有页面(all_frames: true),DOM/HLS/网络嗅探三源合一。
- offscreen/hls.js ------ 在 offscreen 文档里跑 HLS 切片下载与合成,OPFS 落盘支持断点续传。
- popup/ ------ 独立面板窗口(不会因点击页面消失),扫描列表/下载队列/设置。
- rules/ ------ 纯函数工具集(PDF 识别、URL 稳定键、命名规则)。
二、特征优势
2.1 三源合一探测
- el(DOM)------ 直接解析 <video>/<audio> 元素及其 src。
- stream(页面内嵌)------ 解码 HTML 脚本里的 JSON(公众号 playinfo、MP4 直链字典等),无需播放即可拿到全部清晰度。
- net(网络嗅探)------ 通过 webRequest 抓 XHR/fetch 的 m3u8/ts/mp4。
同一视频多清晰度自动分组、默认仅勾选文件最大(最高清)一条。
2.2 零依赖、无构建
整套插件就是 8 个 JS + 3 个 PNG + 1 个 manifest。开发者无需装 npm/yarn/webpack,git clone 后直接 chrome://extensions → 加载已解压 → 选 video-harvester/ 即用。175 例单测也是裸 Node 直跑。
2.3 真正的签名/鉴权续期
对带时效签名的视频/CDN 地址,插件不破算法,而是:
- 捕获 :webRequest.onBeforeSendHeaders 把页面真实发出去的完整请求头(含 Authorization: Bearer、会话 Cookie、自定义 X-*)原样记下(按 pdfStableKey+域名缓存 20 分钟)。
- 重放 :在 chrome.declarativeNetRequest 层原样 set 回去,因为是网络层注入 (CORS 检查之后),不受 SameSite=Lax 限制、不触发 CORS 预检。
- 过期时:自动静音打开源页面,刷新签名与 Cookie,断点续传继续。
这条链路足以覆盖公众号文章视频、智慧教育 PDF、B 站正片、CDN 防盗链等绝大多数主流鉴权模式。
2.4 401 的分层回退
- 主通道:offscreen 拉取 + DNR 注入(最新捕获的完整头)。
- 次通道:页面上下文 fetch 重放(捕获到的 Authorization 透传注入)。
- 兜底:签名续期(重开源页面,换新地址 + 续传)。
2.5 断点续传(OPFS)
- 视频下载(HLS 切片)走 Origin Private File System ,流式写入 part_<taskId>。
- SW 30s 休眠或浏览器关闭后,由 chrome.alarms 每分钟保活 + 启动时 recoverTasks() 自动续传。
- 响应三态 206/200/416 全部覆盖,已下载字节不重传。
2.6 独立面板窗口
点工具栏图标 → chrome.windows.create({type:'popup'}) 弹一个真窗口 ,点页面其他地方不会消失;下载(HLS 合成)不会中断。再点图标会聚焦已有面板并自动跟随当前标签页,而不是新开一个。
2.7 PDF 友好
- 收录口径 isMedia = isVideo || isDoc,PDF 任务默认勾选。
- 文件名按页面标题,URL 是 UUID 才退回网页标题。
- 落盘文件名与扩展名 经 v0.3.5 修复:blob MIME 严格按任务类型(PDF→application/pdf),chrome.downloads.onDeterminingFilename 强制锁定标题名不被 blob URL 段污染。
2.8 智能命名
- 页面标题 + 同源序号 _1, _2, ...。
- B 站等多段视频:标题_1.mp4, 标题_2.mp4。
- URL 末段纯数字递增时(如 123456.mp4文件名带序号)智能补全123456.mp4~123466.mp4。
- 不安全的字符(/\:*?"<>|)自动清洗。
2.9 站点覆盖(截至 v0.3.5)
|-----------------|-------------------------------------------------------|
| 站点 | 支持特性 |
| 微信公众号文章 | 内嵌 `playinfo` 解码,按文件大小选最高清 |
| B 站(视频/番剧) | `playurl?fnval=1` 通道取 durl 完整 mp4,120min CDN 过期自动续期 |
| YouTube | 页面上下文 `/youtubei/v1/player` 拿免签名裸直链(无第三方依赖) |
| cdn 类防盗链 | Secure Token 整 URL 可复用,过期后整段 URL 一起刷新 |
| 智慧教育/私有 CDN PDF | webRequest 捕获 + DNR 重放(含 Authorization) |
| 通用直链 mp4 | 走原生 `chrome.downloads`,浏览器内暂停/续传全支持 |
| 通用 HLS | 分片下载 + `ts → mp4` 合成 |
三、软件功能使用介绍及截图
截图均为线框示意图(基于真实 UI 元素位置与文字绘制,未渲染真实像素)。在 docs/screenshots/ 下也有独立 SVG 文件,可直接打开或嵌入到其他文档。
3.1 安装

图:安装示意
- 打开 Chrome,访问 chrome://extensions。
- 右上角开启「开发者模式」。
- 点击「加载已解压的扩展程序」,选择 video-harvester/ 目录。
- 工具栏出现红色 ▶ 图标即安装成功。
- 若以后想升级版本,重新加载同一个目录即可(无需卸载)。
首次安装涉及 cookies / webRequest 等权限,Chrome 会弹权限确认,点"允许"。
3.2 打开面板与扫描

图:打开面板与扫描示意
- 打开含视频的页面(公众号文章 等站视频地址无需播放就在页面的脚本里;其他站建议播放几秒触发 XHR 加载)。
- 点击工具栏 ▶ 图标,独立面板窗口弹出,自动跟随当前活动标签页。
- 切到「本页视频」页:插件会列出该页全部已识别的视频/文档。
三色徽标:
- 🟦 el 来自 DOM 元素
- 🟦 stream 来自 HLS 播放列表或页面内嵌直链
- 🟪 net 来自网络嗅探(XHR/fetch)
默认行为:同源视频多清晰度分组展示、自动仅勾选文件最大(最高清)一条 ;若该站只用单一 URL,默认全选。
3.3 下载与管理

图:下载与管理示意
- 勾选想要的条目 → 点「下载选中」。
- 切到「下载队列」页可看到实时进度、状态、速度、剩余字节。
- 队列行操作:
- 进行中 ------ 暂停 / 取消
- 失败 ------ 重试 / 移除
- 已完成 ------ 移除
每个任务会有如下状态之一:
|---------|-------------------------------------------|
| 状态 | 含义 |
| `排队` | 等待下载槽位(受"同时下载任务数"限制) |
| `拉取` | 正在从服务器取字节(HLS 在分段下载/合成中) |
| `保存` | 已下载完,落盘到 `~/Downloads/VideoHarvester/` |
| `暂停` | 手动暂停,可恢复 |
| `续期中` | 签名过期,正在重开源页面换新地址,会自动续传 |
| `失败` | 终止,可重试或移除 |
3.4 独立面板与保活
- 面板是真窗口 (chrome.windows.create),点浏览器页面其他地方不会让面板消失。
- 面板窗口关闭后,分钟级 chrome.alarms 会唤起 SW 继续处理队列,避免中途被回收。
- 再次点 ▶ 图标:若面板已开,聚焦并跟随当前活动标签 ;若已关,重新打开。
3.5 设置

图:设置示意
- 同时下载任务数:1--5(默认 2)。数值越大带宽占用越高,CDN 可能限速。
- HLS 分片并发数:1--8(默认 4)。切片越多越能吃满带宽。
- 设置持久化到 chrome.storage.local,SW 启动时立即应用。
3.6 签名续期(自动)

图:签名续期(自动)示意
对带时效签名的视频(公众号、cdn、私有 CDN 等),下载时遇到 401/403:
- 队列行变 续期中 黄色状态条,并显示"正在重打开源页面换新地址..."。
- SW 静默重开源页面 → 内容脚本扫描到新直链 → webRequest 捕获。
- 把新直链塞回下载任务,走断点续传,已下载的字节不会重传。
- 全程无需用户手工点开页面。如果三次续期都失败,任务置为 失败 等待重试。
3.7 通用直链与 HLS
- 直链 mp4/webm :插件把 URL 交给 chrome.downloads,浏览器原生下载器接管,支持暂停/续传、显示速度。
- HLS m3u8:插件解析 m3u8 → 并发拉取所有 ts 分片 → 在 offscreen 文档里合并为 mp4。期间 OPFS 持续落盘。
- 同一任务多段 (B 站多 P / 公众号多段):自动展开为 标题_1.mp4 ... 标题_N.mp4,每段独立可下载。
3.8 PDF 文档
- 页面内若链接指向 .pdf,且符合收录规则,会在「本页视频」页与视频一起列出。
- 插件按 PDF 任务的稳定键(剥掉路径里 ≥10 位长数字块)匹配续期/重扫。
3.9 常见问题
Q:每次下载仍弹"另存为"?
A:这是浏览器级设置「下载前询问每个文件的保存位置」在起作用。打开 chrome://settings/downloads,关闭该开关即可。插件首启会给出此引导。
Q:视频没出现在列表里?
A:先点页面里的播放按钮让视频加载几秒(很多站点的视频地址是开始加载后才出现的 XHR),再点「重新扫描」。如果「重新扫描」不启作用,则浏览器的当前标签再点击刷新一下,等待几秒。
Q:下载一直停在「续期中」?
A:少数站点要求登录态才能换发地址。请先在该站正常登录一次,再回插件面板重试该任务。
Q:能下载哪些视频?
A:合法自有内容、被授权的素材。禁止用于侵犯版权或绕过付费墙 。插件本身不破解 任何加密,遇到私有鉴权时只复用浏览器自己拿到的真实请求头,不构造伪请求。
3.10 测试与质量
- 175 +例单测覆盖 PDF 稳定键、命名规则、CORS/Referer 头注入、签名捕获与重放、Most-thorough 头注入、文件落盘锁定、下载队列调度等核心逻辑。
附:版本与权限
权限说明
|-----------------------------------------|-------------------------------------|
| 权限 | 用途 |
| `downloads` | 创建/监听下载、获取下载项元信息 |
| `storage` | 持久化任务队列与设置 |
| `unlimitedStorage` | OPFS 断点续传需要充裕配额 |
| `tabs` | 跟踪当前活动标签、签名续期打开源页面 |
| `webRequest` | 观察 PDF/CDN 请求的完整头(捕获 Authorization) |
| `scripting` | 给续期用的源页面注入内容脚本(拿新直链) |
| `offscreen` | 跑 HLS 合成与 OPFS 续传 |
| `alarms` | SW 周期保活,避免 30s 休眠中断下载 |
| `cookies` | 读页面会话 Cookie,用于 SameSite=Lax CDN 鉴权 |
| `declarativeNetRequestWithHostAccess` | 网络层注入 Referer/Cookie/Authorization |
*本插件遵循"不破解、只采集与续期"原则。所有鉴权均通过复用浏览器自身抓到的真实请求头完成,遵守目标站点的使用条款与版权法规。*