diff --git "a/GitPodcast_\351\241\271\347\233\256\345\210\206\346\236\220\346\212\245\345\221\212.md" "b/GitPodcast_\351\241\271\347\233\256\345\210\206\346\236\220\346\212\245\345\221\212.md" new file mode 100644 index 0000000..f9ab736 --- /dev/null +++ "b/GitPodcast_\351\241\271\347\233\256\345\210\206\346\236\220\346\212\245\345\221\212.md" @@ -0,0 +1,581 @@ +# GitPodcast 项目深度分析报告 + +> **项目地址**: https://github.com/BandarLabs/gitpodcast +> **一句话概括**: 将任意 GitHub 仓库转化为一段可收听的播客音频 + 可浏览的幻灯片,帮助快速理解开源项目。 +> **在线体验**: https://gitpodcast.com (也可将任意 GitHub URL 中的 `hub` 替换为 `podcast` 直接访问) + +--- + +## 1. 项目整体架构 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 用户浏览器 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ +│ │ URL 输入框 │ │ 音频播放器 │ │ React Flow 幻灯片视图 │ │ +│ │ (MainCard) │ │ + WebVTT字幕 │ │ (可自动播放/方向键翻页)│ │ +│ └──────┬───────┘ └──────▲───────┘ └──────────▲───────────┘ │ +└─────────┼──────────────────┼─────────────────────┼───────────────┘ + │ │ │ + POST /generate audio/mpeg slide_markdown + │ + X-VTT-Content │ +┌─────────▼────────────────────────────────────────────────────────┐ +│ Frontend (Next.js 15) │ +│ │ +│ ┌────────────┐ ┌──────────────┐ ┌────────────────────────┐ │ +│ │ Clerk Auth │ │Server Actions│ │ fetch-backend.ts │ │ +│ │ (登录认证) │ │ (DB缓存CRUD) │ │ (调用后端API + 缓存) │ │ +│ └────────────┘ └──────┬───────┘ └──────────┬─────────────┘ │ +└──────────────────────────┼─────────────────────┼─────────────────┘ + │ │ + PostgreSQL HTTP POST + (Drizzle ORM) │ +┌──────────────────────────────────────────────▼────────────────────┐ +│ Backend (FastAPI + Docker) │ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ API Routes │ │ +│ │ POST /generate → 生成播客 SSML + 音频 MP3 │ │ +│ │ POST /generate/slide → 生成幻灯片 Markdown │ │ +│ │ POST /generate/cost → 估算本次生成费用 │ │ +│ │ POST /modify → 用户指令修改 Mermaid 图(备用) │ │ +│ └──────────────────────┬──────────────────────────────────────┘ │ +│ │ │ +│ ┌──────────────────────▼──────────────────────────────────────┐ │ +│ │ Service Layer │ │ +│ │ │ │ +│ │ ┌──────────────────┐ ┌──────────────────┐ │ │ +│ │ │ GitHubService │ │ OpenAIService │ │ │ +│ │ │ 获取文件树/README│ │ Azure GPT-4o │ │ │ +│ │ │ 获取关键文件内容 │ │ 生成SSML播客稿 │ │ │ +│ │ └──────────────────┘ │ 选择重要文件 │ │ │ +│ │ └──────────────────┘ │ │ +│ │ ┌──────────────────┐ ┌──────────────────┐ │ │ +│ │ │ ClaudeService │ │ GeminiService │ │ │ +│ │ │ Claude 3.5 Son. │ │ Gemini 2.0 Flash│ │ │ +│ │ │ Token计数/修改图│ │ (可选)替代生成 │ │ │ +│ │ └──────────────────┘ │ SSML │ │ │ +│ │ └──────────────────┘ │ │ +│ │ ┌──────────────────┐ ┌──────────────────┐ │ │ +│ │ │ SpeechService │ │ SlideService │ │ │ +│ │ │ Azure TTS Batch │ │ 调用OpenAI生成 │ │ │ +│ │ │ SSML→MP3音频 │ │ Marp Markdown │ │ │ +│ │ │ SSML→WebVTT字幕 │ │ 幻灯片内容 │ │ │ +│ │ └──────────────────┘ └──────────────────┘ │ │ +│ └──────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌────────────┐ ┌──────────────┐ ┌─────────────────────────┐ │ +│ │ SlowAPI │ │ API Analytics│ │ Clerk Backend Auth │ │ +│ │ 速率限制 │ │ 请求统计 │ │ 验证登录态 │ │ +│ └────────────┘ └──────────────┘ └─────────────────────────┘ │ +└───────────────────────────────────────────────────────────────────┘ + │ + ┌──────────▼──────────┐ + │ PostgreSQL │ + │ ┌────────────────┐ │ + │ │ diagram_cache │ │ + │ │ (图表缓存) │ │ + │ ├────────────────┤ │ + │ │audio_blob_store│ │ + │ │(音频+字幕缓存) │ │ + │ └────────────────┘ │ + └──────────────────────┘ +``` + +--- + +## 2. 核心工作流程(Pipeline) + +### 2.1 端到端流程 + +``` +用户输入 GitHub URL + │ + ▼ + ① 解析 username/repo + │ + ▼ + ② GitHubService: 获取文件树 (git trees API, recursive) + GitHubService: 获取 README 内容 + GitHubService: 获取默认分支名 + │ + ▼ + ③ OpenAIService.get_important_files(): + 用 GPT-4o structured output (Pydantic response_format) + 从文件树中选出 ≤10 个最重要的文件路径 + │ + ▼ + ④ GitHubService: 逐个获取这些重要文件的源码内容 + (每个文件截断到 50,000 字符) + │ + ▼ + ⑤ 组装内容 → 送入 LLM 生成 SSML 播客稿 + ├── short (~5min): 单次调用,内容 = file_tree + readme + 重要文件 + └── long (~10min): 并发两次调用 (ThreadPoolExecutor) + ├── 前半段: file_tree + readme → BEFORE_BREAK prompt + └── 后半段: 重要文件内容 → AFTER_BREAK prompt + 然后拼接两段 SSML,包裹在 标签中 + │ + ▼ + ⑥ SpeechService.text_to_mp3(): + Azure Cognitive Services 批量合成 API + 提交 SSML → 轮询状态 → 下载 ZIP → 提取 WAV/MP3 + (16kHz, 32kbps, mono MP3) + │ + ▼ + ⑦ SpeechService.ssml_to_webvtt(): + 解析 SSML 中的纯文本 → 按语速(WPM)计算时间戳 + 生成 WebVTT 字幕文件(用于前端同步显示) + │ + ▼ + ⑧ 同时 SlideService: 用 OpenAI 生成 Marp Markdown 幻灯片 + 按 `---` 分隔符切分为多张幻灯片 + │ + ▼ + ⑨ 前端接收: + - MP3 音频 → URL.createObjectURL →