5.0 KiB
BiliDownloader
哔哩哔哩视频下载器 —— Python 零依赖本地服务 + shadcn/ui 界面 + Edge 应用模式窗口
这是弃用 WinUI3 后的重构版。旧版(C# / WinUI3,位于
E:\deepseek\BiliDownloader)能编译能跑, 但需要 MSIX 打包且本机存在 WinUI3 启动限制;这一版改成浏览器界面,双击即用、无运行时依赖。
启动
双击 start.cmd —— 它会起本地服务并打开一个 Edge 应用模式窗口(无地址栏、无标签页,看起来就是独立应用)。
停止:双击 stop.cmd。
也可以手动:
python server.py # 起服务并自动开窗口
python server.py --no-open # 只起服务,自己用浏览器打开 http://127.0.0.1:8799/
功能
- 站内搜索:WBI 签名的官方搜索接口,卡片列表展示封面 / 标题 / UP主 / 时长 / 播放量
- 粘贴链接或 BV 号直接解析
- 清晰度可选:按真正能下到的流列出(不是标称支持),默认最高
- 多线程加速下载:文件切段并发下载(默认 16,可调 1~64),断线按分片续传,支持跨进程断点续传
- 实时进度:SSE 推送,总体 + 视频流 + 音频流三条进度、实时速度、速度曲线、ETA
- ffmpeg 无损封装为 mp4,产物文件名带清晰度
- 深浅色主题(默认深色)并记忆
架构
BiliDownloaderWeb/
├─ start.cmd / stop.cmd 双击启动 / 停止
├─ server.py 本地 HTTP 服务(标准库 http.server,只监听 127.0.0.1)
│ JSON API + SSE 进度推送 + 托管前端产物
├─ engine.py 下载引擎(已实测验证的核心逻辑)
│ ├─ WBI 签名的站内搜索
│ ├─ 视频详情 / 分P / 清晰度
│ ├─ 多线程分段下载(Range 分片 + 每片重试 + 旁路状态文件续传)
│ └─ ffmpeg 封装
├─ config.json sessdata / outputDir / threads / preferAvc / keepParts
├─ ui/ React 19 + Tailwind 4 + Vite 7 + shadcn/ui(new-york)
│ └─ src/{App.tsx,components/,lib/}
└─ tools/ 验收脚本
├─ smoke_api.py 后端 API 冒烟
├─ e2e_download.py 端到端下载验收(含 ffprobe 与全片解码校验)
└─ ui-check.mjs 浏览器端验收(Edge 无头 + CDP,真的驱动一次搜索)
为什么是"本地薄服务 + 浏览器界面":前端需要跨域访问 B 站 API、需要写本地磁盘、需要用 ffmpeg,
浏览器自己做不到,所以后端必须存在;而这层后端用 Python 标准库就够,零第三方依赖,
engine.py 里那套逻辑也已在上一轮里逐项实测过。
验收结果(都是实测,非推断)
后端 API(tools/smoke_api.py)
| 项 | 结果 |
|---|---|
| 站内搜索 | numResults=1000,返回 20 条,封面 URL 正常 |
| 视频详情 | 标题/UP主/时长/分P 全部正确 |
| 清晰度列表 | 按 dash.video 实际流构建 |
端到端下载(tools/e2e_download.py)—— 13/13 通过
产物: [4K]当你用《航拍中国》的方式打开崂山育才——航拍育才 [480P标清].mp4
大小: 11.2 MB 流: h264 852x480 + aac
时长: 90.0s(源 91s) 全片解码: 无错误
速度: 峰值 15.9 MB/s,16 线程 耗时: 2.0s
中间文件: 已清理
浏览器界面(tools/ui-check.mjs,Edge 无头 + CDP)—— 18/18 通过
其中包含真的驱动界面:填入关键词 → 触发提交 → 等结果渲染(21 个卡片)→ 点选第一个 → 等清晰度解析 → 断言「开始下载」可点。另有:React 挂载、深色主题生效、无横向溢出、零脚本错误。
两个必须知道的坑(都踩过)
1. 清晰度列表必须取 dash.video,不能取 accept_quality
accept_quality / support_formats 只反映视频标称支持什么,与当前账号能否下载无关。
实测:未登录时 accept_quality 仍列出 120(4K),但 dash.video 里只有 32(480P)。
按前者建列表会让用户选到根本拿不到的清晰度,点下载才报错。
2. 产物文件名必须带清晰度
否则同一视频下不同清晰度会互相覆盖 —— 实测踩过:480P 的验收下载把之前下好的 4K 文件直接盖掉。
配置
config.json(与 server.py 同目录):
{
"sessdata": "...",
"outputDir": "E:\\deepseek\\downloads",
"threads": 16,
"preferAvc": true,
"keepParts": false
}
threads 实测:16 线程约 4.1 MB/s,32 线程约 6.8 MB/s;过高可能触发 CDN 限流。
⚠️
sessdata等同于账号登录凭据,明文存在本机。别把这个目录分享给他人。 未登录/失效时 B 站只放出 480P 及以下,界面会明确提示。
重新构建前端
cd ui
npm install # 首次
npm run build # 产物到 ui/dist,由 server.py 托管
npm run dev # 开发模式(热更新,代理 /api 到 8799)