DESIGN.md
本地来源:seo-llm/raw/seo知识库/TXT整理/seo方法论/seo-knowledge-base/DESIGN.md.txt
# SEO Dashboard 设计文档
## 一、项目概述
### 1.1 目标
创建一个内部 SEO 工具,通过 YouTube 视频内容自动生成多语言博客文章,提升网站 SEO 效果。
### 1.2 核心流程
```
关键词输入 → YouTube 搜索 → 选择视频 → 提取脚本 → AI 生成博客 → 多语言翻译 → 发布到目标站点
```
### 1.3 技术约束
- 页面设置为 `noindex`(内部工具,不需要被搜索引擎收录)
- 需要 YouTube Data API v3
- 需要 AI API(用于脚本提取、博客生成、翻译)
---
## 二、开发阶段规划(MVP vs 成熟阶段)
### 2.1 阶段功能对照表
| 功能模块 | MVP 阶段 | 成熟阶段 | 优先级 |
| --------------- | ----------------------- | --------------------- | ------- |
| **视频搜索** | ✅ 基础搜索、筛选 | 批量搜索、智能推荐 | P0 |
| **脚本提取** | ✅ YouTube 字幕 | Whisper AI 转写 | P0 |
| **博客生成** | ✅ 整体生成(不分模块) | 12 模块独立编辑 | P0 → P1 |
| **博客模块** | ✅ 基础 8 模块 | 完整 12 模块 | P0 → P1 |
| **多语言翻译** | ✅ 3 语言 (en/zh/es) | 10+ 语言 | P0 |
| **图片生成** | ❌ 手动上传 | ✅ AI 自动生成 | P2 |
| **竞品分析** | ❌ 无 | ✅ URL 分析、大纲提取 | P2 |
| **模板系统** | ❌ 无 | ✅ 6 种博客模板 | P2 |
| **Prompt 管理** | ✅ 固定 Prompt | 自定义 Prompt 库 | P1 |
| **发布流程** | ✅ MDX 导出 + 手动复制 | API 自动发布 | P1 → P2 |
| **多站点支持** | ✅ siteId 字段预留 | 自动发布到多站点 | P1 |
| **数据分析** | ❌ 无 | ✅ 生成统计、SEO 效果 | P3 |
| **批量处理** | ❌ 无 | ✅ 批量生成、批量翻译 | P2 |
| **定时任务** | ❌ 无 | ✅ 自动抓取、自动发布 | P3 |
### 2.2 MVP 阶段详细需求
#### MVP 核心功能(必须完成)
```
┌─────────────────────────────────────────────────────────────────┐
│ MVP 阶段核心流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 关键词搜索 YouTube 视频 │
│ └── 基础筛选:日期、时长、排序 │
│ │
│ 2. 提取视频脚本 │
│ └── 使用 YouTube 自动字幕 │
│ │
│ 3. AI 生成博客(整体生成,不分模块编辑) │
│ ├── 标题 + Meta Description │
│ ├── 正文内容(含引言、要点、总结) │
│ └── CTA 行动号召 │
│ │
│ 4. 多语言翻译(3 种) │
│ └── en / zh / es │
│ │
│ 5. 导出 MDX 文件 │
│ └── 手动复制到目标项目的 content/blog/ 目录 │
│ │
│ 6. 数据库存储 │
│ └── 保存视频、博客、草稿记录 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
#### MVP 阶段暂不做的功能
| 功能 | 原因 | 后续阶段 |
| ----------------- | -------------------------- | -------- |
| 12 模块独立编辑器 | 增加复杂度,先整体生成够用 | 成熟阶段 |
| AI 图片自动生成 | 手动配图更可控 | 成熟阶段 |
| 竞品 URL 分析 | 锦上添花功能 | 成熟阶段 |
| 复杂模板系统 | 先用固定结构 | 成熟阶段 |
| FAQ Schema 标记 | SEO 优化功能 | 成熟阶段 |
| API 自动发布 | 先用 MDX 导出 | 成熟阶段 |
### 2.3 成熟阶段详细需求
#### 博客模块升级:从 10 模块到 12 模块
基于 SaaS 博客最佳实践,成熟阶段升级为 **12 个模块**:
| 序号 | 模块名称 | 英文名 | MVP | 成熟 | SEO 价值 |
| ---- | -------- | ------------------- | --- | ---- | ---------- |
| 1 | 标题 | Title | ✅ | ✅ | ⭐⭐⭐⭐⭐ |
| 2 | 元描述 | Meta Description | ✅ | ✅ | ⭐⭐⭐⭐⭐ |
| 3 | 特色图片 | Featured Image | ❌ | ✅ | ⭐⭐⭐⭐ |
| 4 | 开头引言 | Introduction | ✅ | ✅ | ⭐⭐⭐⭐ |
| 5 | 目录 | Table of Contents | ❌ | ✅ | ⭐⭐⭐ |
| 6 | 核心要点 | Key Takeaways | ❌ | ✅ | ⭐⭐⭐⭐⭐ |
| 7 | 主要内容 | Main Content | ✅ | ✅ | ⭐⭐⭐⭐⭐ |
| 8 | 案例示例 | Examples/Case Study | ✅ | ✅ | ⭐⭐⭐⭐ |
| 9 | FAQ 问答 | FAQ Section | ❌ | ✅ | ⭐⭐⭐⭐⭐ |
| 10 | 总结结论 | Conclusion | ✅ | ✅ | ⭐⭐⭐⭐ |
| 11 | 相关文章 | Related Articles | ❌ | ✅ | ⭐⭐⭐ |
| 12 | 行动号召 | Call to Action | ✅ | ✅ | ⭐⭐⭐⭐⭐ |
#### 新增模块详解
##### 模块 3: 特色图片 (Featured Image)
```
功能:为博客生成/选择封面图片
MVP:手动上传
成熟:AI 自动生成(使用 KIE API)
输出:
- 主图 URL
- Alt 文本
- 图片尺寸(1200x630 推荐)
```
##### 模块 5: 目录 (Table of Contents)
```
功能:自动生成文章目录,提升用户体验
MVP:无
成熟:根据 H2/H3 标题自动生成
输出:
- 带锚点链接的目录列表
- 支持折叠/展开
```
##### 模块 6: 核心要点 (Key Takeaways)
```
功能:文章开头的 bullet points 摘要
重要性:Google AI Overview 和 Featured Snippets 优先抓取
MVP:无
成熟:AI 自动提取 3-5 个要点
输出示例:
┌─────────────────────────────────────┐
│ 📌 Key Takeaways │
│ • AI upscaling improves quality 4x │
│ • Best for photos under 2MB │
│ • Free tools available in 2026 │
└─────────────────────────────────────┘
```
##### 模块 9: FAQ 问答 (FAQ Section)
```
功能:结构化问答,可添加 Schema 标记
SEO 价值:极高(FAQ Schema 可获得搜索结果富文本展示)
MVP:无
成熟:AI 生成 3-5 个常见问题
输出格式:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [...]
}
</script>
```
##### 模块 11: 相关文章 (Related Articles)
```
功能:内部链接推荐,提升站内 SEO
MVP:无
成熟:基于标签/关键词自动推荐
输出:
- 2-4 篇相关文章链接
- 包含标题和简短描述
```
---
## 三、页面路由设计
| 路由 | 页面名称 | 功能描述 | MVP | 成熟 |
| ----------------- | ----------- | ---------------------------------- | --------- | ------------- |
| `/seo` | Dashboard | 主控制台,显示统计和快捷入口 | ✅ | ✅ |
| `/seo/search` | 视频搜索 | YouTube 关键词搜索、筛选、结果列表 | ✅ | ✅ |
| `/seo/video/[id]` | 视频详情 | 视频信息、脚本提取、开始生成博客 | ✅ | ✅ |
| `/seo/blog/new` | 新建博客 | 博客生成器 | ✅ | 12 模块编辑器 |
| `/seo/blog/[id]` | 博客编辑 | 编辑已生成的博客 | ✅ | ✅ |
| `/seo/drafts` | 草稿箱 | 未发布的博客草稿 | ✅ | ✅ |
| `/seo/blogs` | 已发布文章 | 所有已发布的博客(按日期索引) | ✅ | ✅ |
| `/seo/images` | 图片管理 | 文章配图管理 | ❌ | ✅ |
| `/seo/templates` | 模板管理 | 博客模板、URL 参考 | ❌ | ✅ |
| `/seo/prompts` | Prompt 管理 | 12 个模块的 Prompt 模板 | ✅ 简化版 | ✅ |
| `/seo/settings` | 设置 | API 配置、语言设置、站点管理 | ✅ | ✅ |
### 3.1 文章状态流转
```
┌──────────────────────────────────────────────────────────────┐
│ 文章生命周期 │
├──────────────────────────────────────────────────────────────┤
│ │
│ [新建] ─────▶ [草稿 draft] ─────▶ [已发布 published] │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ /seo/drafts /seo/blogs │
│ │ │ │
│ └───── [编辑] ◀────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
```
### 3.2 文章索引方式(按日期分组)
```
/seo/blogs
├── 2026年1月 (15篇)
│ ├── 2026-01-21: How to Use AI Image Upscaler
│ ├── 2026-01-20: Top 10 AI Video Tools
│ └── ...
├── 2025年12月 (23篇)
│ └── ...
└── 更早...
```
---
## 四、数据库设计
### 4.1 完整表结构(支持 MVP + 成熟阶段)
```typescript
// src/db/schema.ts 中新增
// SEO 视频记录
export const seoVideos = pgTable('seo_videos', {
id: uuid('id').primaryKey().defaultRandom(),
siteId: varchar('site_id', { length: 50 }), // 多站点支持
youtubeId: varchar('youtube_id', { length: 32 }).notNull(),
title: varchar('title', { length: 500 }).notNull(),
channelName: varchar('channel_name', { length: 255 }),
channelId: varchar('channel_id', { length: 64 }),
publishedAt: timestamp('published_at'),
viewCount: bigint('view_count', { mode: 'number' }),
likeCount: integer('like_count'),
commentCount: integer('comment_count'),
duration: varchar('duration', { length: 32 }),
description: text('description'),
thumbnailUrl: varchar('thumbnail_url', { length: 500 }),
script: text('script'),
scriptLanguage: varchar('script_language', { length: 10 }),
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at').defaultNow().notNull(),
});
// SEO 博客(完整 12 模块支持)
export const seoBlogs = pgTable('seo_blogs', {
id: uuid('id').primaryKey().defaultRandom(),
siteId: varchar('site_id', { length: 50 }), // 多站点支持
videoId: uuid('video_id').references(() => seoVideos.id),
// 基础信息
status: varchar('status', { length: 20 }).default('draft'), // draft | published | archived
language: varchar('language', { length: 10 }).notNull(),
// 模块 1: 标题
title: varchar('title', { length: 500 }),
slug: varchar('slug', { length: 200 }),
// 模块 2: 元描述
metaDescription: varchar('meta_description', { length: 200 }),
// 模块 3: 特色图片(成熟阶段)
featuredImageUrl: varchar('featured_image_url', { length: 500 }),
featuredImageAlt: varchar('featured_image_alt', { length: 200 }),
// 模块 4-8, 10: 正文内容(JSON 存储各模块)
content: jsonb('content'), // { introduction, mainContent, examples, conclusion }
// 模块 5: 目录(成熟阶段,自动生成不存储)
// 模块 6: 核心要点(成熟阶段)
keyTakeaways: jsonb('key_takeaways'), // ["point1", "point2", ...]
// 模块 9: FAQ(成熟阶段)
faqContent: jsonb('faq_content'), // [{question, answer}, ...]
// 模块 11: 相关文章(成熟阶段,动态查询不存储)
// 模块 12: CTA
ctaContent: text('cta_content'),
// SEO 元数据
keyword: varchar('keyword', { length: 200 }),
tags: jsonb('tags'), // ["ai", "video", "tutorial"]
wordCount: integer('word_count'),
readingTime: integer('reading_time'), // 分钟数
// 作者信息(成熟阶段)
authorId: varchar('author_id', { length: 100 }),
authorName: varchar('author_name', { length: 200 }),
// 发布信息
templateId: uuid('template_id'),
publishedUrl: varchar('published_url', { length: 500 }),
publishedAt: timestamp('published_at'),
// 统计和标记(成熟阶段)
isFeatured: boolean('is_featured').default(false),
isPinned: boolean('is_pinned').default(false),
viewCount: integer('view_count').default(0),
// 内部链接(成熟阶段)
internalLinks: jsonb('internal_links'), // [{url, anchorText}, ...]
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at').defaultNow().notNull(),
});
// SEO 图片
export const seoImages = pgTable('seo_images', {
id: uuid('id').primaryKey().defaultRandom(),
siteId: varchar('site_id', { length: 50 }),
blogId: uuid('blog_id').references(() => seoBlogs.id),
moduleIndex: integer('module_index'),
prompt: text('prompt'),
model: varchar('model', { length: 100 }),
imageUrl: varchar('image_url', { length: 500 }),
altText: varchar('alt_text', { length: 200 }),
width: integer('width'),
height: integer('height'),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
// SEO Prompt 模板
export const seoPrompts = pgTable('seo_prompts', {
id: uuid('id').primaryKey().defaultRandom(),
siteId: varchar('site_id', { length: 50 }),
module: varchar('module', { length: 50 }).notNull(), // 12 模块之一
name: varchar('name', { length: 200 }).notNull(),
content: text('content').notNull(),
variables: jsonb('variables'),
isDefault: boolean('is_default').default(false),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
// SEO 博客模板(成熟阶段)
export const seoTemplates = pgTable('seo_templates', {
id: uuid('id').primaryKey().defaultRandom(),
siteId: varchar('site_id', { length: 50 }),
name: varchar('name', { length: 200 }).notNull(),
type: varchar('type', { length: 50 }).notNull(), // tutorial/list/comparison/review/news/faq
structure: jsonb('structure'),
referenceUrls: jsonb('reference_urls'),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
// 站点配置(多站点支持)
export const seoSites = pgTable('seo_sites', {
id: varchar('id', { length: 50 }).primaryKey(), // 如 "seedvr", "another-site"
name: varchar('name', { length: 200 }).notNull(),
domain: varchar('domain', { length: 200 }).notNull(),
blogPath: varchar('blog_path', { length: 200 }).default('/blog'),
languages: jsonb('languages'), // ["en", "zh", "es"]
defaultLanguage: varchar('default_language', { length: 10 }).default('en'),
mdxOutputPath: varchar('mdx_output_path', { length: 500 }), // 导出路径
isActive: boolean('is_active').default(true),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
```
### 4.2 MVP 阶段使用的字段
MVP 阶段只使用以下字段,其他字段可暂时为空:
| 表 | 必用字段 | 可选字段 |
| ---------- | -------------------------------------------------------- | ----------------------------------- |
| seoVideos | id, youtubeId, title, script, createdAt | 其他全部 |
| seoBlogs | id, status, language, title, content, keyword, createdAt | featuredImage, faq, keyTakeaways 等 |
| seoPrompts | id, module, name, content | variables, siteId |
---
## 五、发布流程设计
### 5.1 MVP 阶段:MDX 导出 + 手动复制
```
┌─────────────────────────────────────────────────────────────────┐
│ MVP 发布流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ SEO Dashboard 目标站点 │
│ ───────────── ───────── │
│ │
│ 1. 博客编辑完成 │
│ │ │
│ ▼ │
│ 2. 点击"导出 MDX" │
│ │ │
│ ▼ │
│ 3. 下载 MDX 文件 │
│ ├── how-to-upscale-images.en.mdx │
│ ├── how-to-upscale-images.zh.mdx │
│ └── how-to-upscale-images.es.mdx │
│ │ │
│ ▼ │
│ 4. 手动复制到目标项目 ──────▶ content/blog/ │
│ │ │
│ ▼ │
│ 5. git commit & push │
│ │ │
│ ▼ │
│ 6. 站点自动部署 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 5.2 MDX 文件格式
```mdx
---
title: 'How to Upscale Images with AI in 2026'
description: 'Learn the best techniques for AI image upscaling using the latest tools and technologies.'
date: '2026-01-21'
author: 'SEO Dashboard'
tags: ['ai', 'upscaler', 'tutorial']
featuredImage: '/images/blog/ai-upscaler-guide.jpg'
readingTime: 8
---
## Key Takeaways
- AI upscaling can improve image quality by up to 4x
- Best results with photos under 2MB
- Free tools available in 2026
## Introduction
{introductionContent}
## How AI Upscaling Works
{mainContent}
## Real-World Examples
{examplesContent}
## FAQ
### Q: What is AI image upscaling?
A: AI image upscaling uses machine learning...
### Q: Is it free?
A: Yes, there are free options available...
## Conclusion
{conclusionContent}
## Take Action
{ctaContent}
```
### 5.3 成熟阶段:API 自动发布
```
┌─────────────────────────────────────────────────────────────────┐
│ 成熟阶段发布流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 选择目标站点 │
│ ├── seedvr.net │
│ ├── another-site.com │
│ └── third-site.org │
│ │ │
│ ▼ │
│ 2. 点击"发布" │
│ │ │
│ ▼ │
│ 3. 系统自动: │
│ ├── 生成 MDX 文件 │
│ ├── 上传图片到 R2 │
│ ├── 通过 GitHub API 创建 commit │
│ └── 触发站点部署 │
│ │ │
│ ▼ │
│ 4. 返回发布 URL │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 六、API 设计
### 6.1 YouTube 相关
```
GET /api/seo/youtube/search - 搜索视频
GET /api/seo/youtube/video/:id - 获取视频详情
POST /api/seo/youtube/script - 提取视频脚本
```
### 6.2 博客相关
```
GET /api/seo/blogs - 博客列表
POST /api/seo/blogs - 创建博客
GET /api/seo/blogs/:id - 获取博客详情
PUT /api/seo/blogs/:id - 更新博客
DELETE /api/seo/blogs/:id - 删除博客
POST /api/seo/blogs/:id/generate - AI 生成博客内容
POST /api/seo/blogs/:id/translate - 翻译博客
POST /api/seo/blogs/:id/export-mdx - 导出 MDX 文件
POST /api/seo/blogs/:id/publish - 发布博客(成熟阶段)
```
### 6.3 图片相关(成熟阶段)
```
GET /api/seo/images - 图片列表
POST /api/seo/images/generate - AI 生成图片
DELETE /api/seo/images/:id - 删除图片
```
### 6.4 模板相关(成熟阶段)
```
GET /api/seo/templates - 模板列表
POST /api/seo/templates - 创建模板
PUT /api/seo/templates/:id - 更新模板
DELETE /api/seo/templates/:id - 删除模板
POST /api/seo/templates/analyze-url - 分析参考 URL
```
### 6.5 Prompt 相关
```
GET /api/seo/prompts - Prompt 列表
PUT /api/seo/prompts/:module - 更新模块 Prompt
POST /api/seo/prompts/test - 测试 Prompt
```
### 6.6 站点相关(多站点支持)
```
GET /api/seo/sites - 站点列表
POST /api/seo/sites - 添加站点
PUT /api/seo/sites/:id - 更新站点配置
DELETE /api/seo/sites/:id - 删除站点
```
---
## 七、完整 API 梳理
### 7.1 当前项目已有的 API Key(可复用)
| API | 环境变量 | 用途 | 状态 |
| -------------- | --------------------- | ----------------------------------------------- | --------- |
| **KIE API** | `KIE_API_KEY` | 生成图片(Nano Banana, Seedream, Grok Image等) | ✅ 已配置 |
| **OpenRouter** | `OPENROUTER_API_KEY` | LLM 大模型(GPT-4, Claude等) | ✅ 已配置 |
| **FAL AI** | `FAL_API_KEY` | AI 图片/视频生成 | ✅ 已配置 |
| **Replicate** | `REPLICATE_API_TOKEN` | 各种AI模型 | ✅ 已配置 |
| **WaveSpeed** | `WAVESPEED_API_KEY` | 视频生成 | ✅ 已配置 |
| **Resend** | `RESEND_API_KEY` | 邮件发送 | ✅ 已配置 |
| **R2 Storage** | `STORAGE_*` | 图片/文件存储 | ✅ 已配置 |
### 7.2 需要新增的 API Key
| API | 环境变量 | 用途 | 获取地址 |
| ----------------------- | ----------------- | ------------------ | --------------------------------------------------------- |
| **YouTube Data API v3** | `YOUTUBE_API_KEY` | 视频搜索和信息获取 | [Google Cloud Console](https://console.cloud.google.com/) |
### 7.3 SEO Dashboard 需要用到的所有 API
```
┌─────────────────────────────────────────────────────────────────┐
│ SEO Dashboard API 架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ YouTube Data API v3 ──────────────────────┐ │
│ └── 搜索视频、获取视频详情、获取字幕 │ │
│ ▼ │
│ OpenRouter LLM API ─────────────────────────────────────────── │
│ ├── 脚本内容理解和分析 │
│ ├── 博客内容生成(12个模块) │
│ ├── 多语言翻译 │
│ ├── Key Takeaways 提取 │
│ ├── FAQ 生成 │
│ └── URL 竞品分析 │
│ │ │
│ KIE API (图片生成) ─────────────────────────────────────────── │
│ ├── Nano Banana Pro - 文章配图生成 │
│ ├── Seedream - 风格化配图 │
│ └── Grok Image - 高质量图片 │
│ │ │
│ R2 Storage ─────────────────────────────────────────────────── │
│ └── 存储生成的图片和博客资源 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 八、图片生成方案(文章配图)
### 8.1 方案概述
使用当前项目已有的 KIE API 为博客文章自动生成配图,无需额外配置。
### 8.2 支持的图片生成模型
| 模型 | API 路由 | 特点 | 推荐用途 |
| ------------------- | ----------------------------------- | -------------- | ------------ |
| **Nano Banana Pro** | `/api/kie-nano-banana-pro/generate` | 快速、风格多样 | 通用文章配图 |
| **Seedream** | `/api/kie/seedream/generate` | 梦幻风格 | 艺术类文章 |
| **Grok Image** | `/api/kie/grok/generate` | 高质量、逼真 | 产品展示 |
| **GPT-4o Image** | `/api/kie/gpt4o-image/generate` | 理解力强 | 复杂场景 |
| **Qwen Image** | `/api/kie/qwen/generate` | 中文理解好 | 中文内容配图 |
### 8.3 图片生成流程(成熟阶段)
```
博客模块内容 ─────────────────────────────────────────────────────┐
│ │
▼ │
LLM 生成图片描述 Prompt ──────────────────────────────────────────┤
│ │
▼ │
选择图片生成模型 ─────────────────────────────────────────────────┤
│ │
▼ │
调用 KIE API 生成图片 ─────────────────────────────────────────── │
│ │
▼ │
上传到 R2 Storage ────────────────────────────────────────────── │
│ │
▼ │
返回图片 URL 插入博客 ─────────────────────────────────────────── │
```
---
## 九、LLM 大模型方案
### 9.1 使用 OpenRouter API
| 模型 | 模型 ID | 特点 | 推荐用途 |
| --------------------- | ----------------------------- | ------------ | ------------------ |
| **Claude 3.5 Sonnet** | `anthropic/claude-3.5-sonnet` | 长文本、创作 | 博客写作、FAQ 生成 |
| **GPT-4 Turbo** | `openai/gpt-4-turbo` | 最强综合能力 | 复杂内容生成 |
| **GPT-3.5 Turbo** | `openai/gpt-3.5-turbo` | 快速、便宜 | 简单任务、翻译 |
| **DeepSeek** | `deepseek/deepseek-chat` | 性价比高 | 中文内容 |
### 9.2 API 调用示例
```typescript
// src/lib/seo/llm.ts
import OpenAI from 'openai';
const openrouter = new OpenAI({
apiKey: process.env.OPENROUTER_API_KEY,
baseURL: 'https://openrouter.ai/api/v1',
});
// 博客内容生成
export async function generateBlogModule(
script: string,
module: string,
prompt: string,
model: string = 'anthropic/claude-3.5-sonnet'
) {
const response = await openrouter.chat.completions.create({
model,
messages: [
{ role: 'system', content: prompt },
{ role: 'user', content: script },
],
stream: true,
});
return response;
}
// Key Takeaways 提取
export async function generateKeyTakeaways(content: string) {
// 提取 3-5 个核心要点
}
// FAQ 生成
export async function generateFAQ(content: string, keyword: string) {
// 生成 3-5 个常见问题
}
// 多语言翻译
export async function translateContent(
content: string,
targetLang: string,
model: string = 'openai/gpt-3.5-turbo'
) {
// 使用便宜的模型做翻译
}
```
---
## 十、多语言处理方案
### 10.1 当前项目多语言配置
项目已支持 **3 种语言**:
- `en` - English
- `zh` - 中文
- `es` - Español
### 10.2 SEO Dashboard 多语言策略
| 部分 | 多语言策略 | 原因 |
| ---------------- | ------------- | --------------------- |
| **Dashboard UI** | 仅英文 | 内部工具,简化开发 |
| **博客内容** | 支持 3 种语言 | 与项目一致 |
| **Prompt 模板** | 仅英文 | Prompt 本身不需要翻译 |
### 10.3 博客多语言生成流程
```
原始视频脚本(任意语言)
│
▼
LLM 理解内容
│
▼
生成英文博客(主语言)
│
├───────────────────────────────────────────┐
▼ ▼
翻译成中文 翻译成西班牙语
│ │
▼ ▼
存储 language='zh' 存储 language='es'
```
---
## 十一、界面布局
### 11.1 整体布局
```
┌─────────────────────────────────────────────────────────────┐
│ Logo SEO Dashboard [User] [设置] │
├─────────┬───────────────────────────────────────────────────┤
│ │ │
│ 侧边栏 │ 主内容区 │
│ │ │
│ Dashboard│ │
│ 视频搜索 │ │
│ 草稿箱 │ │
│ 已发布 │ │
│ 图片管理 │ │
│ 模板管理 │ │
│ Prompt │ │
│ 设置 │ │
│ │ │
└─────────┴───────────────────────────────────────────────────┘
```
### 11.2 博客编辑器布局(成熟阶段 12 模块)
```
┌─────────────────────────────────────────────────────────────┐
│ 博客编辑器 [预览] [保存] [翻译] [发布] │
├─────────────────────────────────────────────────────────────┤
│ 源视频: [视频标题] 关键词: [________] │
├──────────────────────┬──────────────────────────────────────┤
│ 模块列表 │ 编辑区 │
│ ───────────── │ ───────────────────────────────── │
│ ✅ 1. 标题 │ ## 模块: 标题 │
│ ✅ 2. 元描述 │ │
│ ✅ 3. 特色图片 │ Prompt: [选择模板 ▼] [编辑] │
│ ✅ 4. 开头引言 │ │
│ ⬜ 5. 目录(自动) │ ┌────────────────────────────┐ │
│ ✅ 6. 核心要点 │ │ │ │
│ ✅ 7. 主要内容 │ │ 内容编辑区 │ │
│ ✅ 8. 案例示例 │ │ │ │
│ ✅ 9. FAQ │ │ │ │
│ ✅ 10. 总结结论 │ └────────────────────────────┘ │
│ ⬜ 11. 相关文章(自动)│ │
│ ✅ 12. 行动号召 │ 字数: 150 [🤖生成] [🔄重新生成] │
│ │ │
│ [全部生成] │ │
└──────────────────────┴──────────────────────────────────────┘
```
---
## 十二、技术实现要点
### 12.1 noindex 设置
```tsx
// src/app/(seo)/layout.tsx
export const metadata: Metadata = {
robots: {
index: false,
follow: false,
},
};
```
### 12.2 YouTube API 集成
- 使用 YouTube Data API v3
- 需要配置 `YOUTUBE_API_KEY` 环境变量
- 每日配额限制:10,000 单位
### 12.3 脚本提取方案
1. **YouTube 字幕 API** - 优先使用(MVP)
2. **youtube-transcript 库** - 备选方案
3. **Whisper API** - 无字幕时使用(成熟阶段)
### 12.4 AI 生成方案
- 使用 OpenRouter (Claude 3.5 Sonnet)
- 流式输出提升体验
- 重试机制处理失败
---
## 十三、文件结构
```
src/app/(seo)/
├── layout.tsx # SEO 布局(noindex)
├── seo/
│ ├── page.tsx # Dashboard
│ ├── search/
│ │ └── page.tsx # 视频搜索
│ ├── video/
│ │ └── [id]/
│ │ └── page.tsx # 视频详情
│ ├── blog/
│ │ ├── new/
│ │ │ └── page.tsx # 新建博客
│ │ └── [id]/
│ │ └── page.tsx # 编辑博客
│ ├── drafts/
│ │ └── page.tsx # 草稿箱
│ ├── blogs/
│ │ └── page.tsx # 已发布文章(按日期索引)
│ ├── images/
│ │ ├── page.tsx # 图片管理(成熟阶段)
│ │ └── [id]/
│ │ └── page.tsx # 图片详情
│ ├── templates/
│ │ └── page.tsx # 模板管理(成熟阶段)
│ ├── prompts/
│ │ └── page.tsx # Prompt 管理
│ └── settings/
│ └── page.tsx # 设置
src/components/seo/
├── video-search-form.tsx # 搜索表单
├── video-list.tsx # 视频列表
├── video-card.tsx # 视频卡片
├── script-viewer.tsx # 脚本查看器
├── blog-editor.tsx # 博客编辑器
├── module-editor.tsx # 模块编辑器
├── prompt-editor.tsx # Prompt 编辑器
├── language-selector.tsx # 语言选择器
├── template-picker.tsx # 模板选择器
├── mdx-exporter.tsx # MDX 导出器
├── key-takeaways-editor.tsx # 核心要点编辑器(成熟阶段)
├── faq-editor.tsx # FAQ 编辑器(成熟阶段)
└── image-generator.tsx # 图片生成器(成熟阶段)
src/actions/seo/
├── youtube.ts # YouTube API 操作
├── blog.ts # 博客 CRUD
├── generate.ts # AI 生成
├── translate.ts # 翻译
├── export.ts # MDX 导出
├── template.ts # 模板操作(成熟阶段)
└── image.ts # 图片生成(成熟阶段)
src/lib/seo/
├── llm.ts # LLM 调用封装
├── youtube.ts # YouTube API 封装
├── mdx.ts # MDX 生成
└── schema.ts # FAQ Schema 生成(成熟阶段)
```
---
## 十四、开发优先级总结
### MVP 阶段(先做这些)
| 优先级 | 功能 | 时间估计 |
| ------ | ------------------------ | -------- |
| P0 | 视频搜索页面 | - |
| P0 | 视频详情 + 脚本提取 | - |
| P0 | 基础博客生成(整体生成) | - |
| P0 | 3 语言翻译 (en/zh/es) | - |
| P0 | 数据库存储 | - |
| P0 | MDX 导出功能 | - |
| P0 | 草稿箱 + 已发布列表 | - |
### 成熟阶段(后续迭代)
| 优先级 | 功能 | 依赖 |
| ------ | ----------------- | -------- |
| P1 | 12 模块独立编辑器 | MVP 完成 |
| P1 | Prompt 自定义管理 | MVP 完成 |
| P1 | 多站点支持 | MVP 完成 |
| P2 | AI 图片自动生成 | P1 完成 |
| P2 | 竞品 URL 分析 | P1 完成 |
| P2 | 模板系统 | P1 完成 |
| P2 | FAQ Schema 标记 | P1 完成 |
| P2 | 批量处理 | P1 完成 |
| P3 | API 自动发布 | P2 完成 |
| P3 | 数据分析统计 | P2 完成 |
| P3 | 定时任务 | P2 完成 |
---
## 十五、技术选型总结
| 需求 | 方案 | 阶段 | 备注 |
| ------------ | --------------------------- | ---- | ---------------- |
| YouTube 搜索 | YouTube Data API v3 | MVP | 需要新增 API Key |
| 内容生成 | OpenRouter API (Claude 3.5) | MVP | 已有 |
| 图片生成 | KIE API | 成熟 | 已有 |
| 翻译 | OpenRouter (GPT-3.5) | MVP | 便宜够用 |
| 存储 | PostgreSQL + R2 | MVP | 已有 |
| 多语言 | 3 种 (en/zh/es) | MVP | 与项目一致 |
| 发布 | MDX 导出 | MVP | 手动复制 |
| 发布 | GitHub API | 成熟 | 自动发布 |
---
## 十六、实现进度追踪
### 16.1 已完成的页面
| 页面 | 路由 | 状态 | 说明 |
| ----------- | ---------------- | ----------- | ------------------------ |
| Dashboard | `/seo` | ✅ 已完成 | 主控制台,统计和快捷入口 |
| 视频搜索 | `/seo/search` | ✅ 已完成 | YouTube 关键词搜索 |
| 草稿箱 | `/seo/drafts` | ✅ 占位页面 | 待实现功能 |
| 已发布 | `/seo/blogs` | ✅ 占位页面 | 待实现功能 |
| 图片管理 | `/seo/images` | ✅ 占位页面 | 成熟阶段功能 |
| 模板管理 | `/seo/templates` | ✅ 占位页面 | 成熟阶段功能 |
| Prompt 管理 | `/seo/prompts` | ✅ 占位页面 | 待实现功能 |
| 设置 | `/seo/settings` | ✅ 占位页面 | 待实现功能 |
### 16.2 待实现的核心功能
| 功能 | API 端点 | 优先级 | 说明 |
| ------------ | --------------------------- | ------ | --------------- |
| YouTube 搜索 | `/api/seo/youtube/search` | P0 | 关键词搜索视频 |
| 脚本提取 | `/api/seo/youtube/script` | P0 | 提取视频字幕 |
| 博客生成 | `/api/seo/blogs/generate` | P0 | AI 生成博客内容 |
| 多语言翻译 | `/api/seo/blogs/translate` | P0 | 翻译到 zh/es |
| MDX 导出 | `/api/seo/blogs/export-mdx` | P0 | 导出文件 |
---
## 十七、三步工作流程详解
### 17.1 完整流程
```
┌─────────────────────────────────────────────────────────────────┐
│ SEO Dashboard 三步流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 第一步:关键词 → YouTube 视频 URL │
│ ───────────────────────────────────────────────────────────── │
│ • 输入关键词(如 "ai image upscaler") │
│ • 调用 YouTube Data API v3 搜索 │
│ • 返回视频列表(标题、URL、时长、观看数等) │
│ • 支持筛选:日期、时长、排序方式 │
│ • 结果存储为 JSON 文件(不用数据库) │
│ │
│ 第二步:批量提取视频脚本 │
│ ───────────────────────────────────────────────────────────── │
│ • 从 URL 列表批量提取字幕/脚本 │
│ • 使用 youtube-transcript-api 或 yt-dlp │
│ • 本地可直接循环处理 │
│ • Vercel 需要任务队列(Inngest/Cron) │
│ • 脚本存储为 JSON 文件 │
│ │
│ 第三步:AI 生成博客文章 │
│ ───────────────────────────────────────────────────────────── │
│ • 选择脚本 → 调用 OpenRouter API │
│ • 使用 Claude 3.5 Sonnet 生成博客 │
│ • 按模板结构生成内容 │
│ • 使用 GPT-3.5 Turbo 翻译到其他语言 │
│ • 导出 MDX 文件到目标站点 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 17.2 存储方案(无数据库)
```
data/seo/
├── searches/ # 搜索结果
│ └── {keyword}-{date}.json
├── videos/ # 视频信息
│ └── {video_id}.json
├── scripts/ # 提取的脚本
│ └── {video_id}.json
├── drafts/ # 博客草稿
│ └── {slug}.json
└── published/ # 已发布博客
└── {slug}/
├── en.mdx
├── zh.mdx
└── es.mdx
```
---
## 十八、脚本提取方案对比
### 18.1 方案对比表
| 方案 | 类型 | 优点 | 缺点 | 推荐场景 |
| -------------------------- | --------- | -------------------------- | --------------------- | --------------- |
| **youtube-transcript-api** | Python 库 | 最稳定、最流行、专门做字幕 | 需要 Python 环境 | ✅ 本地开发首选 |
| **yt-dlp** | CLI 工具 | 最强大、支持字幕+音频+视频 | 需要安装额外工具 | 备选方案 |
| **YouTube Captions API** | 官方 API | 官方支持 | 需要 OAuth 认证,复杂 | 生产环境 |
### 18.2 youtube-transcript-api 使用示例
```python
# scripts/extract_transcript.py
from youtube_transcript_api import YouTubeTranscriptApi
def get_transcript(video_id):
"""提取视频字幕"""
try:
# 尝试获取中文字幕,失败则获取英文
transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
# 优先获取手动字幕
try:
transcript = transcript_list.find_manually_created_transcript(['zh', 'en'])
except:
# 回退到自动生成字幕
transcript = transcript_list.find_generated_transcript(['zh', 'en'])
# 合并所有文本
full_text = ' '.join([t['text'] for t in transcript.fetch()])
return full_text
except Exception as e:
return f"Error: {str(e)}"
```
### 18.3 yt-dlp 使用示例
```bash
# 提取字幕(不下载视频)
yt-dlp --write-sub --sub-lang en --skip-download "https://youtube.com/watch?v=xxx"
# 仅列出可用字幕
yt-dlp --list-subs "https://youtube.com/watch?v=xxx"
```
---
## 十九、本地开发 vs Vercel 部署
### 19.1 关键差异
| 特性 | 本地开发 | Vercel 部署 |
| --------------- | ------------ | ----------------------------- |
| **超时限制** | 无限制 | 10-60 秒(Serverless) |
| **批量处理** | 简单循环即可 | 需要任务队列(Inngest) |
| **文件存储** | 本地文件系统 | 需要云存储(R2) |
| **Python 脚本** | 直接运行 | 需要 Edge Function 或外部服务 |
| **开发体验** | 更自由 | 有限制但更稳定 |
### 19.2 开发策略
```
┌─────────────────────────────────────────────────────────────────┐
│ 开发部署策略 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 阶段一:本地开发(当前阶段) │
│ ───────────────────────────────────────────────────────────── │
│ • 所有功能先在本地实现 │
│ • 使用本地文件存储 JSON │
│ • Python 脚本直接调用 │
│ • 批量处理用简单循环 │
│ • 无超时限制 │
│ │
│ 阶段二:Vercel 部署(后续) │
│ ───────────────────────────────────────────────────────────── │
│ • 单个操作可直接迁移 │
│ • 批量操作需要改用 Inngest 任务队列 │
│ • Python 脚本改用 Edge Function 或外部 API │
│ • JSON 存储改用 R2 云存储 │
│ • 考虑超时限制优化 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 19.3 批量处理差异
**本地开发(简单循环):**
```typescript
// 本地可以直接循环
async function batchExtractScripts(videoIds: string[]) {
const results = [];
for (const id of videoIds) {
const script = await extractScript(id);
results.push(script);
await delay(1000); // 避免请求过快
}
return results;
}
```
**Vercel 部署(任务队列):**
```typescript
// Vercel 需要使用 Inngest
import { inngest } from '@/lib/inngest';
export const batchExtract = inngest.createFunction(
{ id: 'batch-extract-scripts' },
{ event: 'seo/batch-extract' },
async ({ event, step }) => {
const { videoIds } = event.data;
// 每个视频作为独立步骤
for (const id of videoIds) {
await step.run(`extract-${id}`, async () => {
return await extractScript(id);
});
}
}
);
```
---
## 二十、YouTube API 配额说明
### 20.1 免费配额
| 操作 | 配额消耗 | 每日免费额度 |
| ------------ | ----------- | ----------------- |
| **搜索** | 100 单位/次 | 10,000 单位 |
| **视频详情** | 1 单位/次 | = 100 次搜索 |
| **字幕列表** | 50 单位/次 | 或 200 次视频详情 |
### 20.2 配额计算示例
```
假设每天需要:
- 搜索 20 个关键词 × 100 单位 = 2,000 单位
- 获取 200 个视频详情 × 1 单位 = 200 单位
- 总计:2,200 单位 < 10,000 单位 ✅ 足够使用
```
---
## 二十一、Vercel 部署方案详解
### 21.1 Vercel 的限制
Vercel 是 **Serverless 平台**,本质上是"按需启动的临时服务器":
| 限制类型 | 具体限制 | 影响 |
| ------------------ | --------------------------- | ------------------------ |
| **执行超时** | Hobby: 10秒, Pro: 60秒 | 批量任务无法完成 |
| **无状态** | 每次请求都是新环境 | 无法保持长连接 |
| **文件系统只读** | 只有 `/tmp` 可写 | 无法本地存储 JSON |
| **无 Python 环境** | 只支持 Node.js/Edge Runtime | 无法直接运行 Python 脚本 |
### 21.2 Inngest 是什么?
**Inngest** = 托管的任务队列服务(类似邮局)
```
你的应用 Inngest(邮局) 后台任务
│ │ │
│ 发送任务 │ │
├──────────────────────→│ │
│ "提取100个视频脚本" │ │
│ │ 分发任务 │
│ ├──────────────────────→│
│ │ "提取视频1" │
│ ├──────────────────────→│
│ │ "提取视频2" │
│ ├──────────────────────→│
│ │ ... │
│ │ │
│ 立即返回给用户 │ │ 慢慢执行
│←──────────────────────┤ │ 不受超时限制
```
**优点:**
- 不受 Vercel 超时限制
- 自动重试失败任务
- 有免费额度
**缺点:**
- 需要注册新服务
- 需要配置 Webhook
- 增加架构复杂度
### 21.3 独立 Python Worker 是什么?
**Python Worker** = 单独跑的 Python 脚本服务器
```
Vercel (Next.js) 独立服务器 (Python)
│ │
│ HTTP 请求 │
├───────────────────────→│
│ "提取这个视频脚本" │ 运行 Python 脚本
│ │ youtube-transcript-api
│ │ yt-dlp
│ 返回脚本内容 │
│←───────────────────────┤
```
**实现方式:**
1. **Railway/Render 免费托管** - 部署一个 Flask/FastAPI 服务
2. **VPS(如阿里云/腾讯云)** - 自己的服务器跑 Python 脚本
3. **Vercel + Supabase Edge Functions** - 使用 Deno 运行 Python
---
## 二十二、所有部署方案对比
### 22.1 方案全景图
| 方案 | 成本 | 复杂度 | 性能 | 推荐指数 |
| ------------------------------------ | ------ | --------------- | --------------- | ----------------- |
| **方案1: 本地开发** | 免费 | ⭐ 简单 | ⭐⭐⭐⭐⭐ 最快 | ✅✅✅ MVP 首选 |
| **方案2: VPS 服务器** | ¥50/月 | ⭐⭐ 中等 | ⭐⭐⭐⭐⭐ 最快 | ✅✅ 个人使用推荐 |
| **方案3: Vercel + Railway Python** | 免费 | ⭐⭐⭐ 复杂 | ⭐⭐⭐⭐ 快 | ✅ 适合多人协作 |
| **方案4: Vercel + Inngest** | 免费 | ⭐⭐⭐⭐ 最复杂 | ⭐⭐⭐ 中等 | ⚠️ 大规模需要 |
| **方案5: 全 Serverless (无 Python)** | 免费 | ⭐⭐ 中等 | ⭐⭐ 慢 | ⚠️ 不推荐 |
### 22.2 详细方案说明
#### 方案1: 本地开发(当前阶段)✅
```
你的电脑(本地)
├── Next.js 前端页面(pnpm dev)
├── Next.js API 路由(YouTube 搜索、博客生成)
├── Python 脚本(提取字幕)
└── JSON 文件存储(data/seo/)
```
**优点:**
- 无需任何配置,直接开发
- 无超时限制,随便跑
- 文件系统随便用
- 调试方便
**缺点:**
- 只能你自己用
- 电脑关了就不能用
**适合场景:**
- ✅ MVP 开发阶段
- ✅ 个人使用
- ✅ 测试和验证想法
---
#### 方案2: VPS 服务器(最简单的生产方案)✅✅
```
阿里云/腾讯云 轻量服务器(¥50/月)
├── Next.js 应用(pm2 运行)
├── Python 脚本(直接调用)
├── JSON 文件存储(/var/www/data/)
└── Nginx 反向代理
```
**部署步骤:**
```bash
# 1. 购买服务器(Ubuntu 22.04)
# 2. 安装 Node.js + Python
sudo apt update
sudo apt install nodejs npm python3 python3-pip
# 3. 克隆项目
git clone your-repo.git
cd your-project
# 4. 安装依赖
pnpm install
pip3 install youtube-transcript-api
# 5. 启动应用
pm2 start npm --name "seo-dashboard" -- start
# 6. 配置 Nginx
# 完成!直接用域名访问
```
**优点:**
- 完全控制,想干啥干啥
- 无超时限制
- 文件存储简单
- 性能好
**缺点:**
- 需要自己维护服务器
- 需要一定运维知识
- 每月约 ¥50 成本
**适合场景:**
- ✅ 个人长期使用
- ✅ 多个网站共用工具
- ✅ 不想折腾各种云服务
---
#### 方案3: Vercel + Railway Python Worker ✅
```
Vercel (前端 + API) Railway (Python 服务)
│ │
│ 用户访问网页 │
│ │
│ 调用 YouTube 搜索 │
│ │
│ 调用 Python 服务 ────────→│ 提取脚本
│ │ youtube-transcript-api
│ ←────────────────────── │ 返回结果
│ │
│ 保存到 R2 Storage │
```
**Railway 是什么?**
- 免费的 Python/Docker 托管平台
- 每月免费 $5 额度(约 500 小时运行时间)
- 自动从 GitHub 部署
**部署步骤:**
```python
# 1. 创建 Python 服务 (railway-python-worker/)
# main.py
from fastapi import FastAPI
from youtube_transcript_api import YouTubeTranscriptApi
app = FastAPI()
@app.get("/transcript/{video_id}")
def get_transcript(video_id: str):
transcript = YouTubeTranscriptApi.get_transcript(video_id)
return {"script": " ".join([t["text"] for t in transcript])}
```
```yaml
# railway.toml
[build]
builder = "nixpacks"
[deploy]
startCommand = "uvicorn main:app --host 0.0.0.0 --port $PORT"
```
```typescript
// 2. Vercel 调用 Railway
// src/lib/seo/transcript.ts
export async function extractTranscript(videoId: string) {
const response = await fetch(
`${process.env.RAILWAY_PYTHON_URL}/transcript/${videoId}`
);
return response.json();
}
```
**优点:**
- 前后端分离,架构清晰
- Railway 免费额度够用
- Vercel 负责前端和 API
- 自动部署
**缺点:**
- 需要管理两个服务
- 需要配置环境变量
- Railway 和 Vercel 之间有网络延迟
**适合场景:**
- ✅ 团队协作开发
- ✅ 需要公开访问
- ✅ 不想自己管服务器
---
#### 方案4: Vercel + Inngest(大规模任务队列)⚠️
```
用户 → Vercel → Inngest 任务队列 → 慢慢执行
```
**只有在以下场景需要:**
- 每天要处理 1000+ 个视频
- 需要定时自动抓取
- 需要自动重试失败任务
**当前阶段不推荐,过度工程化。**
---
#### 方案5: 全 Serverless (不用 Python) ⚠️
使用 Node.js 库替代 Python:
- `youtube-transcript` (npm 包)
- 或直接调用 YouTube API
**缺点:**
- Node.js 字幕库不如 Python 稳定
- YouTube API 需要 OAuth 认证(复杂)
- 性能和准确性不如 youtube-transcript-api
**不推荐,除非你非常讨厌 Python。**
---
## 二十三、推荐的开发路径
### 23.1 三阶段路径
```
┌─────────────────────────────────────────────────────────────────┐
│ 推荐开发路径 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 第一阶段:本地开发(1-2周) │
│ ───────────────────────────────────────────────────────────── │
│ • 在本地实现所有功能 │
│ • 验证工作流程是否满足需求 │
│ • 测试文章质量 │
│ • 优化 Prompt 模板 │
│ → 成本:免费 │
│ → 部署:不需要 │
│ │
│ 第二阶段:VPS 部署(第3周) │
│ ───────────────────────────────────────────────────────────── │
│ • 购买轻量服务器(阿里云/腾讯云) │
│ • 直接把本地代码搬上去 │
│ • 配置域名和 HTTPS │
│ • 可以随时随地访问 │
│ → 成本:¥50/月 │
│ → 复杂度:低(基本不用改代码) │
│ │
│ 第三阶段(可选):Serverless 优化(未来) │
│ ───────────────────────────────────────────────────────────── │
│ • 如果需要多人使用 │
│ • 或者需要自动扩容 │
│ • 再考虑 Vercel + Railway 方案 │
│ → 成本:免费(小规模) │
│ → 复杂度:中等(需要拆分前后端) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 23.2 当前应该做什么?
**答案:先在本地把功能做完!**
不用考虑 Inngest、不用考虑 Railway、不用考虑 Serverless。
1. **第一步:实现 YouTube 搜索**
- 创建 `/api/seo/youtube/search` API
- 存储结果到 `data/seo/searches/` JSON 文件
2. **第二步:实现脚本提取**
- 创建 Python 脚本 `scripts/extract_transcript.py`
- Next.js API 调用 Python 脚本
- 存储结果到 `data/seo/scripts/` JSON 文件
3. **第三步:实现博客生成**
- 使用 OpenRouter API (Claude 3.5 Sonnet)
- 生成博客内容
- 导出 MDX 文件
**等所有功能都验证 OK 了,再考虑部署到服务器。**
---
## 二十四、实现完成总结(2026-01-21)
### 24.1 ✅ 已完成的功能
所有核心功能已实现并可用:
| 功能 | 状态 | API 端点 | 文件位置 |
| ---------------- | ------- | -------------------------------- | ------------------------------------------------------------- |
| **YouTube 搜索** | ✅ 完成 | `/api/seo/youtube/search` | [route.ts](../src/app/api/seo/youtube/search/route.ts) |
| **单视频提取** | ✅ 完成 | `/api/seo/youtube/extract` | [route.ts](../src/app/api/seo/youtube/extract/route.ts) |
| **批量提取** | ✅ 完成 | `/api/seo/youtube/batch-extract` | [route.ts](../src/app/api/seo/youtube/batch-extract/route.ts) |
| **AI 生成博客** | ✅ 完成 | `/api/seo/blog/generate` | 已存在 |
| **MDX 导出** | ✅ 完成 | `/api/seo/blog/export-mdx` | [route.ts](../src/app/api/seo/blog/export-mdx/route.ts) |
| **JSON 存储** | ✅ 完成 | - | [storage.ts](../src/lib/seo/storage.ts) |
### 24.2 技术实现细节
#### 脚本提取方案(最终选择)
**选择:Node.js `youtube-transcript` 包** ✅
```bash
# 安装
pnpm add youtube-transcript
# 使用
import { YoutubeTranscript } from 'youtube-transcript';
const transcript = await YoutubeTranscript.fetchTranscript(videoId);
```
**为什么选这个?**
- ✅ 与 Next.js 无缝集成(无需 Python)
- ✅ 免费(无 API 费用)
- ✅ 已实现缓存机制
- ✅ 适合个人/小团队使用
#### IP 限制和速率控制
YouTube 官方限制(所有方案都一样):
```
单 IP 限制:
- 正常:~100 请求/小时
- 限速:101-150 请求/小时(变慢)
- 封禁:151+ 请求/小时(429 错误)
解决方案(已实现):
✅ 每个视频间隔 1 秒(batch-extract API)
✅ 缓存机制(避免重复请求)
✅ 错误处理(失败继续处理下一个)
实际使用建议:
- 每小时最多处理 100 个视频
- 或每天分批处理 500 个视频(5批 × 100个)
```
#### 存储架构(JSON 文件)
```
data/seo/
├── searches/ # 搜索结果
│ └── {keyword}-{date}.json
├── videos/ # 视频信息
│ └── {video_id}.json
├── scripts/ # 提取的脚本(带缓存)
│ └── {video_id}.json
├── drafts/ # 博客草稿
│ └── {slug}.json
└── published/ # 已发布博客
└── {slug}/
├── en.mdx
├── zh.mdx
└── es.mdx
```
**优点:**
- ✅ 无需数据库
- ✅ 本地开发友好
- ✅ 易于备份和迁移
- ✅ Git 可管理(可选)
### 24.3 访问和权限
#### 路由访问
```bash
# 正确的访问 URL
http://localhost:3000/seo # 英文(默认)
http://localhost:3000/zh/seo # 中文
http://localhost:3000/es/seo # 西班牙语
```
#### 权限要求
**⚠️ 重要:SEO Dashboard 需要 admin 权限**
代码位置:[src/app/[locale]/(protected)/seo/layout.tsx](<../src/app/[locale]/(protected)/seo/layout.tsx>)
```typescript
// 需要登录
if (!session) {
notFound();
}
// 只有 admin 才能访问
if (session.user.role !== 'admin') {
notFound();
}
```
#### SEO 设置
**所有 /seo 路由已配置 robots:**
```typescript
export const metadata: Metadata = {
title: 'SEO Dashboard',
robots: {
index: false, // ✅ 禁止搜索引擎索引
follow: false, // ✅ 禁止跟踪链接
},
};
```
### 24.4 使用流程(完整)
#### 阶段 1:单视频测试(5 分钟)
```bash
1. 启动开发服务器
pnpm dev
2. 访问 SEO Dashboard
http://localhost:3000/seo
(确保以 admin 身份登录)
3. 搜索视频
- 输入关键词:"seedvr2"
- 查看搜索结果
- 结果自动保存到:data/seo/searches/
4. 提取脚本
- 选择一个视频
- 点击"提取脚本"
- 脚本保存到:data/seo/scripts/{video_id}.json
5. 生成博客
- 使用提取的脚本
- AI 生成博客内容
- 保存草稿到:data/seo/drafts/{slug}.json
6. 导出 MDX
- 选择语言(en/zh/es)
- 导出文件到:data/seo/published/{slug}/{lang}.mdx
```
#### 阶段 2:批量处理(10-20 分钟)
```bash
1. 批量搜索
- 搜索多个关键词
- 收集视频 ID 列表
2. 批量提取(API 调用)
POST /api/seo/youtube/batch-extract
{
"videoIds": ["id1", "id2", ..., "id50"]
}
特点:
- 自动检查缓存(已提取的跳过)
- 每个视频间隔 1 秒
- 详细进度统计
3. 批量生成博客
- 遍历所有脚本
- 逐个生成博客
- 手动审阅质量
4. 批量导出 MDX
- 多语言导出
- 自动生成 frontmatter
```
#### 阶段 3:日常维护(建议)
```
每天工作流程:
1. 搜索 1-2 个新关键词
2. 批量提取 50 个视频脚本
3. 生成 5-10 篇博客
4. 审阅 + 导出高质量内容
每周总计:
- 搜索:5-10 个关键词
- 提取:250 个视频脚本
- 生成:25-50 篇博客
- 发布:10-20 篇优质文章
```
### 24.5 成本分析(个人使用)
#### 方案对比(月处理 500 个视频)
| 方案 | 月成本 | 处理时间 | 优点 | 缺点 |
| ------------- | ------ | ------------- | ------------ | ----------- |
| **当前实现** | **$0** | 8分钟(分批) | 免费、稳定 | 需要分批 |
| TranscriptAPI | $5 | 4分钟 | 快速、无限制 | 付费 |
| Python 方案 | $0 | 10分钟 | 最稳定 | 需要 Python |
**推荐:继续使用当前免费方案** ✅
原因:
- ✅ 月处理 500 个视频完全够用
- ✅ 成本 $0
- ✅ 无需额外部署
- ✅ 适合个人/小团队
### 24.6 环境变量配置
**必需的环境变量(已配置):**
```bash
# ✅ YouTube API(已配置)
YOUTUBE_API_KEY="your_youtube_api_key_here"
# ✅ OpenRouter API(已配置)
OPENROUTER_API_KEY="your_openrouter_api_key_here"
# ✅ 认证相关(已配置)
BETTER_AUTH_SECRET="your_secret_here"
GOOGLE_CLIENT_ID="your_google_client_id"
GOOGLE_CLIENT_SECRET="your_google_client_secret"
# ✅ 基础配置(已配置)
NEXT_PUBLIC_BASE_URL="https://seedvr2.net"
```
**所有必需的环境变量都已配置完成!** ✅
### 24.7 常见问题解答
#### Q1: 为什么访问 /seo 显示 404?
**A:** 需要满足两个条件:
1. 已登录
2. 账号角色是 `admin`
检查方法:
```sql
SELECT id, email, role FROM user WHERE email = '你的邮箱';
```
修改角色:
```sql
UPDATE user SET role = 'admin' WHERE email = '你的邮箱';
```
#### Q2: 提取脚本时遇到 429 错误怎么办?
**A:** YouTube 限流了,解决方法:
```bash
1. 检查是否短时间内提取了 >100 个视频
2. 等待 1 小时后再继续
3. 增加延迟时间(修改 batch-extract API 的 delay)
4. 或分批处理:每批 50 个,间隔 1 小时
```
#### Q3: 某些视频无法提取脚本?
**A:** 可能的原因:
```
❌ 视频没有字幕
❌ 字幕被禁用
❌ 区域限制(国家/地区限制)
❌ 会员专属视频
解决方案:
✅ 系统会自动使用视频描述作为备用
✅ 或手动添加脚本内容
✅ 或跳过该视频
```
#### Q4: 生成的博客质量不满意怎么办?
**A:** 优化方向:
```bash
1. 调整 AI Prompt(在 generate API 中)
2. 增加上下文信息(视频标题、描述)
3. 使用更强大的模型(GPT-4、Claude Opus)
4. 人工审阅和编辑草稿
```
#### Q5: 如何备份数据?
**A:** 数据都在 `data/seo/` 目录:
```bash
# 备份所有数据
cp -r data/seo/ backup/seo-$(date +%Y%m%d)/
# 或使用 Git(如果添加到版本控制)
git add data/seo/
git commit -m "Backup SEO data"
# 或压缩备份
tar -czf seo-backup-$(date +%Y%m%d).tar.gz data/seo/
```
### 24.8 下一步优化(可选)
**短期(1-2 周):**
- [ ] 优化 AI Prompt 提高博客质量
- [ ] 添加批量导出功能(一键导出所有草稿)
- [ ] 添加搜索历史和统计面板
**中期(1-2 月):**
- [ ] 实现定时任务(每天自动搜索+提取)
- [ ] 添加质量评分(自动评估博客质量)
- [ ] 集成 GitHub API(自动提交 MDX 到仓库)
**长期(按需):**
- [ ] VPS 部署(如果需要远程访问)
- [ ] 代理池(如果需要大规模抓取)
- [ ] 多人协作(如果团队使用)
### 24.9 技术债务和注意事项
**已知限制:**
1. **IP 限制**
- YouTube 单 IP 每小时限制 ~100 请求
- 建议分批处理,避免被限流
2. **缓存策略**
- 当前使用永久缓存(除非手动删除)
- 未来可考虑添加过期机制
3. **错误重试**
- 当前失败后不重试
- 可添加指数退避重试机制
4. **并发控制**
- 当前使用简单循环(顺序处理)
- 可优化为并发处理(控制并发数)
**安全性注意:**
- ✅ 所有 SEO 路由需要 admin 权限
- ✅ 已设置 robots noindex/nofollow
- ✅ API 端点已验证登录状态
- ⚠️ 建议定期检查访问日志
### 24.10 总结
**核心成果:**
- ✅ 完整的 YouTube → AI 博客工作流
- ✅ 无需数据库的 JSON 存储方案
- ✅ 适合个人/小团队的免费实现
- ✅ 所有功能可立即使用
**技术栈:**
- Next.js 15 + TypeScript
- youtube-transcript (npm)
- OpenRouter API (Claude 3.5 Sonnet)
- JSON 文件存储
**适用场景:**
- ✅ 个人博客 SEO 优化
- ✅ 内容创作辅助工具
- ✅ YouTube 视频内容分析
- ✅ 多语言内容生成
**开始使用:**
```bash
# 1. 启动服务器
pnpm dev
# 2. 访问 Dashboard(需要 admin 权限)
http://localhost:3000/seo
# 3. 开始你的第一个工作流
搜索 → 提取 → 生成 → 导出
```
---
## 二十五、最新修改记录(2026-01-21)
### 25.1 搜索页面工作流程修正
#### 原始问题
最初实现的搜索页面 (`/seo/search`) 只支持单个 URL 输入,不符合实际需求。
#### 用户反馈
> "这个不太对呀,应该是我输入关键词,然后获取批量的搜索结果的全部youtube url相关的呀然后脚本也自动获取吧,可以单个单个的,不然不是多个批量任务要排队吗,或者用api是不是也可以呀,而且我前面给你发了,你是不是可以直接给我搜索调用api都给我弄出来json格式就好了这样我可以直接在网页上查看加载一下呀"
#### 正确的工作流程
```
关键词输入 → YouTube 批量搜索 → 批量选择视频 → 批量提取脚本 → JSON 导出
```
#### 实现的功能
1. **关键词搜索**
- 输入关键词(如 "ai video generator")
- 调用 YouTube Data API v3
- 返回批量视频列表
2. **批量选择**
- 复选框批量选择视频
- 支持全选/取消全选
- 显示选择数量
3. **批量提取脚本**
- 一次提取多个视频
- 自动检查缓存(已提取的跳过)
- 显示提取进度和状态
- 每个视频间隔 1 秒(避免限流)
4. **JSON 导出**
- 在网页上预览 JSON
- 下载完整的 JSON 文件
- 包含搜索结果和提取结果
#### 文件修改
- `src/app/[locale]/(protected)/seo/search/page.tsx` - 完全重写
- `src/app/api/seo/youtube/search/route.ts` - 已存在
- `src/app/api/seo/youtube/batch-extract/route.ts` - 已存在
### 25.2 批量处理的 API 超时风险分析
#### 潜在问题
当前 `batch-extract` API 的实现方式:
- **串行处理**:一个接一个提取视频脚本
- **延迟机制**:每个视频延迟 1 秒避免 YouTube 限流
- **时间计算**:50 个视频 = 至少 50 秒
#### 风险评估
- Next.js API 路由默认超时:60 秒
- Vercel 免费版超时:10 秒
- 如果用户选择 50-100 个视频,**很可能会超时**
#### 解决方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
| -------------------- | ------------------ | ------------ | ----------- |
| **限制最大选择数量** | 改动最小,避免超时 | 需要分批操作 | ✅ MVP 首选 |
| **添加进度提示** | 用户体验略好 | 仍有超时风险 | 折中方案 |
| **流式响应 (SSE)** | 真实进度,不超时 | 实现复杂 | 未来优化 |
#### 用户使用场景
用户明确表示:"本地处理为主,网页端主要是查看,后期再弄网页版处理,现在本地可以直接处理,全部不限额"
**结论**:
- ✅ 本地开发无超时限制
- ✅ 可以直接批量处理 100+ 个视频
- ✅ 不需要限制数量
- ⚠️ 未来部署到 Vercel 时再考虑优化
### 25.3 Templates 和 Prompts 功能状态
#### 当前状态
两个页面都是 **占位页面**,只有 UI 展示,没有实际功能:
**Templates 页面** (`/seo/templates`)
- ✅ 有 4 个预设模板展示(教程类、评测类、清单类、对比类)
- ❌ 没有实际功能实现
- ❌ 不能创建/编辑/删除模板
- ❌ 不能应用模板到博客生成
**Prompts 页面** (`/seo/prompts`)
- ✅ 有系统 Prompt 和自定义 Prompt 区分
- ❌ 只有占位数据(preview 只是示例文本)
- ❌ 不能编辑/保存 Prompt
- ❌ 不能测试 Prompt 效果
#### 待实现功能
**Templates 功能需求**
1. 从参考 URL 提取结构(网页端)
2. 保存模板到 JSON 文件(本地)
3. 博客生成时选择模板
4. 根据模板结构生成内容
**Prompts 功能需求**
1. 编辑系统 Prompt(博客生成、翻译等)
2. 创建自定义 Prompt
3. 测试 Prompt 效果(预览生成结果)
4. Prompt 版本管理
#### 等待用户提供内容
用户表示会提供一些内容,需要优化 prompt 和 template 做几个版本。
### 25.4 本地测试计划
#### 测试任务
1. **关键词搜索测试**
```bash
关键词: "seedvr2"
预期: 获取所有相关视频
目标: 形成完整的 JSON 数据
```
2. **批量提取测试**
```bash
选择: 前 20 个视频
测试: 批量提取脚本
验证: 缓存机制和错误处理
```
3. **JSON 数据验证**
```bash
检查: 数据完整性
确认: 可以在网页上查看
导出: 下载 JSON 文件
```
### 25.5 自动化脚本实现
#### 脚本功能
创建了 `scripts/fetch-seedvr2-videos.ts` 脚本,一键完成:
1. YouTube 关键词搜索(获取 50 个视频)
2. 视频详细信息提取(时长、播放量、点赞数等)
3. 批量提取字幕脚本(自动延迟避免限流)
4. 保存完整 JSON 数据到本地 `data/seo/` 目录
5. 生成人类可读的摘要文档
#### 使用方式
```bash
pnpm fetch-seedvr2
```
#### 测试结果
- **总视频数**: 50 个
- **成功提取**: 37 个
- **有字幕视频**: 0 个(所有视频字幕均被禁用)
- **提取失败**: 13 个
- **数据文件**: `data/seo/seedvr2-complete-*.json` (103.93 KB)
#### 关键发现
所有 seedvr2 视频的字幕都被禁用,但**视频描述非常详细**,包含:
- 技术细节
- 使用方法
- 相关链接
- 配置说明
**建议**: 使用 `video.description` 字段而非 `video.script` 来生成博客内容。
### 25.6 网页查看接口实现
#### API 接口 (`/api/seo/data`)
- **GET** - 列出所有 JSON 数据文件
- 返回文件名、大小、修改时间
- 按修改时间倒序排列
- **GET?file=xxx.json** - 获取指定文件内容
- 返回完整 JSON 数据
- 包含统计信息
#### UI 页面 (`/seo/data`)
**功能特性**:
- 左侧:文件列表(显示大小、修改时间)
- 右侧:内容查看器
- 统计卡片(总视频数、成功数、字幕数、失败数)
- JSON 完整预览
- 下载按钮
**访问方式**:
在 SEO Dashboard 侧边栏选择 "Data Files" 即可访问 `/seo/data` 页面。
#### 导航更新
在 `src/components/seo/seo-sidebar.tsx` 中添加了:
```typescript
{ id: 'data', label: 'Data Files', href: '/seo/data', icon: FileJson }
```
### 25.7 下一步工作
#### 已完成
- [x] 更新 DESIGN.md 文档
- [x] 本地调用 API 测试 seedvr2 关键词搜索
- [x] 验证批量提取功能
- [x] 导出示例 JSON 数据
- [x] 创建网页查看接口
- [x] 更新侧边栏导航
#### 等待用户输入
- [ ] 接收用户提供的 Prompt 优化内容
- [ ] 接收用户提供的 Template 参考资料
- [ ] 根据用户需求实现 Prompts 管理功能
- [ ] 根据用户需求实现 Templates 管理功能
#### 未来优化
- [ ] Prompt 编辑器实现
- [ ] Template 提取工具实现
- [ ] 博客生成时支持选择模板
- [ ] Prompt 版本管理和测试功能
---
_文档版本: v5.1_
_更新日期: 2026-01-21_
_更新内容: 完成 seedvr2 自动化脚本、创建网页查看接口、更新侧边栏导航_
本文档为站内渲染。原始文件本地路径:saas/source/seo-llm/raw-seo知识库-TXT整理-seo方法论-seo-knowledge-base-DESIGN-md-e8d5a4.txt(仅本地保留,不入库不部署)