Notre avis
Convertit une vidéo en notes visuelles sous forme de canvas Obsidian en utilisant un pipeline hybride à trois étapes (transcription audio, détection visuelle, fusion par LLM).
Points forts
- Combine transcription audio et analyse visuelle pour une couverture complète du contenu.
- Gère les vidéos longues avec découpage automatique en segments de 15 minutes pour éviter les hallucinations.
- Produit un fichier .canvas directement exploitable dans Obsidian avec mise en page intelligente.
Limites
- Nécessite des outils externes (FFmpeg, WhisperX, Gemini) et une configuration Python.
- Le pipeline peut prendre du temps selon la durée de la vidéo et la puissance de calcul disponible.
- La qualité finale dépend de la précision des modèles de transcription et de détection visuelle.
Idéal pour transformer des vidéos de formation, conférences ou tutoriels en notes structurées et visuelles.
Déconseillé pour des vidéos très courtes (<1 minute) ou dont le contenu audio est inexistant ou non pertinent.
Analyse de sécurité
PrudenceThe skill legitimately uses Bash to invoke a Python processing pipeline for video analysis, involving FFmpeg and possibly network APIs. While the skill itself seems well-intentioned, the combination of Bash with user-supplied file paths presents a risk of command injection if not properly sanitized by the agent. However, the skill is designed for local use and does not instruct destructive actions. Therefore, classify as caution.
- •Allows Bash execution that could be misused if video path is maliciously crafted, though double-quoting mitigates some risk.
- •Runs a Python script that may make network calls (Gemini API) and executes system commands (FFmpeg/ffprobe), which could lead to data exfiltration or unintended effects if the API keys are exposed.
Exemples
/video-to-canvas video.mp4/video-to-canvas video.mp4 --depth=deep_dive/video-to-canvas video1.mp4 video2.mp4 video3.mp4name: video-to-canvas description: | 将视频转换为 Obsidian Canvas 可视化笔记。
三阶段混合管道 (社区验证最佳实践):
- Stage 1 (Ears): WhisperX/Gemini 音频转录
- Stage 2 (Eyes): Gemini 视觉检测 + FFmpeg 截图
- Stage 3 (Brain): LLM 双通道融合生成笔记
- Phase 4: Claude 智能布局生成 Canvas
用法:/video-to-canvas <视频路径> [选项]
user-invocable: true
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
- AskUserQuestion
- Task
- mcp__sequential-thinking__sequentialthinking
skills:
- obsidian-canvas
hooks: PreToolUse: - matcher: "Bash" hooks: - type: command command: "echo '[video-to-canvas] 执行系统命令...'"
Video to Canvas
将视频转换为 Obsidian Canvas 可视化笔记(三阶段混合管道)。
快速使用
/video-to-canvas <视频路径>
/video-to-canvas video.mp4 --depth=deep_dive
/video-to-canvas video.mp4 --no-transcribe # 跳过转录(旧模式)
/video-to-canvas video.mp4 --layout=mindmap
# 批量队列模式(多个视频顺序处理)
/video-to-canvas video1.mp4 video2.mp4 video3.mp4
完整工作流(三阶段混合管道)
📹 视频文件
│
├──────────────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Stage 1 (Ears) │ │ Stage 2 (Eyes) │
│ WhisperX/Gemini │ │ Gemini 视觉检测 │
│ 音频转录 │ │ + FFmpeg 截图 │
│ → 时间戳文本 │ │ → screenshots/ │
└──────────────────┘ └──────────────────┘
│ │
└──────────┬───────────┘
▼
┌────────────────────────────┐
│ Stage 3 (Brain) │
│ Gemini 2.5 Flash │
│ 转录文本 + 截图 → 笔记 │
│ 15 分钟分段避免幻觉 │
│ → 结构化 Markdown │
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ Phase 4: Claude │
│ 语义理解 + 智能布局 │
│ → .canvas 文件 │
└────────────────────────────┘
│
▼
📊 Obsidian Canvas 可视化笔记
为什么需要三阶段?
| 问题 | 旧架构 | 三阶段管道 | |------|--------|-----------| | 音频内容丢失 | Phase 2 只发送截图,丢失口述内容 | Stage 1 转录音频,Stage 3 融合 | | 长视频幻觉 | Gemini >20min 严重幻觉 | 15 分钟分段处理 | | 信息不完整 | 只有屏幕变化,无讲解内容 | 双通道:视觉+音频 | | 截图覆盖缺口 | Gemini 只分析前半部分 | Stage 2.5 自动补充 + ffprobe 时长校正 | | 幻觉图片引用 | LLM 编造不存在的截图路径 | 提示词约束 + 后处理验证 |
防护机制(自动生效)
管道内置以下防护,无需手动干预:
| 机制 | 位置 | 解决的问题 |
|------|------|-----------|
| ffprobe 时长优先 | Stage 2.5, Stage 3 | Gemini Audio 转录时长可能幻觉(如 56min 视频报告 78min) |
| Stage 2.5 覆盖率检查 | Stage 2 之后 | Gemini 视觉检测只分析前半部分,后半段无截图 |
| 自动补充截图 | Stage 2.5 | 未覆盖区域每 30 秒自动截图填充 |
| 分段时长截断 | Stage 3 分段 | 超出实际视频时长的转录 chunks 被丢弃 |
| 提示词截图约束 | Stage 3 Prompt | 明确告知 LLM 只能引用列表中的截图文件 |
| 后处理图片验证 | 保存 MD 前 | 扫描所有  引用,移除指向不存在文件的 |
| 反引号修复 | 保存 MD 前 | 修复 Gemini 输出的 `` 格式问题 |
Stage 1-3: 三阶段管道 (Python 脚本)
执行步骤
-
后台启动三阶段管道(
--daemon自守护,无需 nohup):cd ~/.claude/skills/video-to-canvas/scripts && PYTHONUTF8=1 uv run python video_to_md.py "<视频路径>" -o "<输出目录>" --depth balanced --srt-lang zh --daemon -
轮询进度(每 30-60 秒检查一次 progress.json):
cat "<输出目录>/progress.json"progress.json 字段说明:
status:running|completed|failedstage:stage1|stage1.5|stage2|stage3|donestage_detail: 当前阶段详细描述error: 失败时的错误信息
-
管道完成后(status=completed),获取输出文件:
<输出目录>/<视频名>.md- Markdown 笔记<输出目录>/screenshots/- 截图目录<输出目录>/<视频名>_transcript.json- 转录结果<输出目录>/<视频名>_changes.json- 变化点信息<输出目录>/<视频名>.srt- 英文字幕(精确时间戳,默认生成)<输出目录>/<视频名>.<lang>.srt- 翻译字幕(使用--srt-lang时生成)
恢复机制
管道支持断点恢复。如果中途失败,只需重新运行同一命令:
transcript.json已存在 → 跳过 Stage 1screenshots/+changes.json已存在 → 跳过 Stage 2chunks/chunk_N.json已存在 → Stage 3 跳过对应分段.srt文件已存在 → 跳过字幕生成
参数说明
| 参数 | 说明 | 默认值 |
|------|------|--------|
| --depth | 笔记深度 | balanced |
| --density | 检测密度 (sparse/normal/dense) | normal |
| --min-interval | 最小截图间隔(秒)| 2.0 |
| --fusion | 启用视觉双通道融合 | false |
| --backend | 转录后端 (auto/faster-whisper/gemini) | auto |
| --whisper-model | Whisper 模型大小 | large-v3 |
| --segment-minutes | 长视频分段时长(分钟)| 15 |
| --transcript | 已有转录文件路径 | - |
| --no-transcribe | 跳过音频转录(旧模式)| false |
| --no-srt | 不生成 SRT 字幕文件 | false |
| --srt-lang | SRT 翻译目标语言 (如 zh, ja, ko) | 不翻译 |
深度选项
short_hand: 极简模式,要点列表balanced: 平衡模式(推荐),段落+列表deep_dive: 深度模式,详尽解释
转录后端选择
| 后端 | 优势 | 要求 |
|------|------|------|
| faster-whisper (推荐) | 速度快、VAD 去幻觉、本地运行 | pip install faster-whisper |
| gemini (备选) | 无需本地模型、零配置 | GEMINI_API_KEY |
--backend auto 会自动检测:优先使用 faster-whisper,未安装则回退到 Gemini。
Phase 4: Canvas 智能生成
Phase 1-3 由 Python 脚本执行后,Phase 4 由 Claude 完成。
输入
读取 Phase 3 生成的 Markdown 笔记文件。
分析任务
-
结构识别
# 标题 → 画布标题(不创建节点) ## 一级章节 → group 节点(分组容器) ### 二级章节 → text 节点 #### 三级标题 → text 节点(在父节点内)  → file 节点 -
语义分析
- 并列关系 → 水平排列
- 层级关系 → 垂直排列
- 对比关系 → 左右对称
- 重要内容 → 颜色高亮
-
布局决策
- 教程类 → 流程图布局(从上到下)
- 概念类 → 思维导图(中心辐射)
- 对比类 → 表格布局(左右对称)
输出格式
生成 JSON Canvas 格式:
{
"nodes": [
{
"id": "group-章节名",
"type": "group",
"label": "一、章节标题",
"x": 0, "y": 0,
"width": 800, "height": 400,
"color": "4"
},
{
"id": "text-知识点",
"type": "text",
"text": "### 知识点标题\n\n内容描述...",
"x": 50, "y": 80,
"width": 350, "height": 150
},
{
"id": "img-00-36",
"type": "file",
"file": "<输出目录名>/screenshots/00-36.jpg",
"x": 50, "y": 250,
"width": 350, "height": 250
}
],
"edges": [
{
"id": "edge-1",
"fromNode": "text-知识点",
"toNode": "img-00-36",
"fromSide": "bottom",
"toSide": "top",
"label": "演示"
}
]
}
JSON Canvas 格式规范
节点类型
| 类型 | 用途 | 必需字段 |
|------|------|---------|
| text | Markdown 文本 | text |
| file | 图片/文件引用 | file |
| link | 外部 URL | url |
| group | 分组容器 | label (可选) |
通用节点属性
{
"id": "unique-16-char-hex",
"type": "text|file|link|group",
"x": 0,
"y": 0,
"width": 300,
"height": 150,
"color": "1" // 可选
}
颜色系统
| 值 | 颜色 | 建议用途 | |----|------|---------| | "1" | 红色 | 重要/警告 | | "2" | 橙色 | 提示/注意 | | "3" | 黄色 | 高亮重点 | | "4" | 绿色 | 正确/完成 | | "5" | 青色 | 引用/链接 | | "6" | 紫色 | 概念/定义 |
也支持 hex 格式:"#FF5733"
Edge 属性
{
"id": "edge-unique-id",
"fromNode": "source-node-id",
"toNode": "target-node-id",
"fromSide": "bottom", // top|right|bottom|left
"toSide": "top",
"toEnd": "arrow", // arrow|none
"label": "关系描述" // 可选
}
布局算法
尺寸建议
| 元素 | 宽度 | 高度 | |------|------|------| | 标题文本节点 | 300 | 80 | | 内容文本节点 | 400 | 150 | | 图片节点 | 350 | 250 | | 分组最小 | 自适应 | 自适应 | | 节点水平间距 | 100 | - | | 节点垂直间距 | 80 | - |
层级布局(默认)
[文档标题]
│
┌───────────────────┼───────────────────┐
│ │ │
[Group: 章节1] [Group: 章节2] [Group: 章节3]
│ │ │
┌───┴───┐ ┌─────┴─────┐ ┌───┴───┐
│ │ │ │ │ │
[知识点] [知识点] [知识点] [知识点] [知识点] [知识点]
│ │ │ │ │ │
[图片] [图片] [图片] [图片] [图片] [图片]
坐标计算规则
- 根节点:从 (0, 0) 开始
- Group 内部:padding 50px
- 同级节点:水平排列,间距 100px
- 子节点:垂直排列在父节点下方,间距 80px
- 图片节点:紧跟对应文本节点下方
避免重叠
- 计算每个 group 的实际宽高(基于内部节点)
- Group 之间保持 100px 间距
- 使用深度优先遍历计算坐标
图片路径处理
Markdown 中的图片

转换为 Canvas file 节点
{
"id": "img-00-36",
"type": "file",
"file": "<输出目录名>/screenshots/00-36.jpg",
"x": 50,
"y": 250,
"width": 350,
"height": 250
}
⚠️ 重要:Vault 相对路径
Obsidian Canvas 的 file 路径是相对于 vault 根目录的,不是相对于 .canvas 文件。
例如,输出目录为 lecture1/,用户将其复制到 vault 根目录后:
vault根目录/
├── lecture1/
│ ├── lecture.canvas
│ ├── lecture.md
│ └── screenshots/
│ └── 05-33.jpg
Canvas 中的路径应为:
"file": "lecture1/screenshots/05-33.jpg" // ✅ 正确 (vault 相对路径)
"file": "screenshots/05-33.jpg" // ❌ 错误 (canvas 相对路径)
Phase 4 生成规则:file 字段必须使用 <输出目录名>/screenshots/xx-xx.jpg 格式。
执行流程
当用户调用 /video-to-canvas <视频路径> 时:
Step 1: 参数解析
视频路径: <用户提供>
输出目录: 与视频同目录,或用户指定
深度: balanced (默认)
布局: hierarchical (默认)
Step 2: 后台启动三阶段管道
cd ~/.claude/skills/video-to-canvas/scripts && PYTHONUTF8=1 nohup uv run python video_to_md.py "<视频路径>" -o "<输出目录>" --depth <深度> --srt-lang zh > "<输出目录>/pipeline.log" 2>&1 &
Step 2.5: 轮询进度(每 30-60 秒)
cat "<输出目录>/progress.json"
等待 status 变为 completed(或 failed)。如果失败,查看 pipeline.log 和 error 字段。
完成后检查输出:
<输出目录>/<视频名>.md存在<输出目录>/screenshots/目录有图片<输出目录>/<视频名>_transcript.json存在(如启用转录)
Step 3: 读取 Markdown
使用 Read 工具读取生成的 .md 文件
Step 4: 分析并生成 Canvas
- 解析 Markdown 结构(标题、内容、图片)
- 确定语义关系和布局策略
- 计算每个节点的坐标
- 生成 JSON Canvas
- file 节点路径: 使用
<输出目录名>/screenshots/xx-xx.jpg(vault 相对路径) - text 节点内容: 确保 JSON 字符串中的双引号已转义 (
\") 或替换为全角引号
Step 5: 写入 Canvas 文件
使用 Write 工具写入 <视频名>.canvas
Step 6: 报告结果
✅ 三阶段混合管道完成!
输出文件:
├── <视频名>.md # Markdown 笔记(双通道融合)
├── <视频名>.canvas # Canvas 可视化
├── <视频名>.srt # 英文字幕(精确时间戳,默认生成)
├── <视频名>.<lang>.srt # 翻译字幕(--srt-lang 时生成)
├── <视频名>_transcript.json # 音频转录结果
├── <视频名>_changes.json # 变化点信息
└── screenshots/ # 截图目录
提示:将整个输出目录复制到 Obsidian vault 中,
然后打开 .canvas 文件查看可视化笔记。
SRT 字幕文件会被 Media Extended 插件自动检测(同名同目录)。
队列模式(批量处理多个视频)
当用户提供多个视频路径时,使用队列模式顺序处理。
队列流程
📹 video1.mp4 📹 video2.mp4 📹 video3.mp4
│ │ │
└───────────────┬───────────────┘
▼
┌─────────────────────┐
│ queue_processor.py │
│ add → run --daemon │
│ 顺序处理每个视频 │
└─────────────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
[Stage 1-3] [Stage 1-3] [Stage 1-3]
video1 ✓ video2 ◉ video3 ○
│ │ │
▼ ▼ ▼
[Phase 4] [Phase 4] [Phase 4]
Claude生成 Claude生成 Claude生成
Canvas Canvas Canvas
Step Q1: 添加视频到队列
cd ~/.claude/skills/video-to-canvas/scripts && PYTHONUTF8=1 uv run python queue_processor.py add "<视频1>" "<视频2>" "<视频3>" --depth balanced --srt-lang zh
Step Q2: 后台启动队列处理
cd ~/.claude/skills/video-to-canvas/scripts && PYTHONUTF8=1 uv run python queue_processor.py run --daemon
Step Q3: 轮询队列进度
cat ~/.claude/skills/video-to-canvas/queue.json
queue.json 字段说明:
status:idle|processing|completedtotal: 队列总数completed: 已完成数failed: 失败数current_index: 当前正在处理的项目索引items[].status:pending|processing|completed|failed
轮询策略:
- 每 60 秒检查一次 queue.json
- 当某个 item 的 status 变为
completed时,立即为其生成 Canvas(Phase 4) - 然后继续轮询等待下一个视频完成
- 当 queue.status 变为
completed时,所有视频处理完毕
Step Q4: 每个视频完成时生成 Canvas
对于队列中每个 completed 的视频:
- 读取其
<output>/<视频名>.md - 执行 Phase 4(分析 + 生成 Canvas)
- 写入
<output>/<视频名>.canvas
⚠️ 重要:Canvas 生成(Phase 4)在每个视频的管道完成后立即执行,不需要等待所有视频都完成。这样可以边处理边生成。
Step Q5: 处理中追加新视频
用户可以在队列处理过程中追加新视频:
cd ~/.claude/skills/video-to-canvas/scripts && PYTHONUTF8=1 uv run python queue_processor.py add "<新视频>"
队列处理器会在当前视频完成后自动热加载队列,开始处理新添加的视频。
Step Q6: 查看队列状态
cd ~/.claude/skills/video-to-canvas/scripts && PYTHONUTF8=1 uv run python queue_processor.py status
Step Q7: 清理队列
cd ~/.claude/skills/video-to-canvas/scripts && PYTHONUTF8=1 uv run python queue_processor.py clear --completed
队列模式判断规则
当用户调用 /video-to-canvas 时:
- 单个视频路径 → 使用原有单视频流程(Step 1-6)
- 多个视频路径 → 使用队列模式(Step Q1-Q7)
- 路径中包含通配符(如
*.mp4)→ 先 glob 展开,然后使用队列模式
错误处理
Python 脚本执行失败
- 检查 GEMINI_API_KEY 环境变量
- 检查视频文件路径是否正确
- 检查 FFmpeg 是否安装
转录失败
--backend auto: faster-whisper 未安装时自动回退到 Gemini- 安装 faster-whisper:
pip install faster-whisper - 或强制使用 Gemini:
--backend gemini - 使用已有转录:
--transcript existing_transcript.json - 跳过转录:
--no-transcribe
图片不显示
- 确保
screenshots/目录与.canvas文件在同一目录 - 检查图片路径是否正确(相对路径)
Canvas 节点重叠
- 增加
nodeSpacing参数 - 使用更简化的布局
高级选项
指定布局
/video-to-canvas video.mp4 --layout=mindmap
布局选项:
hierarchical: 层级布局(默认)mindmap: 思维导图flowchart: 流程图
指定深度
/video-to-canvas video.mp4 --depth=deep_dive
只生成 Canvas(已有 MD)
/video-to-canvas --canvas-only existing-notes.md
示例输出
输入 Markdown 片段
# Obsidian 核心功能
## 一、双向链接
双向链接让笔记形成网状结构,而非传统的树状层级。
### 什么是双向链接?
当笔记 A 链接到笔记 B 时,B 会自动显示反向链接。

### 如何创建?
1. 输入 `[[` 触发建议
2. 选择目标笔记
3. 按 Enter 确认

## 二、本地存储
所有文件以 Markdown 格式存储在本地。

输出 Canvas
{
"nodes": [
{
"id": "group-双向链接",
"type": "group",
"label": "一、双向链接",
"x": 0,
"y": 0,
"width": 850,
"height": 700,
"color": "4"
},
{
"id": "text-intro",
"type": "text",
"text": "双向链接让笔记形成网状结构,而非传统的树状层级。",
"x": 50,
"y": 50,
"width": 750,
"height": 60
},
{
"id": "text-what",
"type": "text",
"text": "### 什么是双向链接?\n\n当笔记 A 链接到笔记 B 时,B 会自动显示反向链接。",
"x": 50,
"y": 130,
"width": 350,
"height": 120
},
{
"id": "img-00-36",
"type": "file",
"file": "<输出目录名>/screenshots/00-36.jpg",
"x": 50,
"y": 270,
"width": 350,
"height": 220
},
{
"id": "text-how",
"type": "text",
"text": "### 如何创建?\n\n1. 输入 `[[` 触发建议\n2. 选择目标笔记\n3. 按 Enter 确认",
"x": 450,
"y": 130,
"width": 350,
"height": 120
},
{
"id": "img-00-48",
"type": "file",
"file": "<输出目录名>/screenshots/00-48.jpg",
"x": 450,
"y": 270,
"width": 350,
"height": 220
},
{
"id": "group-本地存储",
"type": "group",
"label": "二、本地存储",
"x": 950,
"y": 0,
"width": 500,
"height": 450,
"color": "5"
},
{
"id": "text-local",
"type": "text",
"text": "所有文件以 Markdown 格式存储在本地。",
"x": 1000,
"y": 50,
"width": 400,
"height": 60
},
{
"id": "img-01-16",
"type": "file",
"file": "<输出目录名>/screenshots/01-16.jpg",
"x": 1000,
"y": 130,
"width": 400,
"height": 280
}
],
"edges": [
{
"id": "edge-1",
"fromNode": "text-what",
"toNode": "img-00-36",
"fromSide": "bottom",
"toSide": "top"
},
{
"id": "edge-2",
"fromNode": "text-how",
"toNode": "img-00-48",
"fromSide": "bottom",
"toSide": "top"
},
{
"id": "edge-3",
"fromNode": "text-local",
"toNode": "img-01-16",
"fromSide": "bottom",
"toSide": "top"
}
]
}
验证清单
生成 Canvas 后检查:
- [ ] 所有节点 ID 唯一
- [ ] Edge 引用的节点存在
- [ ] 图片路径有效(相对路径)
- [ ] 无节点重叠
- [ ] JSON 格式正确
- [ ] Group 正确包含子节点
Atomiseur de Contenu
Contenu
Transforme un contenu unique en publications adaptées à chaque plateforme.
Rédacteur de Blog SEO
Contenu
Rédige des articles de blog optimisés SEO avec structure et mots-clés.
Scénariste YouTube
Contenu
Écrit des scripts YouTube engageants avec hooks, structure et rétention.