Skip to content

feat(bilibili): B站合集分P + HashRouter + 公式渲染 + prompt LaTeX 说明 + ctranslate2 兼容#372

Open
Yurken wants to merge 3 commits into
JefferyHcool:masterfrom
Yurken:master
Open

feat(bilibili): B站合集分P + HashRouter + 公式渲染 + prompt LaTeX 说明 + ctranslate2 兼容#372
Yurken wants to merge 3 commits into
JefferyHcool:masterfrom
Yurken:master

Conversation

@Yurken
Copy link
Copy Markdown

@Yurken Yurken commented May 22, 2026

  • B站下载器支持合集分 P 参数识别,避免总是下载第一集
  • URL 解析器提取分 P 参数防止不同 P 覆盖同一文件
  • 前端改用 HashRouter 适配桌面/扩展场景
  • MarkdownViewer 修复 remarkMath/rehypeKatex 配置(singleDollarTextMath、strict false)
  • prompt 新增 LaTeX 公式格式要求并修复 {aligned} KeyError
  • ctranslate2 版本兼容(>=4.6.0)+ mlx-whisper 导入保护 + .env 加载路径修复

- B站下载器支持合集分 P 参数识别,避免总是下载第一集
- URL 解析器提取分 P 参数防止不同 P 覆盖同一文件
- 前端改用 HashRouter 适配桌面/扩展场景
- MarkdownViewer 修复 remarkMath/rehypeKatex 配置(singleDollarTextMath、strict false)
- prompt 新增 LaTeX 公式格式要求并修复 {aligned} KeyError
- ctranslate2 版本兼容(>=4.6.0)+ mlx-whisper 导入保护 + .env 加载路径修复

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 22, 2026 05:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 聚焦于提升 B 站多分 P/合集下载的正确性,并改善多端运行适配与 Markdown/LaTeX 渲染体验,同时补齐后端在依赖兼容与运行环境加载方面的健壮性。

Changes:

  • 后端:尝试支持 B 站分 P 参数识别(下载侧 + URL 解析侧)、改进 .env 加载路径、增强 mlx-whisper 导入兼容与 ctranslate2 版本约束。
  • 前端:路由切换为 HashRouter,并修复/放宽 KaTeX 渲染配置以减少公式渲染失败。
  • Prompt:补充 LaTeX 输出格式规则并修复 {aligned} 相关模板问题。

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
BillNote_frontend/src/pages/HomePage/components/MarkdownViewer.tsx 调整 remark-math/rehype-katex 插件配置,提升公式渲染容错与兼容性。
BillNote_frontend/src/App.tsx 使用 HashRouter 以适配桌面端/扩展等无后端路由支持场景。
backend/requirements.txt 放宽 ctranslate2 版本约束以提升兼容性(但会影响可复现性)。
backend/main.py 显式从项目根目录加载 .env,支持在 backend/ 子目录运行。
backend/app/utils/url_parser.py 为 B 站 URL 提取逻辑加入 p= 参数(但当前实现会影响 bvid 的语义)。
backend/app/routers/config.py 为 mlx-whisper 状态查询增加导入保护(但异常处理过宽且静默)。
backend/app/gpt/prompt.py 强化 LaTeX 公式输出规范与示例,避免渲染歧义(示例呈现方式仍有冲突点)。
backend/app/downloaders/bilibili_downloader.py yt-dlp 下载配置加入分 P 选择逻辑(但文件命名/缓存一致性仍存在关键问题)。
Comments suppressed due to low confidence (1)

backend/app/downloaders/bilibili_downloader.py:140

  • download_video() 里同样只通过 playlist_items 选集,但 outtmpl 仍是 %(id)s.%(ext)s,不同分 P 可能落到同名 BV...mp4 覆盖;同时函数前面对 extract_video_id() 生成的文件名做存在性判断(其返回值已被本 PR 改为带 _pN),会与 yt-dlp 实际产物文件名不一致,导致缓存失效/重复下载。建议统一“用于缓存/文件名”的 ID 生成逻辑,并让 outtmpl 与该逻辑一致。
        output_path = os.path.join(output_dir, "%(id)s.%(ext)s")

        ydl_opts = {
            'format': 'bv*[ext=mp4]/bestvideo+bestaudio/best',
            'outtmpl': output_path,
            'http_headers': {'Referer': 'https://www.bilibili.com'},
            'quiet': False,
            'merge_output_format': 'mp4',  # 确保合并成 mp4
        }

        # 合集分 P 处理
        p_match = re.search(r'[?&]p=(\d+)', video_url)
        if p_match:
            ydl_opts['playlist_items'] = p_match.group(1)
        else:
            ydl_opts['noplaylist'] = True


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backend/app/utils/url_parser.py Outdated
Comment on lines +22 to +30
match = re.search(r"BV([0-9A-Za-z]+)", url)
return f"BV{match.group(1)}" if match else None
if not match:
return None
bv = f"BV{match.group(1)}"
# 提取分 P 参数(合集),避免不同 P 覆盖同一文件
p_match = re.search(r'[?&]p=(\d+)', url)
if p_match:
return f"{bv}_p{p_match.group(1)}"
return bv
Comment on lines +58 to +80
ydl_opts['playlist_items'] = p_match.group(1)
else:
ydl_opts['noplaylist'] = True

Comment thread backend/app/gpt/prompt.py
Comment on lines +41 to +55
5. 视频中提及的数学公式必须保留,并以 LaTeX 语法形式呈现:
- 行内公式用 `$...$`,$ 与公式内容之间**不能有空格**
- 块级公式用 `$$...$$`,**必须独占一行**,前后各空一行,$$ 与公式内容之间**不能有空格**
- 例如:
```
原问题为:

$$\begin{{aligned}}
\min \quad & f = 3x_1 - 5x_2
\end{{aligned}}$$

转换为:$z = -f$
```
- **禁止**用代码块(如 ` ```math ` 或 ` ``` `)包裹公式。
6. **禁止元叙述**:笔记中不要出现"视频讲了……"、"视频中提到……"、"在本视频中……"等指向视频本身的表述。直接总结内容即可,把信息当作客观事实陈述。
Comment thread backend/app/routers/config.py Outdated
Comment on lines +188 to +190
except Exception:
# mlx-whisper 未安装或导入失败,跳过该分支
pass
Comment thread backend/requirements.txt Outdated
coloredlogs==15.0.1
cssselect2==0.8.0
ctranslate2==4.6.0
ctranslate2>=4.6.0
- url_parser: extract_video_id 恢复返回纯 BV 号,新增 extract_bilibili_task_id
  用于带分 P 的任务签名,避免破坏 B 站 API 调用
- bilibili_downloader: outtmpl 与返回路径加入 p_suffix,防止不同 P 覆盖同名文件
- prompt: 公式示例去掉三引号代码块,避免与"禁止代码块包裹公式"矛盾
- config: mlx-whisper 导入捕获由 except Exception 收紧为 except ImportError
- requirements: ctranslate2 版本约束加 <5 上界

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

backend/app/downloaders/bilibili_downloader.py:204

  • outtmpl uses task_id, but extract_bilibili_task_id() can return an empty string on parse failure, which would generate paths like <dir>/.srt and potentially overwrite/behave unexpectedly. Consider validating task_id (fallback to video_id, or raise a clear error before calling yt-dlp).
            'subtitleslangs': langs,
            'subtitlesformat': 'srt/json3/best',  # 支持多种格式
            'skip_download': True,
            'outtmpl': os.path.join(output_dir, f'{task_id}.%(ext)s'),
            'quiet': True,

Comment on lines +47 to +51
bvid = extract_video_id(url, "bilibili")
if not bvid:
return ""
p_match = re.search(r'[?&]p=(\d+)', url)
if p_match:
Comment on lines +58 to +62
# 合集分 P 处理:识别 URL 中的 p 参数,避免总是下载第一集
p_match = re.search(r'[?&]p=(\d+)', video_url)
p_suffix = f"_p{p_match.group(1)}" if p_match else ""

output_path = os.path.join(output_dir, f"%(id)s{p_suffix}.%(ext)s")
@@ -106,30 +116,37 @@ def download_video(
os.makedirs(output_dir, exist_ok=True)
print("video_url",video_url)
Comment thread backend/app/routers/config.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants