Jianwu Huang
e5c6b89be4
Merge pull request #428 from pumpkinperson996/fix/ytdlp-zero-retries
...
fix(downloader): yt-dlp 未设 retries 时零重试,一次网络抖动就让任务失败
2026-08-25 13:57:33 +08:00
Jianwu Huang
674c4a8feb
Merge pull request #427 from pumpkinperson996/fix/youtube-format-not-available
...
fix(youtube): 修复 YouTube 笔记生成失败 "Requested format is not available"
2026-08-25 13:57:27 +08:00
Jianwu Huang
73e509868a
Merge pull request #425 from pumpkinperson996/agent/fix-whisper-model-selection
...
Fix Whisper model selection caching
2026-08-25 13:57:21 +08:00
Jianwu Huang
05f28dad29
Merge pull request #422 from pumpkinperson996/fix/bcut-upload-session
...
fix: 必剪转写实例复用导致的上传状态残留与并发竞争
2026-08-25 13:57:14 +08:00
Jianwu Huang
11396e47d3
Merge pull request #423 from pumpkinperson996/fix/frontend-schemeless-url
...
fix(frontend): 视频链接缺协议头时自动补 https:// 而非直接拒绝
2026-08-25 13:57:09 +08:00
Jianwu Huang
c39ee1d5d8
Merge pull request #421 from pumpkinperson996/fix/normalize-bilibili-url
...
fix: 规范化含 BV 号的任意 B 站链接(稍后再看/收藏夹/追踪参数)
2026-08-25 13:57:02 +08:00
huangjianwu
5f51b34672
test(youtube): keep metadata tests runnable with retry options
2026-08-25 13:54:54 +08:00
Jianwu Huang
f58e6182c4
Merge pull request #438 from katsugtgz/fix/requests-cve-2024-47081
...
fix(deps): bump requests to 2.32.4
2026-08-11 16:55:24 +08:00
OSS Security Bot
f0090f90ad
fix(deps): bump requests to 2.32.4 to resolve GHSA-9hjg-9r4m-mvj7 (CVE-2024-47081)
2026-08-06 18:19:21 +07:00
Jianwu Huang
37bbcaaab2
Merge pull request #436 from JefferyHcool/develop
...
Develop
2026-08-04 16:23:52 +08:00
Jianwu Huang
c277909ed4
Merge pull request #435 from JefferyHcool/codex/docs-kacutai-recommendation
...
docs(readme): 推荐 KaCutAI 素材搜索工具
2026-08-04 16:22:47 +08:00
huangjianwu
990bc69ca2
docs(readme): 推荐 KaCutAI 素材搜索工具
2026-08-04 16:18:00 +08:00
pumpkinperson996
58ec74f2a2
fix(downloader): yt-dlp 未设 retries 时零重试,网络抖动一次任务即失败
...
## 问题
任意一次瞬时网络故障都会让整个笔记任务失败,即便立刻重试同一个链接就能成功。
实际遇到的报错:
ERROR: [download] Got error: HTTPSConnectionPool(
host='upos-sz-mirrorcosov.bilivideo.com', port=443): Read timed out.
同一个视频一分钟后重新提交,10.18 MiB 四秒下完。
## 原因
yt-dlp 文档里 `retries` 默认 10,但那个默认值是**命令行参数解析器**给的,
Python API 不套用。项目所有 `ydl_opts` 都没设 `retries`,于是:
# yt_dlp/downloader/http.py
for retry in RetryManager(self.params.get('retries'), ...) # -> None
# yt_dlp/utils/_utils.py
self.retries = _retries or 0 # -> 0
也就是**每次下载只尝试一次,零重试**。这不是 B 站独有的问题,
YouTube 以及所有走 yt-dlp 的路径都一样。
## 改动
- `base.py`:新增 `YDL_RETRY_OPTS`(`retries` / `fragment_retries` /
`socket_timeout`),两个 downloader 本来就从 base 导入,不额外引入模块。
- `youtube_downloader.py`(2 处)、`bilibili_downloader.py`(3 处):
所有 `ydl_opts` 都展开该常量。只修报错的那一处会把其余四处继续留在零重试。
- 用的是 yt-dlp 自带的重试机制,没有自写重试循环。
取值偏保守(3 次而非 CLI 的 10):笔记任务是用户在前台等的,
重试太久不如早点失败让用户重来。
## 测试
新增 `tests/test_ydl_retry_opts.py`:
- 行为:常量给出的 RetryManager 预算 > 0;并显式钉住
`RetryManager(None).retries == 0` 这个被规避的坑。
- 结构:用 AST 断言两个 downloader 里**每一个** `ydl_opts` 字面量都展开了
`YDL_RETRY_OPTS`,防止以后新增下载路径时又悄悄回到零重试。
结构用例确认过 red-green:去掉任一处展开即失败,并指出具体文件行号。
无 yt-dlp 的环境下两个行为用例自动 skip,与仓库既有测试风格一致。
2026-07-25 12:00:06 -05:00
pumpkinperson996
3e579b1434
fix(youtube): 修复 YouTube 笔记生成失败 "Requested format is not available"
...
## 问题
输入 YouTube 链接生成笔记时任务必定失败:
ERROR: [youtube] <id>: Requested format is not available
即使字幕已经抓取成功(日志里能看到"成功获取 YouTube 字幕,共 N 段"),
任务仍然在下载阶段崩掉。
## 原因
两个独立的问题叠加:
1. `requirements.txt` 把 yt-dlp 钉在 `2025.3.31`。YouTube 之后轮换过
player,旧版 yt-dlp 解不出 nsig 签名,所有音视频格式都被丢弃,只剩下
storyboard 图片(日志:`Only images are available for download`),
格式选择随即抛错。
2. 有字幕时 `NoteGenerator` 走的是"只取元信息"的路径
(`download(skip_download=True)`,只要 title/duration/cover),但
`YoutubeDownloader.download` 无条件设置了
`format='bestaudio[ext=m4a]/bestaudio/best'`。于是一个根本不需要媒体流的
调用,也会因为选不出格式而失败——把一个字幕已经到手的任务整个带崩。
## 改动
- `youtube_downloader.py`:`skip_download` 时设置
`ignore_no_formats_error=True`。yt-dlp 落后于 YouTube 时,只取元信息的路径
降级为"没有音频",而不是让整个笔记失败。
- `youtube_downloader.py`:`ext = info.get("ext") or "m4a"`。跳过下载时
yt-dlp 返回 `ext=None`,`dict.get` 的默认值对显式 None 不生效,
会拼出 `xxx.None` 这样的路径。
- `requirements.txt`:`yt-dlp==2025.3.31` → `>=2026.7.4`。yt-dlp 是对抗
YouTube 变化的滚动依赖,精确钉版本本身就是这个 bug 的成因;用 `>=` 与同文件
的 `youtube-transcript-api>=1.0.0` 保持一致。
- `bilibili_dm_patch.py`:wrapper 改为透传 `**kwargs`。升级 yt-dlp 后
`_real_extract` 会以 `fatal=False` 调用 `_download_playinfo`,而 wrapper
钉死了签名,导致 **所有 B 站下载** 抛
`TypeError: ... got an unexpected keyword argument 'fatal'`。
- 测试:新增 `test_youtube_metadata_only.py` 覆盖上面两条 YouTube 保证;
`test_bilibili_dm_patch.py` 新增未知 kwargs 透传用例,并让 fake 响应带上
`code` 字段(yt-dlp 2026.x 会先校验信封再返回 data)。
## 验证
- 真实跑通:YouTube(有字幕,走元信息路径)与 B 站(无字幕,走完整下载 +
转写)均能生成笔记。
- `pytest tests/` → 46 passed。唯一失败的
`test_task_serial_executor` 在升级前后表现一致,与本次改动无关,未作改动。
2026-07-25 07:37:10 -05:00
pumpkinperson996
e5849ca1af
Honor explicit Whisper model selection
2026-07-20 20:19:44 -05:00
pumpkinperson996
456ee6037a
Fix Whisper model selection caching
2026-07-20 18:46:45 -05:00
pumpkinperson996 and Claude Fable 5
75911667a6
fix(frontend): 视频链接缺协议头时自动补 https:// 而非直接拒绝
...
用户从各处摘抄的链接常常没有 https:// 前缀(如 bilibili.com/...),
表单校验用 new URL() 解析会直接失败,提示"请输入正确的视频链接"。
校验时对无 scheme 的输入先补 https:// 再解析;提交时同样补全后再发
给后端(本地视频路径除外)。已有明确 scheme 的输入不受影响,ftp://
等非 http(s) 协议仍被拒绝。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-09 16:00:13 -05:00
pumpkinperson996 and Claude Fable 5
944985fc94
fix: 必剪转写实例复用导致的上传状态残留与并发竞争
...
BcutTranscriber 被 transcriber_provider 缓存复用,但 __etags 等上传
会话状态只在 __init__ 清空、每次上传只追加,导致容器启动后第二次
及以后的转写提交的 etag 数与分片数不符,B 站返回"第三方服务异常"。
并发提交多个视频时,多个后台任务还会在同一实例上交错上传,etag
互相混入。
- _upload() 开头重置全部上传会话状态,修串行残留
- transcript() 加实例锁,整个转写会话串行执行,修并发交错
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-09 15:44:47 -05:00
pumpkinperson996 and Claude Fable 5
b85d7bc1ff
fix: 规范化含 BV 号的任意 B 站链接(稍后再看/收藏夹/追踪参数)
...
从"稍后再看"(/list/watchlater/?bvid=BV...)、收藏夹播放页等场景
复制的链接会被判为无效链接,尽管其中包含完整 BV 号;校验通过的
链接也会带着追踪参数原样传给 yt-dlp。
在请求入口新增 normalize_video_url():提取 BV 号重建标准
/video/BVxxx 链接,保留分 P 参数(?p=N),丢弃其余查询参数。
b23.tv 短链与其他平台行为不变,无 BV 号链接仍按原逻辑拒绝。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-09 15:03:07 -05:00
huangjianwu and Claude Opus 4.8
bebf2e8c61
fix(backend): 修复 DeepSeek 模型列表为空 & whisper 下载不走代理 ( #417 )
...
问题1 — DeepSeek 模型下拉为空:
provider 的 /models 调用失败时,get_model_list 吞掉异常返回 [],
get_all_models_by_id 再对 [] 取 .data 触发 AttributeError 又被吞,
最终接口返回 {"code":0,"msg":"success","data":[]},把失败伪装成空成功,
用户看不到任何原因。
- 捕获并回传真实错误,不再二次吞
- 新增 model_fallback.normalize_models 兼容 SyncPage/list/dict,绝不再 .data 崩
- 内置供应商提供已知模型兜底清单(DeepSeek→deepseek-chat/deepseek-reasoner,
Qwen→qwen-plus 等),动态拿不到时回退,保证下拉非空;动态可用时仍以动态为准
问题2 — whisper 模型下载不走代理(Docker 里代理没生效):
snapshot_download 既不读 UI 配的代理,HF_ENDPOINT 又固定 hf-mirror.com。
- ProxyConfigManager.apply_to_env() 把生效代理 export 到 HTTP(S)_PROXY/ALL_PROXY,
huggingface_hub 即可复用;在每次下载前与启动时应用(覆盖转写按需下载)
- 网络类下载报错翻译成可操作提示(配代理 / 改 HF_ENDPOINT / 检查容器外网)
- .env.example 补充 HF_ENDPOINT 与代理覆盖说明
新增 tests/test_model_fallback.py、tests/test_proxy_apply_env.py(14 用例)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-29 13:54:44 +08:00
huangjianwu
6d67e5a76a
Merge branch 'hotfix/2.4.4'
v2.4.4
2026-06-23 11:46:41 +08:00
huangjianwu
6a43043874
Merge branch 'hotfix/2.4.4' into develop
2026-06-23 11:46:41 +08:00
huangjianwu
e21e329d42
chore(release): 2.4.4
2026-06-23 11:46:10 +08:00
huangjianwu and Claude Opus 4.8
55946b82ec
fix(deps): 升级 starlette 0.46.1→0.47.2 修复 CVE-2025-54121
...
starlette < 0.47.2 在解析 multipart 表单的大文件时,SpooledTemporaryFile
从内存溢写到磁盘的 rollover 是在事件循环线程内同步执行的,攻击者可借大文件
上传阻塞事件循环造成拒绝服务(GHSA-2c2j-9gv5-cj73)。0.47.2 把 rollover
写入移到线程池(UploadFile.write 命中 _will_roll 时走 run_in_threadpool)。
由于 FastAPI 0.115.12 的约束为 starlette<0.47.0,同步升级 FastAPI
0.115.12→0.116.2(约束放宽至 starlette<0.48.0/<0.49.0),与现有
pydantic 2.11.2 / anyio 4.9.0 / python-multipart 0.0.20 均兼容。
验证:pip check 无冲突;2MB multipart 上传走 rollover 路径正常;
docker 整套栈在新框架下 boot 健康(sys_health backend/db ok)。
Closes #411
Refs GHSA-2c2j-9gv5-cj73
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-23 11:45:28 +08:00
huangjianwu
f5bd0be29a
Merge branch 'hotfix/2.4.3' into develop
2026-06-23 10:52:58 +08:00
huangjianwu
5380f4c412
Merge branch 'hotfix/2.4.3'
v2.4.3
2026-06-23 10:52:50 +08:00
huangjianwu
4ef3631712
chore(release): 2.4.3
2026-06-23 10:52:11 +08:00
huangjianwu and Claude Opus 4.8
4a87c5b93b
fix(transcriber): 下载失败时透传错误到前端并提示
...
issue #402 衍生问题:whisper 模型后台下载失败时,/transcriber_models_status
只回传 downloading/downloaded 两个布尔,failed 态被直接丢弃,于是前端表现为
「点了下载没反应、状态一直未下载、且无任何错误提示」。
后端:新增轻量模块 model_download_state 统一维护下载状态(downloading/done/
failed)与失败原因,config.py 的下载触发与状态查询共享同一份内存态;状态接口
新增 failed 字段,失败时附带 error(仓库 404、网络中断、本地路径缺 model.bin 等)。
前端:模型管理列表新增「下载失败」红色徽标 + 错误详情,按钮在失败后变为「重试」;
自定义模型项同样展示失败图标与原因;并对「本次新出现的失败」弹一次 toast 主动提示。
测试:新增 test_model_download_state 覆盖状态流转(downloading/done/failed、
失败原因透传、downloaded 覆盖 failed、重下清错、mlx key 隔离)。
已用 docker compose 启动整套栈验证:触发本地路径缺失与 HF 仓库 404 两种失败,
/transcriber_models_status 均正确回传 failed:true + error。
Refs #402
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-23 10:50:55 +08:00
huangjianwu and Claude Opus 4.8
3841719d5a
fix(transcriber): 修复 large-v3-turbo 因仓库 404 无法下载
...
Systran/faster-whisper-large-v3-turbo 已从 HuggingFace 下架(API 返回
401/404,仓库不存在)。用户点击下载后,后台 snapshot_download 立即抛错
被吞掉,_downloading 置为 failed 但状态接口只回传 downloading/downloaded
两个布尔,于是表现为:无进度转圈、状态一直「未下载」、前端无错误提示。
改用社区维护的 CT2 转换版 deepdml/faster-whisper-large-v3-turbo-ct2:
HF 直链可达(200,无重定向,保证缓存目录名与存在性检测一致),含
model.bin 等全部所需文件,与 faster-whisper 的 large-v3-turbo 等价。
附回归测试,断言 large-v3-turbo 解析到存活仓库而非已失效的 Systran 仓库。
Closes #402
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-23 10:50:55 +08:00
Jianwu Huang
f072996db5
Merge pull request #412 from JefferyHcool/add-claude-github-actions-1782179231594
...
Add claude GitHub actions 1782179231594
2026-06-23 09:52:52 +08:00
Jianwu Huang
9d424aef59
"Claude Code Review workflow"
2026-06-23 09:47:16 +08:00
Jianwu Huang
48568e52c6
"Claude PR Assistant workflow"
2026-06-23 09:47:14 +08:00
huangjianwu
2c2c2e9982
Merge branch 'hotfix/docker-nginx' into develop
2026-06-17 11:29:17 +08:00
huangjianwu
7baaefd76e
Merge branch 'hotfix/docker-nginx'
v2.4.2
2026-06-17 11:29:02 +08:00
huangjianwu
3002e311ac
chore(release): 2.4.2
2026-06-17 11:17:52 +08:00
huangjianwu and Claude Opus 4.8
ad57bc5489
fix(docker): 修复 Docker 部署打开显示 nginx 欢迎页
...
nginx/default.conf 被 docker-compose(多容器)与 Dockerfile.complete(单镜像)
共用,但两种模式对 location / 的需求相反:多容器需反代独立的 frontend 容器,
单镜像需直接服务本地静态文件。此前共用一份配置,导致其中一种部署总会回退到
nginx 默认欢迎页(本次为 compose 入口 nginx 用了 root 但容器内无前端产物)。
拆分为两份配置,各司其职、互不干扰:
- nginx/default.conf:compose 版,location / 反代 http://frontend:80
- nginx/standalone.conf(新增):单镜像版,location / 服务 /usr/share/nginx/html,
/api、/static 代理到本地 127.0.0.1:8483
- Dockerfile.complete 改用 standalone.conf,移除不再需要的 sed 改写
已用 nginx -t 校验 standalone.conf 语法通过。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-17 11:17:52 +08:00
huangjianwu
fcf1da5c21
Merge branch 'release/2.4.1' into develop
2026-06-17 10:21:03 +08:00
huangjianwu
a7d8995f3a
Merge branch 'release/2.4.1'
v2.4.1
2026-06-17 10:20:57 +08:00
huangjianwu
67486c4d66
chore(release): 2.4.1
2026-06-17 10:00:34 +08:00
Jianwu Huang
54714faa73
Merge pull request #410 from JefferyHcool/fix/bilibili-412-dm-img-params
...
fix(bilibili): 注入 dm_img 风控参数修复 wbi/playurl 412
2026-06-17 09:58:37 +08:00
Jianwu Huang
f6ba347718
Merge pull request #409 from wmsdsb/fix/bilibili-multipart-p-number-clean
...
fix(bilibili): 修正分P视频字幕优先链路未传p参数导致取错集
2026-06-17 09:58:34 +08:00
Jianwu Huang
67253a1bf2
Merge pull request #381 from Loker-Choi/fix/youtube-shorts-url
...
fix(youtube): 支持 Shorts 链接
2026-06-17 09:58:30 +08:00
huangjianwu and Claude Opus 4.8
f79dc612fb
fix(bilibili): 注入 dm_img 风控参数修复 wbi/playurl 412
...
B 站 wbi/playurl 网关新增 dm_img_list/dm_img_str/dm_cover_img_str/
dm_img_inter + web_location 风控校验,缺失即返回 HTTP 412。对于网页不内嵌
playinfo、必须走 API 的视频(如 BV1X9L16oEgB),yt-dlp(含最新版)尚未适配,
导致下载失败,且刷新 cookie 无效。
通过猴补丁在 BilibiliBaseIE._download_playinfo 的 wbi 签名前注入哑值 dm_img
参数(取值形态对齐 yt-dlp 自身在 arc/search 端点的用法),即可恢复 200。
已验证补丁对固定版 2025.03.31 与最新 2026.06.09 签名一致、向前兼容;新增 4 个单元测试。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-17 09:55:54 +08:00
wmsdsb137
ab9ca6a026
fix: address Copilot review suggestions
...
- Remove unused Tuple import
- Validate /pN suffix p >= 1
- Reuse resolve_bilibili_short_url in fetch_subtitles
- Deduplicate short URL resolution
2026-06-16 21:01:27 +08:00
wmsdsb137
2ba409880e
fix(bilibili): 修正分P视频字幕优先链路未传p参数导致取错集
...
问题:B站分P视频(如62集课程),提交?p=36链接时,
字幕优先链路通过x/web-interface/view API拿cid时未传p参数,
默认取第1集cid,导致生成的是第1集的笔记。
同时yt-dlp正确下载了p36音频,但被跳过。
修复:
- url_parser新增extract_bilibili_p_number()提取URL中的p参数
- bilibili_subtitle的_get_cid()接收p参数,从data.pages[p-1]取对应分P的cid
- fetch_subtitles()调用extract_bilibili_p_number()透传p
2026-06-16 20:54:36 +08:00
Jianwu Huang
16a0dd4aec
Merge pull request #406 from fivedang/fix/nginx-default-page
2026-06-15 10:30:43 +08:00
fivedang
39d051cc36
fix: nginx default page hijacks port 80 in Docker image
...
Two issues in Dockerfile.complete caused the nginx welcome page to appear
instead of the BiliNote UI:
1. /etc/nginx/sites-enabled/default had `listen 80 default_server` which
took priority over the custom config in conf.d/
2. The nginx config proxied / to frontend:80, but the Dockerfile sed
replaced it with 127.0.0.1:8080 where no service was running. The
frontend is built as static files in /usr/share/nginx/html/.
Fix:
- Remove /etc/nginx/sites-enabled/default in Dockerfile
- Change location / to serve static files directly instead of proxying
- Remove the frontend proxy sed (no longer needed)
2026-06-15 00:19:54 +08:00
huangjianwu
71c931be55
Merge branch 'master' into develop
2026-06-07 02:09:05 +08:00
huangjianwu and Claude Opus 4.8
f5bfb43619
docs(readme): 群二维码改为关注公众号回复「交流群」获取
...
将 README 社区区块中 5 个会过期的微信群二维码,替换为公众号二维码,
关注后回复「交流群」获取最新群码,避免群码失效。与关于页保持一致。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-07 02:09:03 +08:00
huangjianwu
24b4d4c57c
Merge branch 'release/2.4.0' into develop
2026-06-07 02:05:37 +08:00