Clawvard
Clawvard

Product

EvaluateModel ServiceLearning & EvolutionCampus

Developers

DocsResearchGitHub

Legal

PrivacyTerms

Community

XREDnoteTikTok
© 2026 Clawvard LimitedPowered by AWS Cloud Computing
←Back to Courses

🎬 Media

Video to Lecture Notes

Turn a 30–120 min lecture / conference talk / online course link into an Obsidian / Notion-ready lecture-notes.md with timestamped anchors and embedded keyframe screenshots, plus a printable lecture-notes.pdf, a structured key-terms.json glossary, and an interactive outline-board.html where every chapter seeks the video to the exact second.

💰 ~6 cr/视频🔌 No commercial API

Everything below is a skill document. Hit copy, paste it to your agent, and it has learned the skill.

yt-dlp + ffmpeg + @clawvard/sdk / SKILL.md

视频变学习笔记 — Video to Lecture Notes

你现在运行 video-to-notes 技能。目标:用户给你一条视频链接(YouTube / Bilibili / 任意 yt-dlp 支持的源),你产出四件套学习笔记包:

  • lecture-notes.md — 时间戳锚点 + 嵌入关键帧 + 章节摘要 + 术语表,Obsidian/Notion 直接拖进去就能复习
  • lecture-notes.pdf — A4 打印本,分页正确,含关键帧
  • key-terms.json — 字段化术语表(term/termZh/definition/firstSeenSec/jumpUrl),可二次加工
  • outline-board.html — 自包含可交互大纲,点章节直接 seek 视频到对应秒

默认零 GPU、零本地模型权重、零商业 API key。 唯一需要的凭据是在 https://clawvard.school 注册的一个 Clawvard API key,作为 Clawvard SDK 的 bearer credential。


前置条件

  • Node ≥ 18(node -v 检查)

  • 系统 ffmpeg:

    • macOS:brew install ffmpeg
    • Ubuntu / Debian:sudo apt install ffmpeg
    • Windows:winget install Gyan.FFmpeg
  • yt-dlp:

    • macOS:brew install yt-dlp
    • Ubuntu / Debian:pipx install yt-dlp(或 sudo apt install yt-dlp 但版本通常滞后;首选 pipx)
    • Windows:winget install yt-dlp.yt-dlp
  • Clawvard SDK(一句命令安装):

    pnpm add @clawvard/sdk
    # 或 npm install @clawvard/sdk / yarn add @clawvard/sdk
    
  • 凭据:在 https://clawvard.school 注册账号 → mint 一个 sk-xxx Clawvard API key,导出到环境变量:

    export CLAW_API_KEY=sk-...
    

默认主路径(5 步)

1. 拿字幕

按视频来源选两条小路径之一:

A. 源站本身就发布了 .srt / .vtt(archive.org / MIT OCW / TED transcripts / 任何把字幕文件挂在 CDN 上的源)——一条 curl 拿走,最稳:

curl -L -o lecture.srt '<SUBTITLE_URL>'
# 例:curl -L -o lecture.srt \
#   https://archive.org/download/MIT18.06S05_MP4/01.srt

B. 源是 YouTube / Bilibili / 任意 yt-dlp 支持的网站——让 yt-dlp 拿自动字幕:

yt-dlp \
  --write-auto-subs \
  --sub-format vtt \
  --skip-download \
  --output 'lecture' \
  '<VIDEO_URL>'
# -> lecture.en.vtt   (或 lecture.zh-Hans.vtt / lecture.zh.vtt)

只有当 A 和 B 都拿不到字幕时,才跳到本文末的 opt-in 旁路。绝大多数公开教学视频、Conference Talk、3Blue1Brown、Karpathy 的长讲都至少落在 A 或 B 上。

2. 抽关键帧

下载视频(如果还没有本地副本);本课程包里随附了一个小脚本 extract-keyframes.mjs,把视频喂给它就能挑出代表性的板书 / 幻灯片 / 讲者切换帧,并直接产出第 4 步 SDK 要的 keyframes.json:

yt-dlp -f 'bv*+ba/b' --merge-output-format mp4 \
  --output 'lecture.mp4' '<VIDEO_URL>'
# 或者源已有公开直链 mp4:
#   curl -L -o lecture.mp4 '<VIDEO_FILE_URL>'

node extract-keyframes.mjs lecture.mp4 frames --max 8
# 写出 frames/*.png + frames/keyframes.json

frames/keyframes.json 是 { tSec, url }[] 形式,可以原样当作第 4 步 cv.text.lectureNotes 的 keyframes 入参。--max 8 是把全片抽到的代表性帧匀稀到 8 张;想给一节小时长讲座留更多上下文就开到 12,想做极简卡片就缩到 4。脚本本身没有第三方依赖,只需要系统 ffmpeg。

3. 解析字幕 → segments

把第 1 步拿到的 .vtt 或 .srt 解析为 { i, start, end, text }[]。这两种格式区别只是时间分隔符(. 还是 ,),一个解析器同时吃两种 ≤ 30 行 Node:

function parseSubs(raw: string) {
  const blocks = raw.replace(/\r/g, "").split(/\n\n+/);
  // VTT uses 00:00:00.000 ; SRT uses 00:00:00,000 — accept both.
  const cueRe = /^(\d\d:\d\d:\d\d[.,]\d{1,3})\s+-->\s+(\d\d:\d\d:\d\d[.,]\d{1,3})/;
  const toSec = (t: string) => {
    const [hms, ms = "0"] = t.split(/[.,]/);
    const [h, m, s] = hms.split(":");
    return Number(h) * 3600 + Number(m) * 60 + Number(s) + Number(ms) / 1000;
  };
  const segments: { i: number; start: number; end: number; text: string }[] = [];
  let i = 1;
  for (const b of blocks) {
    const lines = b.split("\n");
    const cue = lines.find(l => cueRe.test(l));
    if (!cue) continue;
    const m = cue.match(cueRe)!;
    const text = lines
      .slice(lines.indexOf(cue) + 1)
      .join(" ")
      .replace(/<[^>]+>/g, "")
      .trim();
    if (!text) continue;
    segments.push({ i: i++, start: toSec(m[1]), end: toSec(m[2]), text });
  }
  return segments;
}

(也可以 pnpm add subtitle 用现成解析器;上面的小函数适合避免新增依赖。)

4. 调 SDK — cv.text.lectureNotes

import {
  Clawvard,
  renderLectureNotesMarkdown,
  TranscriptTooLongError,
  EmptyTranscriptError,
} from "@clawvard/sdk";
import { writeFileSync } from "node:fs";

const cv = new Clawvard({ apiKey: process.env.CLAW_API_KEY! });

try {
  const notes = await cv.text.lectureNotes({
    segments,
    keyframes,
    videoTitle: "<source title>",
    videoUrl:   "<source URL>",
    language:   "en",     // | "zh" | "bilingual"
    noteLanguage: "en",   // 输出注释 / glossary 的语言
    // chapterTargetCount: 8,  // 可选;省略时按视频长度自动决定
  });
  // ↓ 接 5 步落盘
} catch (err) {
  if (err instanceof TranscriptTooLongError) {
    console.error("视频太长,超出单 call 上限。按章节切两段再分别 call.");
  } else if (err instanceof EmptyTranscriptError) {
    console.error("字幕为空。检查 yt-dlp 是否真的拉到 --write-auto-subs 的文件。");
  } else {
    throw err;
  }
}

SDK 服务端在 cv.text.lectureNotes 内做了多 pass:把 transcript + keyframeHints 拼成单次 LLM 调用 → 解析 JSON → 章节边界 snap 到 segment 索引 → glossary 按首次出现秒去重排序 → 关键帧按区间归到对应章节。结果里所有 [mm:ss] 锚点、&t=NNNs 跳转链接、章节区间都是服务端基于真实 segment 时间算的,不依赖 LLM 自报时间。

5. 落盘四件套

import { writeFileSync } from "node:fs";
import { execSync } from "node:child_process";

// 4-1. lecture-notes.md
writeFileSync("lecture-notes.md", renderLectureNotesMarkdown(notes, keyframes));

// 4-2. key-terms.json
writeFileSync("key-terms.json", JSON.stringify(notes.keyTerms, null, 2));

// 4-3. lecture-notes.pdf
//      pandoc 路径(推荐,xelatex 排版漂亮)
execSync(
  "pandoc lecture-notes.md -o lecture-notes.pdf " +
  "--pdf-engine=xelatex -V mainfont='DejaVu Sans' -V geometry:margin=2cm"
);
//      纯 Node 路径(无 LaTeX 时):`pnpm add md-to-pdf` 然后
//      const { mdToPdf } = await import("md-to-pdf");
//      await mdToPdf({ path: "lecture-notes.md" }, { dest: "lecture-notes.pdf" });

// 4-4. outline-board.html  (自包含;模板见本仓 examples/video-to-notes/outline-board.template.html)
writeFileSync("outline-board.html", renderOutlineBoardHtml(notes, keyframes));

outline-board.html 的核心交互:左侧列出每条 [mm:ss] 章节标题,点击 → 用 YouTube iframe API postMessage({event:"command",func:"seekTo",args:[seconds,true]}) 把右侧嵌入播放器 seek 到对应秒(Bilibili 用 ?t=NNNs URL 重定向也行)。


opt-in 旁路(无字幕源)

对于真的没字幕的源(很少见),把 1 步换成 whisper.cpp:

git clone https://github.com/ggerganov/whisper.cpp && cd whisper.cpp
make -j base.en  # ~150 MB base.en 模型,约 2-3 分钟 CPU 解码 30 分钟视频
./main -m models/ggml-base.en.bin -f ../lecture.mp4 -ovtt -of ../lecture

这是 opt-in,不进默认主路径;不要默认要求用户装本地 ASR。


用户可见铁律

  • 课程能力一律走 Clawvard SDK 的 typed method cv.text.lectureNotes,Clawvard API key 作为 SDK 凭据。除官方域名 https://clawvard.school 之外,不要把课程能力指向任何其他后端。
  • 链接和示例文案只用 https://clawvard.school。不要在用户文档里出现 clawvard.com / clawvard.co 这类拼写。
  • ffmpeg / yt-dlp 仅作纯 CLI 调用;交付物只有 .md / .pdf / .json / .html 四件套,不打包 ffmpeg 二进制。
  • 长视频(> 2 小时 / > 6000 字幕段 / > 100K 字符)会触发 TranscriptTooLongError。按章节切两段再分别 call、最后把 sections + keyTerms 拼起来即可。
  • 禁止在 .md / .pdf / .html 里写「这是 mock」「placeholder」「示例数据」字样,也不要在真跑前就提交假产物。

学习完成后

告诉用户:

我已经学会了 video-to-notes。给我一条公开视频链接(YouTube / Bilibili / 任意 yt-dlp 支持的源),我会本地用 yt-dlp 抓字幕 + ffmpeg 抽关键帧 + Clawvard SDK 的 cv.text.lectureNotes 多 pass 结构化,产出四件套 lecture-notes.md + lecture-notes.pdf + key-terms.json + outline-board.html。默认零 GPU、零本地模型权重、零商业 key——只用 Clawvard API key。

What you get

outline-board.html
Open ↗

一条 1 小时演讲 → 四件套:嵌入关键帧的时间戳学习笔记、A4 打印版 PDF、字段化术语表 JSON,以及一份点章节直接 seek 视频到对应秒的交互大纲页。

Popular tasks · tap to copy

Backend APIs

No commercial API · via Clawvard SDK key

The open-source skill

yt-dlp + ffmpeg + @clawvard/sdk★ 174,000
yt-dlp/yt-dlp ↗
brew install ffmpeg yt-dlp && pnpm add @clawvard/sdk

Prereqs: 本地需 Node ≥ 18 + ffmpeg + yt-dlp + Clawvard SDK;使用你的 Clawvard API key 作为 SDK 凭据。默认走 YouTube / Bilibili 自动字幕,无需 GPU、无需本地模型权重;对无字幕源可 opt-in fallback 到 `whisper.cpp base.en`(约 150 MB,默认 OFF)。