120 lines
5.0 KiB
Markdown
120 lines
5.0 KiB
Markdown
# BiliDownloader
|
||
|
||
哔哩哔哩视频下载器 —— **Python 零依赖本地服务 + shadcn/ui 界面 + Edge 应用模式窗口**
|
||
|
||
> 这是**弃用 WinUI3 后的重构版**。旧版(C# / WinUI3,位于 `E:\deepseek\BiliDownloader`)能编译能跑,
|
||
> 但需要 MSIX 打包且本机存在 WinUI3 启动限制;这一版改成浏览器界面,双击即用、无运行时依赖。
|
||
|
||
## 启动
|
||
|
||
双击 **`start.cmd`** —— 它会起本地服务并打开一个 Edge 应用模式窗口(无地址栏、无标签页,看起来就是独立应用)。
|
||
|
||
停止:双击 `stop.cmd`。
|
||
|
||
也可以手动:
|
||
|
||
```powershell
|
||
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` 同目录):
|
||
|
||
```json
|
||
{
|
||
"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 及以下,界面会明确提示。
|
||
|
||
## 重新构建前端
|
||
|
||
```powershell
|
||
cd ui
|
||
npm install # 首次
|
||
npm run build # 产物到 ui/dist,由 server.py 托管
|
||
npm run dev # 开发模式(热更新,代理 /api 到 8799)
|
||
```
|