项目文档:YouTube 缩时播放工具 (Chrome 插件)
1. 用户需求 (User Requirements)
该项目旨在为学生和终身学习者提供一个高效的视频复习工具。
- 核心目标 (The Goal): 用户(特别是学生)在复习在线课程(如YouTube上的OCW)时,希望能跳过视频中的寒暄、重复、停顿或非关键内容,只观看(和收听)逻辑上连贯的核心知识点。
- 核心功能 (The Function):
- 用户能够启动一个“缩时播放”模式。
- 用户能够选择压缩的程度(例如,“简略”约20%,“详细”约40%)。
- 插件必须自动地、连续地播放AI筛选出的重点片段,从一个片段的结尾自动跳跃到下一个片段的开头。
- 关键场景 (The Scene): 学生在考试前快速复习一门课的多个讲座视频,目标是在1小时内“听”完5小时的课程内容。
- 明确排除 (Out of Scope): 本工具的重点是“自动跳跃播放”的速度和效率,而非提供一个可交互的摘要侧边栏(该功能已有其他插件实现)。观看的舒适度(视觉跳跃感)次要于信息的获取效率。
2. 成功关键点 (Key Success Factors)
项目的成败取决于以下三个核心挑战的解决程度:
-
AI 摘要的逻辑连贯性 (Coherence of AI Summary):
- 挑战: 如果AI只是孤立地提取“重点句”,连续播放时将导致逻辑断裂,用户无法理解。
- 对策: AI Prompt的设计是重中之重。必须明确指示AI,其任务是“剪辑”一个逻辑连贯的短视频,而不仅仅是“摘要”。选中的句子必须在上下文中保持可理解性。
-
时间戳的精确性 (Precision of Timestamps):
- 挑战: 跳跃播放的体验完全依赖于精确的
start(开始)和end(结束)时间。任何毫秒级的误差都可能导致切断单词的开头或结尾,产生极度刺耳的听觉体验。 - 对策: 字幕抓取模块必须能精确计算每个字幕片段的
end时间(例如,通过下一句的start时间来推算),并将其无误地传递给播放控制器。
- 挑战: 跳跃播放的体验完全依赖于精确的
-
播放控制器的鲁棒性 (Robustness of Playback Controller):
- 挑战: 视频播放器是一个动态环境。
timeupdate事件会高频触发,同时用户可能随时手动暂停、拖动进度条。 - 对策: 控制器逻辑必须健壮。它需要高效地检测何时到达片段末尾、准确地执行下一次跳跃(
seek),并能正确处理用户的干预(例如,用户手动拖动进度条后,控制器应能自动计算并跳到下一个“摘要片段”)。
- 挑战: 视频播放器是一个动态环境。
3. 公理设计分析 (Axiomatic Design Analysis)
我们使用公理设计(Axiomatic Design)来映射功能需求(FRs)和设计参数(DPs),以确保模块间的解耦。
-
FR1: 用户能以不同压缩率,自动、连续地播放视频的核心内容。
-
DP1: 播放控制模块 (Playback Controller),它根据一个时间片段列表(
PlaySegments)来控制<video>元素的currentTime。 -
FR2: (依赖FR1)播放的内容必须是逻辑连贯的。
-
DP2: AI摘要模块 (AI Summarization Module),它通过特定的Prompt(强调逻辑连贯性)调用Gemini API,将完整的字幕稿处理成一个“被选中的字幕片段”列表。
-
FR3: (依赖FR2)AI必须获得带精确时间戳的完整字幕。
-
DP3: 字幕获取模块 (Transcript Acquisition Module),它负责从YouTube页面抓取或拦截字幕数据,并将其解析为结构化数据(含
start和end时间)。 -
FR4: (依赖FR1, FR2)用户能启动该功能并选择压缩率。
-
DP4: 用户界面模块 (UI Module),它在页面上提供一个触发按钮和选项(如20%, 40%)。
-
FR5: (性能需求)对于长视频,处理必须快速且API成本可控。
-
DP5: 处理与缓存模块 (Processing & Caching Module),它负责在调用API前检查本地缓存,并(在需要时)在将长字幕发送给AI前进行分块(Chunking)。
分析: 这是一个良好的解耦设计 (Decoupled Design)。DPs之间存在清晰的依赖顺序(DP4 -> DP3 -> DP5 -> DP2 -> DP1),但每个模块的功能是独立的,可以分开开发和测试。
4. 模块设计 (Module Design)
根据上述分析,项目可拆分为以下5个核心模块:
-
模块一:用户界面 (UI) 模块 (Content Script / Popup)
- 职责: 在YouTube页面上注入一个控制按钮(或使用插件的
popup.html)。 - 功能:
- 提供“开始缩时播放”按钮。
- 提供压缩率选项(例如:简略-20%,详细-40%)。
- 显示当前状态(例如:“抓取字幕中...”, “AI分析中...”, “播放中...”)。
- 职责: 在YouTube页面上注入一个控制按钮(或使用插件的
-
模块二:字幕获取 (Transcript Acquisition) 模块 (Content Script)
- 职责: 抓取当前视频的完整字幕数据。
- 功能:
- 从DOM或网络请求中捕获字幕流。
- 将其解析为标准JSON格式:
[{text: "...", start: 10.5, end: 12.6}, ...]。 - 关键逻辑: 精确计算
end时间(通常是下一句的start时间减去一个微小偏移量)。
-
模块三:AI 摘要 (AI Summarization) 模块 (Background Script)
- 职责: 与Gemini API通信,获取“剪辑”后的字幕列表。
- 功能:
- 接收来自模块二的完整字幕JSON。
- 关键逻辑 (Prompting): 使用特别设计的、强调“逻辑连贯性”和“连续播放”的Prompt。
- 关键逻辑 (Chunking): 检查字幕总长度。如果超过API上下文窗口,则必须将其分块,分别调用API,最后再合并结果。
- 返回一个只包含被选中片段的字幕JSON数组。
-
模块四:缓存 (Caching) 模块 (Background Script)
- 职责: 存储和检索已处理过的视频摘要,节省API调用和时间。
- 功能:
- 使用
chrome.storage.localAPI。 - 以视频ID和压缩率(
video_id_20_percent)作为Key。 - 在调用模块三之前,先检查缓存。如果命中,则直接返回缓存数据。
- 如果未命中,则在模块三返回结果后,将结果存入缓存。
- 使用
-
模块五:播放控制 (Playback Control) 模块 (Content Script)
- 职责: 这是项目的核心执行者,负责控制视频播放器。
- 功能:
- 接收来自背景脚本的“摘要片段列表”(例如
[[10.5, 12.6], [50.2, 53.5], ...])。 - 获取页面上的
<video>元素。 - 关键逻辑 (Event Listener): 绑定
video.addEventListener('timeupdate', ...)。 - 关键逻辑 (Jumping): 在
timeupdate事件中,检查video.currentTime是否大于等于当前片段的end时间。 - 如果是,则立即更新
currentSegmentIndex,并设置video.currentTime为下一个片段的start时间,确保video.play()被调用。 - (可选) 可视化模块: 在YouTube播放进度条上渲染高亮区域,对应AI选择的片段。
- 接收来自背景脚本的“摘要片段列表”(例如
5. 项目实施规划 (Implementation Plan)
你将使用AI编程,因此我们按“功能验证”的顺序来规划实施,而不是按“代码文件”。
-
第1步:【数据抓取】(验证模块二)
- 目标: 证明你能拿到数据。
- 任务: 编写一个Content Script,在YouTube视频页打开时,自动抓取其完整字幕(带时间戳),并在控制台(Console)中打印出结构化的JSON。这是所有后续工作的基础。
-
第2步:【AI核心逻辑】(验证模块三)
- 目标: 证明AI能返回正确的数据格式。
- 任务: 在Background Script中编写一个函数。将第1步中抓取到的JSON**硬编码(Hardcode)**为输入,调用Gemini API(使用你设计的“连贯性”Prompt),然后在控制台打印出AI返回的“摘要JSON”。
-
第3步:【播放控制】(验证模块五)
- 目标: 证明你能控制播放器。
- 任务: 编写一个Content Script,在其中**硬编码(Hardcode)**一个播放列表(例如
const segments = [[10, 15], [30, 35], [60, 65]])。添加timeupdate监听器,让视频根据这个列表自动跳跃播放。这是项目的核心机制。
-
第4步:【端到端集成 v0.1】(连接 1 -> 4 -> 3 -> 5)
- 目标: 打通最小可行产品(MVP)。
- 任务:
- 制作一个最简单的UI(模块一),例如在页面上添加一个按钮。
- 点击按钮后,触发模块二(抓取字幕)。
- 字幕抓取后,发送到Background Script(模块三和四)。(暂时跳过缓存和分块)。
- Background Script调用AI(模块三),并将返回的“摘要JSON”解析成“播放列表”。
- 将“播放列表”发送回Content Script(模块五),启动自动播放。
-
第5步:【健壮性与性能】(完善模块三、四)
- 目标: 让工具变得实用。
- 任务:
- 实现缓存模块(模块四),避免重复的API调用。
- 实现分块逻辑(模块三),确保长达2小时的讲座视频也能被正确处理。
-
第6步:【体验优化】(完善模块一和可选模块)
- 目标: 提升用户体验。
- 任务:
- 优化UI(模块一),添加清晰的加载和状态提示。
- (推荐) 开发进度条可视化模块,在进度条上高亮显示AI选中的片段。
项目文档:YouTube 缩时播放网站 (React.js + Node.js)
1. 用户需求 (User Requirements)
- 核心目标 (The Goal): 用户(学生)希望在任何设备上(包括电脑、平板、手机)都能快速复习YouTube上的课程视频。
- 核心功能 (The Function):
- 用户在网站上粘贴一个YouTube视频URL。
- 网站加载该视频,并提供“缩时播放”选项(例如:简略-20%,详细-40%)。
- 用户点击播放后,网站内的嵌入式播放器会自动、连续地播放AI筛选出的重点片段,实现“自动跳跃”。
- 关键场景 (The Scene): 学生在图书馆用iPad或在咖啡馆用笔记本电脑复习,他们打开你的网站,粘贴课程链接,戴上耳机开始高效复习。
2. 成功关键点 (Key Success Factors)
-
AI 摘要的逻辑连贯性 (Coherence of AI Summary):
- (与插件方案相同) 依然是第一关键点。AI Prompt 必须优化为“剪辑”一个逻辑连贯的短片,而非简单的“摘要”。
-
后端转录服务的稳定性 (Robustness of Transcript Service):
- (新挑战) 你的后端服务器必须能稳定、可靠地从任何YouTube URL中抓取到带精确时间戳的字幕。这是整个应用的新“阿喀琉斯之踵”。如果YouTube更改了其内部API或页面结构,这个模块可能会失效,需要及时维护(通常使用
youtube-transcript这样的库来处理)。
- (新挑战) 你的后端服务器必须能稳定、可靠地从任何YouTube URL中抓取到带精确时间戳的字幕。这是整个应用的新“阿喀琉斯之踵”。如果YouTube更改了其内部API或页面结构,这个模块可能会失效,需要及时维护(通常使用
-
Iframe 播放器控制 (Iframe Player Control):
- (与插件方案不同) 你的控制对象不再是原生的
<video>元素,而是YouTube Iframe Player API。这个API是异步且基于事件的。你的播放控制器必须能精确处理它的状态(onStateChange)和事件,以实现无缝的seekTo()(跳转) 操作。
- (与插件方案不同) 你的控制对象不再是原生的
3. 公理设计分析 (Axiomatic Design Analysis)
这是一个经典的客户端-服务器架构,解耦非常清晰。
-
FR1: 用户能在网站上输入URL,并观看一个自动跳跃播放的“摘要”视频。
-
DP1: React 前端应用 (Client)。它负责所有UI交互和视频的最终呈现。
-
FR2: (依赖FR1) 前端必须能根据一个时间列表来控制视频播放。
-
DP2: Iframe 播放器控制模块 (Player Controller) (在React中实现,使用YouTube Iframe API)。
-
FR3: (依赖FR1) 前端必须能从后端获取“播放时间列表”。
-
DP3: Node.js 后端服务器 (Server)。它提供一个API端点(例如
/api/summarize)供前端调用。 -
FR4: (依赖FR3) 后端必须能从YouTube获取字幕。
-
DP4: 字幕抓取模块 (Transcript Fetcher) (在Node.js中实现,例如使用
youtube-transcript库)。 -
FR5: (依赖FR3) 后端必须能调用AI生成摘要。
-
DP5: AI 摘要模块 (AI Summarizer) (在Node.js中实现,调用Gemini API)。
-
FR6: (性能需求) 必须减少重复的API调用和处理。
-
DP6: 服务端缓存模块 (Cache) (在Node.js中实现,例如使用 Redis 或 内存缓存)。
分析: 这是一个完美的解耦设计。前端(React)完全不知道Gemini或字幕抓取的存在,它只关心“调用一个API”和“控制一个播放器”。后端处理所有复杂的逻辑和密钥。
4. 模块设计 (Module Design)
A. 前端 (Frontend - React.js)
-
模块一:UI 视图 (UIView Component)
- 职责: 渲染页面。
- 功能: 包含一个
TextField(用于粘贴URL),一个Button(用于提交),以及一个用于加载播放器的div容器。
-
模块二:API 服务 (APIService)
- 职责: 封装所有与后端的通信。
- 功能: 提供一个函数
getSummary(youtubeUrl, percentage)。它使用axios或fetch调用后端的/api/summarize端点,并返回“播放列表”[[start, end], ...]。
-
模块三:播放器组件 (YouTubePlayer Component)
- 职责: 封装 YouTube Iframe 播放器 (例如使用
react-youtube库)。 - 功能: 加载视频,并暴露
player对象给父组件(控制器)。
- 职责: 封装 YouTube Iframe 播放器 (例如使用
-
模块四:播放控制器 (PlaybackController Logic/Hook)
- 职责: 核心的前端逻辑,连接所有其他模块。
- 功能:
- 从 UI 模块获取URL。
- 调用 API 服务获取
playSegments列表。 - 将视频ID传递给播放器组件。
- 关键逻辑: 监听播放器的
onStateChange和onReady事件。使用setInterval或requestAnimationFrame轮询player.getCurrentTime()。 - 当
currentTime>=currentSegment.end时,调用player.seekTo(nextSegment.start)并确保player.playVideo()。
B. 后端 (Backend - Node.js / Express.js)
-
模块五:API 端点 (API Endpoint)
- 职责: 路由。
- 功能: 定义
POST /api/summarize路由。它负责解析请求体(获取URL和percentage),并按顺序调用后续模块。
-
模块六:字幕抓取 (Transcript Fetcher) 模块
- 职责: 从YouTube获取带时间戳的字幕。
- 功能: 使用
youtube-transcript或类似库,输入URL,输出结构化的字幕JSON[{text, start, duration}, ...]。处理字幕不可用或视频不存在的错误。
-
模块七:AI 摘要 (AI Summarizer) 模块
- 职责: 调用Gemini API。
- 功能: (与插件方案相同)接收字幕JSON,使用“逻辑连贯性”Prompt,返回被选中的字幕片段。
-
模块八:服务端缓存 (Caching) 模块
- 职责: 存储已处理过的结果。
- 功能: 使用 (例如)
node-cache或 Redis。在调用模块六和七之前,先用video_id + percentage作为Key检查缓存。如果命中,则直接返回缓存结果。
5. 项目实施规划 (Implementation Plan)
你将使用AI编程,我们按“功能验证”的顺序规划,后端优先,因为它是前端的依赖。
-
第1步:【后端】(验证模块六)
- 目标: 证明能拿到数据。
- 任务: 创建一个独立的Node.js脚本,使用
youtube-transcript库,传入一个YouTube URL,看是否能在控制台打印出带时间戳的字幕JSON。这是最大的外部风险点。
-
第2步:【后端】(验证模块七)
- 目标: 证明AI逻辑。
- 任务: 将第1步的JSON硬编码,在Node.js中调用Gemini API(使用你的“连贯性”Prompt),看是否能返回正确的“摘要”JSON。
-
第3步:【前端】(验证模块三、四)
- 目标: 证明能控制播放器。
- 任务: 创建一个最小的React应用(使用
create-react-app或vite)。使用react-youtube库。硬编码一个播放列表(例如const segments = [[10, 15], [30, 35]])。添加一个按钮,点击后开始根据这个列表自动跳跃播放。
-
第4步:【后端】(验证模块五、八)
- 目标: 搭建可用的API。
- 任务: 结合第1、2步,创建一个Express服务器。实现
POST /api/summarize端点。实现简单的服务器内存缓存(模块八)。
-
第5步:【端到端集成】(连接 4 -> 2 -> 3)
- 目标: 打通完整流程。
- 任务:
- 完善前端UI(模块一),添加输入框。
- 实现前端API服务(模块二)。
- 将前端的播放控制器(模块四)中的硬编码列表,替换为从后端API的动态获取。
-
第6步:【健壮性与部署】
- 目标: 让应用可被公开访问。
- 任务:
- 在前端和后端添加完整的错误处理(例如:视频没有字幕、AI调用失败)。
- 在前端添加加载状态(Loading Spinners)。
- 将后端部署到 (例如) Vercel Serverless Functions 或 Render。
- 将前端部署到 (例如) Vercel 或 Netlify。
vibe coding 结果
https://ai.studio/apps/drive/1k0Ts7_rZ3KtBqzfeugRr1TCZXTrK0oWh