删除就技能
PR Test / lint (pull_request) Successful in 2s

This commit is contained in:
2026-03-16 16:55:21 +08:00
parent f98d649b5c
commit ae8f6080c9
25 changed files with 113 additions and 5415 deletions
@@ -0,0 +1,113 @@
---
status: resolved
trigger: "kb-workflow技能添加bilibili视频时,归档的文件名不对,analysis.md文件中的title, duration, author等元数据也不对。"
created: 2026-03-16T00:00:00Z
updated: 2026-03-16T00:10:00Z
resolved: 2026-03-16
---
## Current Focus
hypothesis: 修复已实施并自验证通过
test: 用户需要在实际环境中验证
expecting: 用户确认修复有效
next_action: 等待用户确认
## Symptoms
expected: |
1. analysis.md 的 frontmatter 应该包含正确的 title, duration, author(从 _metadata.json 获取)
2. .m4a 音频文件名应该遵循 `平台_BV号` 的规范(如 bilibili_BV16cNMzpExh.m4a)
actual: |
1. analysis.md 的 frontmatter 显示:
- title: "未命名" (应该是视频标题)
- duration: 0 (应该是 07:16 或秒数)
- author: "未知" (应该是 "阿周的Eureka")
2. .m4a 文件名是 "2-3月宏观经济运行状态复盘与推演 2026年政府工作报告解读 阿周的Eureka.m4a"
(应该是 bilibili_BV16cNMzpExh.m4a)
errors: 无显式错误,kb-workflow 命令执行成功,但输出不正确
reproduction: 对 Bilibili 视频 BV16cNMzpExh 运行 kb-workflow process
started: 首次测试时发现
additional_context: |
_metadata.json 文件中的元数据是正确的:
- title: "2-3月宏观经济运行状态复盘与推演 + 2026年政府工作报告解读 | 【阿周的Eureka】"
- author: "阿周的Eureka"
- duration: "07:16"
- bvid: "BV16cNMzpExh"
但 analysis.md 的 frontmatter 没有使用这些数据。
归档目录位于:kb-workflow/bilibili_BV16cNMzpExh/
## Eliminated
## Evidence
- timestamp: 2026-03-16
checked: kb-workflow/bilibili_BV16cNMzpExh/bilibili_BV16cNMzpExh_metadata.json
found: metadata 文件结构正确,title/author/duration 都在 metadata.metadata 下
implication: 元数据源文件是正确的
- timestamp: 2026-03-16
checked: kb-workflow/bilibili_BV16cNMzpExh/analysis.md
found: frontmatter 显示 title="未命名", author="未知", duration=0
implication: generate_frontmatter() 使用了默认值
- timestamp: 2026-03-16
checked: kb_pipeline/processors/analyze.py:111-116
found: _write_analysis_report(metadata=metadata, ...) 传递原始 metadata
implication: 原始 metadata 是嵌套结构 {metadata: {...}, stats: {...}}
- timestamp: 2026-03-16
checked: kb-deep-analyzer/deep_analyzer.py:436-470
found: generate_frontmatter() 使用 metadata.get('title', '未命名')
implication: 期望扁平结构,但收到嵌套结构,所以取不到值
- timestamp: 2026-03-16
checked: kb-deep-analyzer/deep_analyzer.py:382-414
found: _normalize_metadata() 可以正确扁平化嵌套结构
implication: DeepAnalyzer.analyze() 内部调用了 _normalize_metadata,但 _write_analysis_report() 没有调用
- timestamp: 2026-03-16
checked: kb_pipeline/platforms/bilibili.py:463-483
found: _sanitize_filename() 使用视频标题作为文件名
implication: 文件名不是规范的 bilibili_BV号 格式
- timestamp: 2026-03-16
checked: 单元测试验证
found: _normalize_metadata() 和 _sanitize_filename() 修复后测试通过
implication: 修复逻辑正确
## Resolution
root_cause: |
问题1 - analysis.md 元数据错误:
AnalyzeProcessor._write_analysis_report() 直接将原始嵌套 metadata 传递给 generate_frontmatter(),
而 generate_frontmatter() 期望扁平化的 metadata 结构。
原始结构: {metadata: {title, author, ...}, stats: {...}}
期望结构: {title, author, ...}
问题2 - 音频文件名不规范:
BilibiliAdapter._sanitize_filename() 使用视频标题作为文件名,
而不是规范的 "bilibili_BV号" 格式。
fix: |
问题1: 在 AnalyzeProcessor 中添加 _normalize_metadata() 方法,
在 _write_analysis_report() 中调用它将嵌套 metadata 扁平化
问题2: 修改 _sanitize_filename() 返回标准化的 "bilibili_{bvid}" 格式
verification: |
自验证测试通过:
- _normalize_metadata() 正确处理嵌套结构,返回扁平化的 metadata
- generate_frontmatter() 使用扁平化后的 metadata,生成正确的 frontmatter
- _sanitize_filename() 返回标准化的 "bilibili_BV号" 格式
files_changed:
- kb_pipeline/processors/analyze.py
- kb_pipeline/platforms/bilibili.py
@@ -0,0 +1,116 @@
---
status: resolved
trigger: "kb-workflow 处理 Bilibili 视频 BV16cNMzpExh 时,字幕内容为空,导致生成的笔记没有真实内容"
created: 2026-03-15T10:30:00Z
updated: 2026-03-16T00:30:00Z
---
## Current Focus
hypothesis: 已实现视频下载功能,DownloadProcessor 现在会为 bilibili video 类型下载视频文件
test: 验证导入成功,等待用户端到端测试
expecting: video_path 非空,ASR Whisper 能正常执行语音识别
next_action: 用户验证端到端流程
## Symptoms
expected: 视频字幕应该被提取;如果没有官方字幕,应该通过 Whisper 语音分析生成字幕
actual: 字幕内容为空,生成的笔记显示"【内容】(完整字幕)部分为空白"
errors: 无显式错误,kb-workflow 命令执行成功,但内容为空
reproduction: 对 Bilibili 视频 BV16cNMzpExh 运行 kb-workflow process
started: asyncio 修复后首次测试发现
additional_context: 用户期望即使没有官方字幕,系统也应该执行 Whisper 语音分析生成字幕
## Eliminated
<!-- 暂无 -->
## Evidence
- timestamp: 2026-03-15T10:30:00Z
checked: kb_pipeline/processors/download.py 第 86-99 行
found: DownloadProcessor 对于 video 类型,content_file 被设置为空字符串(第 93 行:`content_file = ""`)
implication: ASR 步骤无法获得视频文件路径
- timestamp: 2026-03-15T10:31:00Z
checked: kb_pipeline/pipeline.py 第 186-192 行
found: ASRInput 从 download 步骤的 `content_file` 获取 video_path
implication: 如果 download 步骤没有提供有效的 content_file,ASR 将收到空路径
- timestamp: 2026-03-15T10:32:00Z
checked: kb_pipeline/processors/asr.py 第 163-290 行
found: _try_official_subtitle 方法只依赖 bvid 调用 B站 API,不依赖 video_path;但 Whisper 降级需要 video_path
implication: 官方字幕可能正常获取(如果有),但 Whisper 降级会失败
- timestamp: 2026-03-15T10:40:00Z
checked: kb_pipeline/processors/asr.py 第 175-177 行和 Python Path("") 行为
found: `_try_official_subtitle` 第 175 行直接使用 `Path(input_data.video_path)`;当 video_path 为空时,Path("") 的 parent 是 "."(当前目录),stem 是空字符串
implication: 字幕文件会写入错误的目录(当前工作目录而不是内容目录)
- timestamp: 2026-03-15T10:42:00Z
checked: kb_pipeline/pipeline.py 第 184-195 行和 ASRInput 构建逻辑
found: ASRInput 使用 `download_result.get("content_file", "")` 作为 video_path,并传入 `content_dir`;但 ASRProcessor 的 _try_official_subtitle 只用 video_path 而忽略 content_dir
implication: content_dir 已经传入 ASRInput 但没有被正确使用
- timestamp: 2026-03-15T12:00:00Z
checked: pipeline.py 第 155-157 行的跳过逻辑
found: 当 ASR 步骤被跳过(已完成)时,results 字典中不包含 "asr" 键,导致 analyze 步骤找不到字幕文件
implication: analyze 步骤的 content_file 为空,无法分析内容
- timestamp: 2026-03-15T12:10:00Z
checked: 已实现修复 - 在跳过步骤时添加用户确认和文件扫描逻辑
found: _populate_skipped_step_results 方法能扫描 content_dir 找到现有的字幕文件({platform}_{content_id}_subtitle.json)
implication: 跳过 ASR 步骤时,results["asr"]["output_files"]["json"] 会被正确填充
- timestamp: 2026-03-15T13:00:00Z
checked: kb_pipeline/processors/download.py 第 93-113 行的内容获取逻辑
found: content_file 只在 content_type in ["article", "answer", "zhuanlan"] 时被设置,video 类型被忽略
implication: **这是根本原因** - video 类型没有下载视频文件,导致 ASR Whisper 无法执行
- timestamp: 2026-03-15T13:05:00Z
checked: kb-bilibili-content/bilibili_content.py 的 download_video 方法
found: 已有完整的 yt-dlp 视频下载实现,支持多种画质选择
implication: 可以复用此逻辑,但只需要下载音频(Whisper 只需要音频)
## Resolution
root_cause: |
**核心问题:DownloadProcessor 对于 video 类型只获取元数据,不下载视频文件**
在 kb_pipeline/processors/download.py 第 93-113 行:
- 只有 content_type in ["article", "answer", "zhuanlan"] 时才调用 adapter.fetch_content()
- 对于 video 类型,content_file 保持为空字符串
结果:
- pipeline.py 第 206 行:`video_path = download_result.get("content_file", "")` 返回空
- ASRProcessor 的 Whisper 需要 video_path 执行语音识别
- 没有 video_path,Whisper 无法运行,只能依赖官方字幕
- 如果视频没有官方字幕,最终笔记内容为空
fix: |
在 DownloadProcessor.process() 中为 video 类型添加视频下载功能:
1. 在 BilibiliAdapter 中添加 download_video() 方法,使用 yt-dlp 下载音频
2. 在 DownloadProcessor.process() 中,对于 bilibili video 类型调用 adapter.download_video()
3. 将下载的文件路径设置到 content_file,供 ASR Whisper 使用
修改的文件:
- kb_pipeline/config.py: 添加 bilibili_cookie 配置项
- kb_pipeline/platforms/bilibili.py: 添加 download_video() 方法
- kb_pipeline/processors/download.py: 调用视频下载逻辑
- kb_pipeline/processors/asr.py: 修复缩进错误
verification: |
✅ 已通过端到端测试验证
- 视频下载成功 (m4a 格式)
- Whisper 语音识别成功生成字幕
- 分析步骤正确读取字幕内容
- 生成的分析报告包含真实视频内容(具体数据如 CPI、PPI、M1 等)
files_changed:
- kb_pipeline/config.py
- kb_pipeline/platforms/bilibili.py
- kb_pipeline/processors/download.py
- kb_pipeline/processors/asr.py
commits:
- eae0817: fix(asr): use content_dir for subtitle output
- 729f465: fix(pipeline): populate results for skipped steps
- 60b0eae: feat(download): add video download capability