Skip to content

BilbliCopy for Windows v1.0.0

Choose a tag to compare

@github-actions github-actions released this 30 Jul 06:35
· 0 commits to f70de45b0c26577523f1a69c9ab0a00c4d11ef2e since this release

v1.0.0 更新内容

🎉 1.0 正式版:首个稳定里程碑版本。功能全面成型(下载 / 在线播放 / 浏览 / 专栏 / 弹幕字幕 / 防风控),本次附带多项稳定性修复与性能优化。

⚠️ 重要:不兼容 0.x 旧数据(Breaking Change)

  • 1.0 与 0.x 数据结构断代,建议所有用户直接下载全新安装包安装
  • 老版本用户升级后,本地解析记录 / 下载历史 / 播放进度 / 搜索历史将被重置(首次启动自动重建数据库,已下载的视频文件不受影响)
  • 登录凭证与常规设置项保留;个别远古版本(≤ v0.5)的设置文件若无法识别将重置为默认值
  • 工程层面:移除 0.x 的 8 版数据库增量迁移链与旧设置格式兼容代码,schema 版本不匹配时整库重建,后续维护更简单

✨ 新功能(自 v0.10.1 后累积)

发现页:搜索历史 + B站热搜榜

  • 未搜索时展示最近 10 条搜索历史(胶囊标签,支持单条删除/一键清空)与 B站实时热搜榜(前 3 名高亮)
  • 点任意词条立即搜索;搜索词自动落库去重置顶(本地保留最近 50 条)

详情页:简介展开 / 一键复制

  • 简介支持展开全文/收起(保留换行排版),右上角一键复制全文到剪贴板

🐛 修复

在线播放器「播着播着流失败」

  • 分块拉流失败自动退避重试(最多 4 次),瞬时网络抖动/代理超时不再中断播放
  • 修复 endOfStream 竞态:短视频播完时偶发的「播放流加载失败」误报

专栏导出 PDF 只有 1 页

  • 改用离屏 iframe 打印:长文章正常分页,图片等待加载完成不再空白,图片/引用块不跨页拦腰截断,导出始终白底黑字

大会员专享内容报错不明

  • 番剧会员集无权限时透传真实原因(不再是笼统的「均失败」),并停止无效的逐档降级请求
  • 新增试看流检测:不再把几分钟试看片段当正片下载/播放,明确提示「仅能获取试看片段,已取消」
  • 前端新增大会员/充电/付费类友好文案,无权限时一目了然

🚀 性能

  • API 连接池化:全部 B站 API 请求共享 keep-alive 连接池,消除每请求 100-300ms 的 TLS 握手开销,浏览页切换筛选/翻页/解析链路明显提速(走代理时收益更大)
  • b23 短链解析补上超时保护,不再可能永久卡死解析流程

📝 升级说明

  • 建议全新下载安装 .msi 或 .exe 安装包;覆盖安装也可,首次启动会自动重置本地历史数据(见上方 Breaking Change)
  • 已下载的视频文件、登录状态不受影响

v0.10.1 更新内容

功能版:「每周必看」浏览页 + 在线播放器「播放列表模式」(跨稿件自动连播)。

✨ 新功能

每周必看

  • 顶栏新增 📅 每周必看入口:接入 B站「每周必看」公开接口,按周浏览官方精选内容
  • 期数选择器:顶部下拉列出历史各期(期数 + 主题 + 日期),默认打开最新一期,可自由切换回看
  • 期数信息头:展示本期封面、主题、更新周期与提醒文案
  • 视频卡片:封面 + 标题 + UP 主 + 时长 + 播放/弹幕/点赞数 + 分区标签,并附编辑精选推荐理由
  • 点卡片解析进详情页(复用既有解析/下载流程);进详情返回后期数选择与列表位置不丢失

播放列表模式(跨稿件自动连播)

  • 一键连播整期:每周必看页顶部「连续播放」按钮,或任意视频旁的 ▶ 图标,从指定位置开始连播本期全部视频
  • 自动切下一集:播放器监听播放结束事件,播完自动加载并播放下一集(复用既有 MSE 重载机制)
  • 连播开关:播放器顶栏「连播」按钮可随时开/关自动连播(本会话记忆)
  • 播放列表面板:顶栏「播放列表 N/M」按钮展开右侧面板,缩略图 + 标题 + UP 主 + 时长,当前项高亮,点任意条目即切集
  • 区别于同稿件「分P选集」:播放列表每项是独立稿件(独立 bvid/aid),适配每周必看、收藏夹等跨视频场景

🐛 修复

  • 修复从非详情视图(如每周必看)点播放/连播无反应:播放器此前被嵌套在「详情视图」渲染条件内,其他视图触发播放时不渲染。现将播放器拆为独立覆盖层,只要存在播放会话即在任意视图弹出

🔧 工程

  • 后端新增 bilibili/weekly.rs 模块与 2 个命令:get_weekly_series(期数列表)、get_weekly_detail(某期详情)
  • 新增前端组件 WeeklyPage.tsx;VideoPlayer.tsx 增加播放列表状态管理与自动切集;types.ts 新增 WeeklySeriesItem/WeeklyDetail/PlaylistItem 等类型

📝 说明

  • 本次无数据库 schema 变更、无新增依赖,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.10.0 更新内容

功能版:专栏/图文阅读器、追番追剧 Tab、在线播放进度记忆(续播)。

✨ 新功能

专栏 / 图文阅读器

  • 应用内直接阅读专栏文章:解析输入框粘贴 read/cv 链接、裸 cv 号或 opus 图文链接,自动打开阅读页(不再走视频解析)
  • 剪贴板 / 拖放感知:复制专栏链接后切回应用,自动识别并打开阅读页,无需手动粘贴
  • HTML 净化渲染:白名单标签过滤(去 script/iframe/事件属性),图片懒加载属性规范化,安全展示原文排版
  • 导出 Markdown:顶栏一键将专栏内容导出为 .md 文件,保留标题层级、图片、引用等结构
  • 支持传统专栏(cv 号)与新版 opus 图文(19 位 id 字符串,避免 JS 精度丢失)

追番 / 追剧 Tab

  • 个人页新增「追番」Tab:展示你的追番(番剧/国创)与追剧(电影/电视剧/纪录片/综艺)列表
  • 追番 / 追剧两个子分类切换,封面 + 标题 + 进度 + 评分,分页加载
  • 点击条目直接解析进详情页,复用既有番剧解析与下载流程

在线播放进度记忆(续播)

  • 播放器自动保存进度:播放中每 5 秒节流落库,关闭 / 切 P 时补存一次
  • 「继续观看」提示条:再次打开同一视频(按分 P),进度 > 5 秒时顶部显示提示条,点击跳转到上次位置;12 秒无操作自动隐藏
  • 看到接近结尾时自动清除记录(下次从头播放);容量控制最多保留 500 条进度

🔧 工程

  • DB schema 升级 v6 → v7(新建 play_progress 表,启动自动迁移,老数据不受影响)
  • 新增 5 个后端命令:get_article_content、export_article_markdown、get_bangumi_follow、get_play_progress、save_play_progress
  • 新增前端组件 ArticleReaderPage.tsx、BangumiTab.tsx;播放器增加续播提示与进度保存

📝 说明

  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.9.0 更新内容

功能版:在线播放器弹幕渲染、播放器快捷键 + 迷你窗 / 画中画、关注动态页。

✨ 新功能

在线播放器弹幕渲染

  • 在线播放器终于有弹幕了:详情页「在线播放」时顶栏新增「弹幕」开关,实时叠加滚动 / 顶部 / 底部弹幕;此前 v0.8.3 就预留了后端 get_danmaku_json 命令但一直未接入,本次补齐
  • 高性能直绘:弹幕拉取后一次性预布局(确定性通道分配,碰撞规则与下载路径的 ASS 弹幕同源),渲染走 requestAnimationFrame 直接画 canvas 覆盖层,不经 React state,密集弹幕也不卡;切 P 自动换弹幕、画质切换不重拉
  • 开关记忆:弹幕开 / 关状态本会话记忆(与画质、倍速同策略);无弹幕的视频按钮自动禁用

播放器快捷键 + 迷你窗 / 画中画

  • 键盘快捷键:空格 播放 / 暂停、← / → 快退快进 5 秒、↑ / ↓ 音量、M 静音、D 弹幕开关、F 全屏、Esc 关菜单 / 退出播放器
  • 迷你窗口:顶栏一键切到右下角浮动小窗,可边看边浏览应用内其他页面;切换时 video 元素不重建,MSE 播放流不中断
  • 系统画中画:调用 WebView2 原生画中画,小窗置顶悬浮于所有应用之上

关注动态页

  • 顶栏新增 📡 关注动态入口:展示你关注的 UP 主最新视频投稿,含 UP 主头像 / 名称 / 发布时间、封面时长角标、播放 / 弹幕数
  • 无限滚动:滚动到底部自动加载下一页(cursor 分页),并保留「加载更多」按钮兜底;追加失败不清空已有列表
  • 未登录时展示登录引导;与其他浏览页一致,进详情返回后列表与游标位置不丢失

🔧 工程

  • 后端新增 get_dynamic_feed 命令(对接 web-dynamic/v1/feed/all,需登录、cursor 分页),注册命令数 55 → 56
  • 新增前端组件 DynamicPage.tsx,播放器 VideoPlayer.tsx 增加弹幕层 / 快捷键 / 迷你窗 / 画中画

📝 说明

  • 无数据库 schema 变更、无新增依赖,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.9 更新内容

功能版:复制链接自动填入、自定义文件名模板、在线播放器倍速+字幕、一键三连。

✨ 新功能

剪贴板 / 拖放感知

  • 复制链接自动填入:在浏览器复制 B 站链接(完整链接 / b23 短链 / 纯 BV 号)后切回应用,自动填入解析输入框,无需手动粘贴;同一链接不会重复填入
  • 拖拽链接入窗:把链接文本直接拖进窗口同样触发填入(任意页面均可,会自动跳回主页)

自定义文件名模板(设置 → 下载)

  • 支持 {title} {video_title} {bvid} {ep} {cid} {up} 六个占位符,/ 表示子目录,如 {up}/{title} [{bvid}] 可按 UP 主归档
  • 留空 = 历史目录结构(合集名/标题.mp4),老用户无感知;非法字符与路径穿越自动清理,超长路径自动裁剪文件名
  • 弹幕/字幕/NFO/封面等附属文件自动跟随模板路径
  • UP 主名持久化到下载记录(DB 升级 v6,自动迁移),暂停后恢复、失败后重试也能落到同一目录

在线播放器增强

  • 倍速播放:顶栏新增倍速菜单(0.5x–2x),画质切换、精准拖动、切 P 后倍速保持(WebView2 原生控件无倍速,本次自建)
  • 字幕轨道:顶栏新增字幕菜单,支持多语言轨道切换,AI 字幕带标注(很多视频只有 AI 字幕);底部覆盖层实时渲染,切 P 自动重置、画质切换不重置

一键三连

  • 详情页互动栏新增「三连」按钮:点赞 + 投 1 币 + 收藏一步完成;收藏夹优先使用你本次手动选过的,否则进默认收藏夹
  • 三步互相独立:投币失败(如今日已投)不阻断收藏,结果分项汇总提示

🔧 工程

  • DB schema 升级 v5 → v6(download_history 增加 owner_name 列,启动自动迁移,老数据不受影响)
  • 在线播放器新增 2 个后端命令(字幕列表 / 字幕内容),注册命令数 53 → 55

📝 说明

  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.8 更新内容

性能与工程优化版:首屏加载瘦身、下载落库降频、CSP 安全收紧,外加一轮内部重构。功能行为不变。

🚀 性能优化

首屏加载瘦身(懒加载 + 分包)

  • 设置页、统计页、在线播放器改为按需加载:SettingsPage/StatsPanel/VideoPlayer 三个体积较大的组件改用 React.lazy + Suspense 懒加载,不再打进首屏 bundle,应用启动更快
  • React 运行时单独分包:Vite 手动拆出 react-vendor chunk,业务代码迭代不会使这部分缓存失效,版本升级后缓存命中率更高

下载进度落库降频

  • 进度 UI 刷新(1.2s 节流)与 SQLite 落库(5s 节流)拆成两级:中途进度仅供异常退出重启后恢复展示,无需高频写库;完成/失败/暂停等状态变更仍实时落库,不受影响

🔒 安全

CSP 收紧

  • connect-src 由通配 * 改为显式白名单('self' + Tauri IPC + biliproxy 代理 + GeeTest),script-src 显式放行 *.geetest.com;在线播放、IPC 通信与验证码功能均不受影响,攻击面更小

♻️ 重构(无行为变化)

  • 下载事件监听(进度节流、状态更新、同步落库)从 App.tsx 抽离为独立的 useDownloadEvents Hook,主组件净精简约 160 行
  • 视频详情页跳转统一为 openDetail 公共函数,各入口行为一致(保留来源视图与 ID 前缀),消除重复逻辑
  • 后端各 B站 API 模块统一改用共享的 api_client() 工厂,删除 8 处重复的客户端构建函数与从未启用的 client.rs 骨架

📝 说明

  • 不改 DB schema、无数据迁移,下载与在线播放的外部行为不变
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.7 更新内容

在线播放器支持多分P切换:多分P视频终于能在播放器里选集播放,不再卡在第一P。

✨ 新增

在线播放器多分P切换(选集菜单)

  • 多分P视频可在播放器内直接切集:详情页点「在线播放」后,顶栏新增「📺 选集」按钮(显示当前 P 号),点开列出全部正片分P,选任意一P 即重新加载并从该P 开头播放
  • 此前多分P视频只能播第一P(在线播放写死了 pages[0].cid);现在分P列表从详情页一路透传到播放器,内部按「当前分P」派生 cid/duration/epId,切集时复用播放器既有的 MSE 重载机制(中断旧流 → 按新 cid 取流),切集时长也跟随该P 更新
  • 单P视频不显示选集按钮;切集沿用本会话上次画质,该P没有该画质则自动回退默认档

🐛 修复

画质/选集下拉菜单点不动(z-index 层叠 bug)

  • 修复播放器顶栏下拉菜单(画质、选集)打开后点选项无反应:关闭用遮罩 z-20 高于菜单层(无 z-index),遮罩盖住了菜单项,点击实际落在遮罩上只触发关闭菜单,看起来「点一下就没了」。给菜单加 z-30 修正层级
  • 画质菜单为既有潜伏 bug(v0.8.5 引入),本次随选集菜单一并修复

📝 说明

  • 仅在线播放器生效,下载路径不受影响;无新增依赖、不改 DB schema,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.6 更新内容

在线播放器流畅度大版本:精准拖动秒到 + 代理连接复用 + 拖动不黑屏。

✨ 新增

在线播放器精准拖动(解析 sidx 秒级 seek)

  • 拖动进度条到未缓冲处,~1s 内从目标位置续播,不再像以前那样要从当前缓冲末端顺序下载到目标点(拖得越靠后越慢)
  • 实现:解析 B站 DASH 流的 sidx(Segment Index)盒,建立「时间→分片字节」索引;拖动时跳到目标分片的 moof 字节拉取(moof 自带绝对时间,MSE 按真实时间放置,无需时间重映射)
  • 新增后端模块 mp4_seek.rs(ISO BMFF box + sidx 解析,含单测)与命令 get_seek_index;前端监听原生 seeking 触发精准 seek,解析失败/无索引时自动回退顺序填充(无回退)

拖动不黑屏(冻结帧 overlay)

  • 拖动重建播放流的瞬间不再黑屏:播放时持续把最近帧缓存到隐藏 canvas,拖动时显示该帧盖住重建期的清屏,新帧渲染后移除

🚀 性能优化

代理连接复用(拉流更顺、起播更快)

  • biliproxy 改用池化的 HTTP client(keep-alive 连接复用),此前每个 2MB 分块都新建 TCP+TLS 握手到 B站 CDN(每块多 ~100-300ms),上百块累计显著拖慢;复用后连续分块几乎瞬到,起播、缓冲跟手、切画质追帧都更快

📝 说明

  • 仅在线播放器生效,下载路径不受影响;无新增依赖、不改 DB schema,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.5 更新内容

在线播放器画质选择 + 一批播放器/弹幕设置修复。

✨ 新增

在线播放器画质选择 + 取消 1080P 硬上限

  • 详情页播放器顶栏新增「⚙ 画质」选择:列出该视频所有可选画质(360P…1080P…),点选即切换,当前档打勾
  • 取消在线播放的 1080P 人为上限:画质封顶由 1080P 提到 4K,凡 B站 提供 AVC 的画质都会出现在菜单(视账号可有 1080P 高码率 / 60 帧等)
  • 切画质从原位置续播:切换后自动重建播放流并快速追帧到当前进度继续,无需从头看
  • 本会话记住上次画质选择:换一个视频仍沿用你上次的清晰度
  • 编码策略:保持在线仅 H.264/AVC(webview 兼容性最好);下载路径完全不受影响,仍用用户自定义编解码器
  • 说明:B站 4K/8K 几乎只提供 HEVC/AV1、极少 AVC,故 AVC-only 下多数视频菜单最高到 1080P;4K/8K 留待后续放开 HEVC/AV1 支持

🐛 修复

在线播放器「SourceBuffer is full」中断(长视频 / 切画质)

  • 根因:限流读的是 video.buffered(视频/音频两路 SourceBuffer 的交集),一路慢了会让另一路误判「前方不足」无限狂拉 → 撑爆配额报错中断
  • 修复:改为按「本条流自己的缓冲」限流;从 currentTime 起即回收已播放段;appendBuffer 配额不足时强制回收重试;启动期盲目拉取封顶 4MB;出错立即停掉另一条流

竖屏视频下半部分被裁切看不到

  • 根因:flex 子项默认 min-height:auto 不允许收缩,竖屏视频原生很高会把播放区撑到视口外,下半部分被推出屏幕
  • 修复:播放区加 min-h-0 允许压缩到剩余高度,视频加 object-contain,竖屏画面完整按比例显示

在线播放器进度条消失

  • 重写播放器时误删了 <video> 的 controls,导致原生进度条/控制条不显示;已恢复

弹幕透明度设置反转

  • 根因:「透明度」控件用 低/中/高 标签,但值是 opacity(越高越不透明)——选「高」反而最不透明,与「高透明度」直觉相反
  • 修复:改为直观标签「不透明 / 半透明 / 透明」,且选最近档位时总有高亮项
  • 注:仅影响新生成的 ASS 弹幕文件,已下载视频需重新生成弹幕才生效

📝 说明

  • 本次无数据库 schema 变更、无新增依赖,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.4 更新内容

紧急修复:v0.8.3 的内置播放器在正式版无法播放(CSP 拦截了 MSE 的 blob 视频源)。

🐛 修复

正式版播放器无法播放(CSP 拦截)

  • 修复 v0.8.3 在线播放器在正式版完全无法播放的问题:根因是生产 CSP 缺少 media-src,MSE 生成的 blob: 视频源被 default-src 'self' 拦截(开发版 Tauri 自动放宽 CSP,故未暴露此问题)
  • CSP 新增 media-src 'self' blob: data: 放行 MSE 视频源;connect-src 显式加上 biliproxy:,确保代理流拉取不被拦

📝 说明

  • 仅 CSP 配置变更,无数据库 schema 变更、无新增依赖,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.3 更新内容

新增「内置在线播放器」:详情页可直接在线播放视频,无需先下载。

✨ 新增

内置在线播放器(MSE)

  • 详情页新增「▶ 在线播放」按钮:点击直接在应用内播放,黑底全屏播放器 + 原生控件(播放/暂停/进度/音量/全屏),无需先下载到本地
  • 在线播放强制 H.264 / AVC:webview 的 MSE 对 H.264(avc1)+AAC 支持最完整;下载路径完全不受影响,仍用用户设置的画质/编解码器优先级
  • 按播放节奏边下边播:仅在「前方缓冲不足 30s」时拉取下一块,并自动回收已播放段,大视频也不会撑爆内存配额
  • 通过自定义 biliproxy 协议代理 B站流:补 Referer 头、绕过跨域、透传 Range 分块请求

🔧 实现

  • 后端:biliproxy 自定义协议(B站流代理)+ get_play_streams(取 H.264 流)+ get_danmaku_json(弹幕,本版未启用)
  • 前端:VideoPlayer.tsx(MediaSource 双 SourceBuffer:视频 avc1 + 音频 mp4a,Range 分块 append)

📝 说明 / 已知限制

  • 本版为播放器 MVP(暂未接入弹幕):支持完整顺序播放、已缓冲范围内拖动进度条
  • 大幅向前跳转(seek 到未缓冲处)会停顿:B站 DASH 为单个 fMP4、无「时间→字节」索引,无法精确定位。顺序观看完全正常,此限制留待后续优化(解析 sidx 或改分段策略)
  • 本次无数据库 schema 变更、无新增依赖,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.2 更新内容

修复 + 界面布局优化版本:修复个人页等级/硬币/UP 主投稿数显示为 0 的问题,并优化详情页布局与默认窗口尺寸。

🐛 重要修复

个人主页 / UP 主主页数据显示为 0

  • 修复个人主页「等级」「硬币」一直显示为 0
    • 等级:B站 nav 接口的等级字段是 level_info.current_level,原代码误用 level 字段名,serde 匹配不上导致恒为 0
    • 硬币:B站 nav 的 coins 字段对多数账号不再返回真实余额(恒为 0),改用专用接口 account.bilibili.com/site/getCoin 获取真实硬币数
  • 修复 UP 主主页「投稿数」一直显示为 0:B站 web-interface/card 的 archive_count 在 data 顶层(非 card 内),原代码读错路径导致恒为 0

🎨 界面布局优化

详情页双栏布局

  • 详情页改为双栏(宽屏下):左栏常驻显示封面 + 标题 + UP 主 + 统计 + 互动 + 简介,右栏滚动显示分P 列表 + 评论区
  • 视频信息常驻可见,选 P / 看评论无需来回滚动;窗口较窄时自动回退单栏整体滚动

面包屑导航

  • 详情页与 UP 主主页头部新增面包屑(来源 › 当前页),back 按钮显示来源页名称
  • 发现 → 视频详情 → UP 主主页 → 新视频 的导航层级一目了然,明确「返回」会回到哪里

默认窗口调大

  • 默认窗口由 700×500 调整为 1080×720,最小尺寸 600×400 → 800×600
  • 详情页双栏与各浏览页有更舒适的展示空间

📝 说明

  • 本次无数据库 schema 变更、无新增依赖,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.1 更新内容

小版本:详情页新增「点击 UP 主头像进入其主页」入口,纯前端改动。

✨ 新增

详情页 → UP 主主页

  • 详情页点头像即可进入 UP 主主页:点击 UP 主卡片(头像 / 名称)进入该 UP 主主页,查看其全部投稿与合集/列表
  • 完整复用既有主页能力:投稿/合集 Tab、UP 主信息卡(粉丝 / 关注 / 投稿数)、长列表虚拟化与无限滚动,与「发现」搜索到的 UP 主主页体验一致
  • 导航栈清晰:进入 UP 主页后点「返回」回到原视频详情;在 UP 主页点开任一视频则直接替换为该视频的详情页(返回仍回到来源页)

🔧 实现

  • 新增 UpperHomePage 组件统一封装 UP 主主页全屏布局,「发现」搜索与「详情页点头像」两处复用,消除原先的内联重复
  • UP 主主页覆盖层以更高 z-index 叠加在视频详情覆盖层之上(嵌套渲染,无需改动既有 9 个视图的切换逻辑),无新增后端命令

📝 说明

  • 本次为纯前端改动,无数据库 schema 变更、无新增依赖,升级无数据迁移
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.8.0 更新内容

本次为性能与稳定性版本:长列表虚拟化 + 下载/解析引擎优化 + 修复跨天搜索失效等严重问题。

✨ 新增

长列表虚拟化(收藏夹 / 投稿 / 合集)

  • 收藏夹内容、UP 主投稿、合集视频改为虚拟化列表:只渲染可视区域内的卡片,不再一次性挂载全部 DOM 节点
  • 无限滚动:滚动到列表底部附近自动加载下一页(同时保留「加载更多」按钮作为兜底)
  • 打开上千视频的收藏夹 / 投稿列表时,滚动流畅、内存占用稳定,不再因海量封面图导致界面卡顿

🚀 性能优化

下载引擎

  • 分片写盘启用 BufWriter(64KB 缓冲):合并网络小数据块后再落盘,大幅减少系统调用次数
  • 续传进度位图降频落盘:从「每个分片完成都写一次」改为「每 8 个分片 + 最后一个」,写盘次数从 N 降到 ~N/8;失败 / 中断时补落一次,保证续传位图一致
  • 单线程续传下载同样启用 BufWriter

视频流解析

  • playurl 改为单次请求:利用 B站 fnval=4048 一次返回所有画质的能力,绝大多数情况一次请求即可选中目标画质,避免逐档降级的多次往返(最坏情况请求数从 ~10 次降到 1 次),同时降低触发风控的概率

网络并发

  • 登录校验的 nav 与关注 / 粉丝数查询并行(tokio::join!),省一次往返
  • 下载副产物(弹幕 + 字幕)并行下载,省一次往返
  • WBI 密钥获取加 fetch 锁:消除冷启动 / 密钥过期瞬间多个请求同时打 nav 接口的惊群

🐛 重要修复

WBI 密钥跨天失效(严重)

  • 修复跨天后搜索 / 投稿 / 合集列表全部失效、必须重启程序才恢复的问题:WBI 密钥缓存新增 12 小时 TTL,B站每日轮换密钥后会自动刷新,不再用过期密钥签名

per-video 信号量泄漏

  • 修复下载调度中 per-video 信号量表随使用无限增长的内存泄漏:原清理逻辑在 permit 未归还时永不触发,实际从不回收;改用引用计数判定「无其他任务在用」时安全移除

🎨 前端优化

  • 下载进度事件节流:UI 更新与数据库写入统一节流,修复「下载时整个界面高频全量重渲染」导致的卡顿
  • 下载列表行级 memo:下载进行时只有进度变化的那一行重绘,其余行跳过
  • UpdateContext 值对象 memo:避免更新流程中无谓的消费者重渲染

🧪 工程修复

  • 修复测试编译错误(download_manager 测试 helper 缺少 audio_only 字段)
  • 修正数据库迁移测试中过时的版本断言(v4 / v5 迁移加入后未同步)

📝 说明

  • 本次未改动数据库 schema,升级无数据迁移
  • 依赖新增 @tanstack/react-virtual(前端列表虚拟化)
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.7.6 更新内容

✨ 新增

下载完成桌面通知

  • 完成即通知:视频下载完成时发送 Windows 系统桌面通知,标题「下载完成」,正文带视频标题(如「《xxx》已下载完成」)
  • 窗口最小化到托盘时尤其有用:不盯着窗口也能第一时间知道下载完成
  • 设置开关:设置 → 通用 → 窗口与托盘 → 新增「下载完成通知」开关,默认开启;关闭后下载完成不弹通知
  • 复用上次托盘功能已安装的 tauri-plugin-notification,无需新增依赖

🔧 实现亮点

  • 后端触发:在 download_manager.rs::finalize_outcome 的 Done 分支中读 settings.json → 根据 notify_on_complete 决定是否发通知。读设置失败时静默跳过,不影响下载主流程
  • 完成时已拿到 title:finalize_outcome 新增 title: &str 参数(spawn 闭包内 params 被 move 之前先 clone),通知正文用真实视频标题
  • 设置 UI 沿用现有模式:与「关闭时最小化到托盘」同一张 SettingCard 风格,复用 ToggleSwitch 组件

📝 说明

  • 本次未改动数据库 schema,升级无数据迁移
  • settings.json 新增字段 notify_on_complete(默认 true),旧版本配置自动迁移,默认开启通知
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送

v0.7.5 更新内容

✨ 新增

系统托盘最小化(关闭窗口后台继续下载)

  • 关闭即最小化到托盘:点击窗口关闭按钮不再直接退出,而是最小化到系统托盘,程序在后台继续运行
  • 后台下载不中断:下载调度器是独立后台任务,窗口隐藏后所有进行中 / 排队中的下载任务照常执行
  • 托盘菜单:右键托盘图标可「显示主窗口」或「退出」(真正退出进程)
  • 点击托盘恢复:左键单击 / 双击托盘图标即可恢复主窗口
  • 首次最小化提示:第一次最小化到托盘时弹一次系统通知(Windows 原生),告知「程序在后台运行、下载不会中断」,之后不再打扰

可配置开关

  • 设置 → 通用 → 窗口与托盘:新增「关闭时最小化到托盘」开关,默认开启
  • 关闭此开关后,点击关闭按钮恢复为传统行为(直接退出应用),进行中的下载会被中断

下载统计面板

  • 顶部导航新增 📊 统计入口,进入独立「下载统计」视图,展示:
    • 累计下载视频数(已完成数量 + 全部记录数)
    • 总大小(已完成下载的总字节数,自动换算 B/KB/MB/GB)
    • 总时长(已完成下载的总时长,自动换算为 Xh Ym 形式)
  • 统计口径采用累加器:下载完成时直接累加到独立的 download_stats 表,与下载历史解耦。
    • 删除/清空下载列表中的视频,累计统计不会回退——记录的是"曾经下载过多少"。
    • 重试/重复完成同一视频只计一次(仅在状态从非 done 转为 done 时累加)。

🗄️ 数据库变更

  • v4 schema 迁移:download_history 表新增 size(最终文件字节数)、duration(视频时长秒)两列。
    • 下载完成时由 std::fs::metadata 计算最终文件大小落库;时长在提交下载时写入。
  • v5 schema 迁移:新建 download_stats 累加器表(单行)。
    • 升级时自动把已有 status='done' 记录回填进累加器,历史数据不丢失。
  • 两步迁移均幂等(column_exists / CREATE TABLE IF NOT EXISTS 保护),老用户平滑升级。

🔧 实现亮点(托盘)

  • 零后台逻辑改动:下载调度器 run_dispatcher 本就是独立的 tauri::async_runtime::spawn 后台任务,与窗口生命周期解耦,窗口只要隐藏(而非销毁)下载自然继续
  • Tauri 2 原生托盘 API:启用 tauri 的 tray-icon feature,复用 icons/icon.ico 作为托盘图标,无需新增图标资源
  • 关闭拦截:在 on_window_event 中捕获 CloseRequested,根据 close_to_tray 设置决定 prevent_close() + 隐藏,或放行退出;托盘「退出」走 app.exit(0) 绕过拦截实现真正退出
  • 首次提示持久化:settings.json 新增 tray_hint_shown 字段记录是否已提示过,原子写入防止丢失
  • 新增 tauri-plugin-notification:用于首次托盘提示的系统通知

📝 说明

  • settings.json 新增字段 close_to_tray(默认 true)和 tray_hint_shown(默认 false),旧版本配置自动迁移,默认开启托盘最小化
  • Windows: 下载 .msi 或 .exe 安装包覆盖安装,应用内自动更新将在后台推送