去年年中,我写了一篇文章,说明在当下这个时代,学会刷短视频是一种非常高效的获取信息的方式。但问题是,短视频这一媒介的初衷是娱乐与沉迷,因此在对它进行知识管理的时候存在很多困难,现有的 PKM 系统也几乎都不支持短视频平台或短视频形态的对接。
为了证明在将短视频纳入知识管理系统后能够大大增强知识库的范围,我在今年 11 月搭建了一套自动化的短视频 PKM 方案。它可以实现:
手机端一键操作后,将短视频自动备份到存储桶,并利用 AI 对短视频内容概述,抽取标签,有效信息,并写入 notion。
效果图12316×1416 430 KB
效果图21666×1688 279 KB
效果图31798×1470 222 KB
如此一来,后续就可以使用 notion 将短视频与其他文章、论文等收藏项目进行统一管理、搜索。如果你还是 notion AI 用户,那更是可以在 notion AI 中直接与你的视频知识库进行对话。
但是,这个方案对于普通人来说可能门槛较高。接下来,就让我们一步一步来搭建这个系统。
Workflow 下载:
短视频PKM 自动化.json (18.9 KB)
短视频 PKM 删除视频.json (2.2 KB)
如果你想用单一大模型出音频转写文字,不想单独配置一个 Whisper,可以使用这个版本:
视频PKM 无Whsiper 版本.json (16.9 KB)
直接下载必不能用,请导入后跟着教程一步一步理解。
整体步骤:首先,我们先来大致的浏览一下整个工作流的整体步骤。在理解了整体步骤之后,如果其中每个步骤的具体方法,你都可以用你更熟悉的方式进行替换。
步骤
解释
具体方法
1. 获取抖音视频
将抖音 App 下载的视频转移到一个单独的目录等待触发整个流程。
Android 手机+Tasker
2. 将短视频同步到私有云
将短视频同步到 n8n 所属的服务器,以触发 n8n 对应的 Workflow。
群晖 NAS + Synology Drive
3. 上传短视频到 Google
将短视频上传到 Gemini File 暂存服务等待下一步使用 Gemini 对视频分析。
n8n + Google Gemini API Key
4. 短视频内容分析
将短视频按照提前定制好的 Prompt 进行信息提取,获得可存入 PKM 的文字内容。
n8n + Google Gemini API Key
5. 信息入库
将私有云的视频连接、Gemini 返回的可用于搜索和归档的文字信息写入 notion。
n8n + notion API
6. 文本转写
如果 Gemini 认为视频中的音轨值得全文转写,调用 Whsiper API 对视频进行音频文本转写。
LemonFox 账号
如果你没有替换各步骤中具体方法的能力,希望一比一的复刻这一方案,那么你就需要满足以下的使用条件。
必选项:
一台 Android手机;
Tasker 付费版;
一个群晖 NAS 或一个 VPS(不建议用 VPS,因为视频要存在这里,没两天就要用 1GB 空间);
Google 账号;
可自由访问互联网,且你的群晖也可以自由访问互联网,并且不能是香港 IP;
除此之外,还建议你准备:
一个域名(二级也可以);
CloudFlare账号;
可跨境支付的信用卡;
满足以上所有条件之后,我们现在可以开始一步一步的搞了。
具体步骤 第一步:获取抖音视频抖音的反扒非常牛逼,因此我们的工作流完全不考虑直接从抖音服务器获取任何信息。但是,抖音 App 是允许直接下载短视频的,这一步骤是你手工操作,完全在抖音的允许范围之内。
image1440×3088 267 KB
因此,这一步骤的基础思路是:
你自己在抖音中选择“下载视频”;
2. 需要一个工具,持续运行在手机上,监控下载到的视频,识别并标记等待后续处理;
根据这个思路,我们可以清晰的意识到,在 iPhone 上是做不到的,只有 Android 可以。而在 Android 上,又有一个现成的老牌自动化工具叫 Tasker。
在安装好 Tasker 的付费版之后,我们在 Profiles 界面新建一个 Event,选择 File Modifed。然后 File 选择手机的相机目录,Event 选择 Create。抖音会默认将视频下载到这个目录。不同手机的目录地址可能不一样,这个你需要根据自己的情况进行调整。这一步设置好之后,相当于设定了一个触发器,每当相机目录新增文件的时候,会触发 Tasker 的任务。
配置参考如图:
image1440×3088 137 KB
但是,我们的相机目录里大部分其实是照片和自己拍摄的视频,我们应当只对抖音视频进行操作,因此,我们接下来要新建一个 Tasks(任务),这个任务要执行以下操作:
读取新增文件的文件名,判断它是否是抖音下载视频,如果是则继续。
获取文件地址;
将文件移动到指定的单独文件夹;
弹个通知;
Tasker 的语法比较奇葩,我摸索了一番,它的配置应该大致是这样的:
image1440×3088 222 KB
其中第一步 if 的逻辑是,读取触发器传递过来的文件地址(%evtprm1),看看里面是否包含 share_(share_)。
最关键的一步,移动到单独目录的配置是这样的:
image1440×3088 201 KB
这个 %evtprm17 是取文件地址后 17 位的一个变量,如果以后抖音的下载视频文件名位数变了要改这里。
在开启 Tasker 的任务之前,你还要去手机文件 App 里创建一下那个单独的目录。如果你是按照我的截图配置的,那么就需要在手机的内置存储中创建一个叫 DouyinSync 的文件夹。
好,至此我们就完成了第一步,你可以尝试一下你在抖音 App 里下载一个视频,看看是否会被移动到你单独创建的那个 DouyinSync 里。如果成功,那么这一步就成功了。
第二步: 将短视频同步到私有云如果你和我一样用群晖,那这一步会非常简单。
首先,你要在群晖上启用 Synology Drive,也就是群晖网盘,一般这个是默认启用的。
然后,你需要在群晖的 【控制面板】>【共享文件夹】中新建一个共享文件夹用于存放我们的抖音视频,在这里,我取名叫“Douyin转储”:
image882×466 20 KB
第三步,我们在手机端上下载群晖的 Synology Drive,然后创建一个单向同步任务(也就是只把手机文件传上去),配置可以参考我的:
image1440×4322 337 KB
完成这些配置之后,你可以继续测试一下,在抖音里下载一个短视频,是否会自动传到群晖的对应目录里。
这一步可能的坑是,无论 Tasker 或手机端的群晖 Drive 都可能被手机杀后台。你需要根据你的手机系统,给这两个 App 开后台常在权限。
第三步:设置公开访问地址为了让 Notion 和 LemonFox 等外部服务能够访问到存储在群晖 NAS 上的视频文件,我们需要为其配置一个可以通过互联网访问的公开 URL 地址。这主要涉及两个步骤:启用 Web 服务和设置 DDNS。
1. 安装并启用 Web Station
登录你的群晖 DSM 桌面。
打开“套件中心”(Package Center)。
搜索并安装“Web Station”套件。
安装完成后,打开 Web Station。
2. 配置 Web Station 以访问视频文件夹
我们需要让 Web Station 能够提供对“Douyin转储”共享文件夹中文件的访问。一种方法是创建一个虚拟主机或使用默认 Web 目录的子目录。这里以创建一个简单的别名指向共享文件夹为例:
image1764×1336 169 KB
在 Web Station 中,转到“网页服务”,选择新增。
选择“静态网站”,点击“下一步”。
“文档根目录”选择第二步创建的共享文件夹,再点击下一步。
完成“创建”。
image1354×1086 60 KB
在 Web Station 中,转到“网页门户”,选择新增。
服务选择刚刚创建的静态网站。
设置一下你要使用的域名和端口。
3. 设置 DDNS (动态 DNS)
由于家庭宽带的公网 IP 地址通常是动态变化的,我们需要 DDNS 服务将一个固定的域名指向你动态变化的公网 IP。
在群晖 DSM 中,打开“控制面板”(Control Panel)。
转到“外部访问”(External Access)。
选择“DDNS”选项卡。
点击“新增”(Add)。
服务提供商 : 选择一个 DDNS 服务提供商。群晖内置支持一些免费和付费的提供商(如 Synology、DNSPod、Cloudflare 等)。如果你有自己的域名,推荐使用 Cloudflare 或你的域名注册商提供的 DDNS 服务。
主机名称/域名 : 输入你准备好的域名(例如 mynas.mydomain.com )。
用户名/电子邮件 & 密码/密钥 : 根据所选服务提供商的要求,输入你的账户信息或 API Key。
勾选“启用 DDNS 支持”(Enable DDNS support)。
点击“测试联机”(Test Connection) 确保配置正确。
点击“确定”(OK)。
整个第三步基于你对群晖 Web Station 和 DDNS 的理解,如果你搞不定的话,可以稍微搜一下。网上的公开教程非常多,你只需要调通,让一个外部域名能访问你收藏到 NAS 的视频即可。
第四步:上传短视频到 Google从这一步开始,我们需要使用开源低代码自动化平台 n8n。如果你还不知道 n8n 是什么,你可以在 n8n 中文教程 里重头开始学。
你需要至少完成 n8n 在群晖中的部署,才可以继续进行这一步的操作。 如果你已经在群晖中部署了 n8n,那么请直接下载这个 Workflow:
短视频PKM 自动化.json (18.9 KB)
导入你的 n8n ,这样可以省去第三步开始的大部分工作。如果无法正常运行,你可以照着这个教程一步一步检查。导入后请务必检查并替换所有 API Key、Notion Database ID 和 URL 地址为你自己的配置。
本教程是基于 Workflow 的编制进行撰写的,现在我们来看具体的 n8n 配置:
image2060×1284 266 KB
1. 初始设置 (Set Node - 初始设置)
image1372×1594 147 KB
在 Workflow 的最开始,建议添加一个 Set 节点,用于统一存放需要用到的 API Key 和配置信息。这样方便后续修改。
Gemini-Key: 你的 Google Gemini API Key。
LemonFox-Key: 你的 LemonFox API Key (如果需要转写功能)。
存储桶域名: 你配置的用于公开访问群晖中视频文件的域名地址(例如 https://your-domain.com/videos/)。确保这个地址可以从公网访问到对应的视频文件。
2. 检测新视频 (Local File Trigger Node - 检测新视频)
image1236×1510 63.7 KB
这个节点是 Workflow 的起点。
Trigger On: 选择 Folder。
Path: 设置为 n8n 可以访问到的、群晖上存储抖音视频的文件夹路径。在 Workflow 文件中是 /home/node/DouYin/,你需要根据你的实际 n8n 部署和群晖文件夹映射进行修改。
Events: 选择 add,表示当有新文件添加到该目录时触发。
Options: 勾选 Await Write Finish,确保文件完全写入后再触发。
3. 读取新视频 (Read Binary File Node - 读取新视频)
image1090×1620 67.3 KB
当触发器检测到新文件时,这个节点会读取该文件的二进制内容。
File Selector: 使用表达式 {{ $json.path }} 来获取触发器传递过来的文件路径。
4. 上传视频到 Google (HTTP Request Node - 上传视频到Google)
image1214×1556 94.5 KB
这一步是将视频文件上传到 Google Gemini 的 File API,以便后续进行分析。Gemini API 处理视频需要先上传文件,而不是直接发起大模型请求。
Method: POST
URL: 使用表达式构建 URL,注意替换 Key 为你自己的。
=https://generativelanguage.googleapis.com/upload/v1beta/files?key={{ $('初始设置').params.assignments.assignments[0].value }}这里的 $('初始设置').params.assignments.assignments[0].value 是引用了 “初始设置” 节点中定义的 Gemini Key。
Send Headers: On
X-Goog-Upload-Command: start, upload, finalize
X-Goog-Upload-Header-Content-Length: {{ $json.fileSize }} (从上一步读取文件节点获取)
X-Goog-Upload-Header-Content-Type: {{ $json.mimeType }} (从上一步读取文件节点获取)
Send Body: On
Content Type: multipart-form-data
Body Parameters:
file: ="display_name": "{{ $json.fileName }}" (设置在 Google 端的文件名)
Parameter Type: Form Binary Data, Name: {{ $json.fileName }}, Input Data Field Name: data (将上一步读取到的文件二进制数据作为 Body 发送)
5. 等待视频处理 (Wait Node - 等待 & HTTP Request Node - 获取视频准备状态 & If Node - 判断视频准备状态)
image1248×436 31.1 KB
上传视频到 Google File API 后,Google 需要一些时间来处理视频,然后才能用于分析。我们需要轮询检查视频状态。
等待 (Wait Node): 设置一个初始等待时间,例如 30 秒。
获取视频准备状态 (HTTP Request Node):
Method: GET
URL: 使用表达式构建,引用上一步上传操作返回的文件名 (file.name) 和你的 API Key。
=https://generativelanguage.googleapis.com/v1beta/{{ $('上传视频到Google').item.json.file.name }}?key={{ $('初始设置').params.assignments.assignments[0].value }}Send Headers: On, Content-Type: application/json
判断视频准备状态 (If Node):
检查上一步获取状态请求返回的 JSON 数据中 state 字段的值。
Condition: {{ $json.state }} String Equals ACTIVE
如果 state 等于 ACTIVE,则流程继续到下一步(输出 0 / true)。
如果 state 不等于 ACTIVE,则流程回到 等待 节点,再次等待后查询(输出 1 / false)。将此节点的 false 输出连接回 等待 节点。
第五步:短视频内容分析当视频状态变为 ACTIVE 后,我们调用 Gemini API 进行内容分析和信息提取。
1. AI 分析视频 (HTTP Request Node - AI分析视频)
image1016×1632 80.4 KB
由于 n8n 默认的 AI 节点不支持手工上传文件,所以这里我们要使用 HTTP Request 发起一个自定义的 Gemini 请求,它的设置如下:
Method: POST
URL:
https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent我这里使用了 gemini-2.0-falsh-exp,如果你想用别的模型可以自己替换。
Send Query Parameters: On
key: {{ $('初始设置').params.assignments.assignments[0].value }} (你的 Gemini API Key)
Send Headers: On
Content-Type: application/json
Send Body: On
Specify Body: JSON
JSON Body: 这里是核心的 Prompt 和输出格式定义。你需要将 Google File API 返回的视频 uri 填入 fileData 部分,并提供详细的指令告诉 Gemini 如何分析视频并以 JSON 格式返回结果。
={ "contents": [ { "role": "user", "parts": [ { "fileData": { // 引用上一步获取状态成功后返回的视频 URI "fileUri": "{{ $json.uri }}", "mimeType": "video/mp4" } } ] }, { "role": "user", "parts": [ { // 你的 Prompt 指令 "text": "请提取视频信息,并按照结构进行输出。" } ] } ], "generationConfig": { "temperature": 1, "topK": 40, "topP": 0.95, "maxOutputTokens": 8192, // 要求 Gemini 返回 JSON 格式 "responseMimeType": "application/json", // 定义期望的 JSON Schema "responseSchema": { "type": "object", "properties": { "抖音号": { "type": "string", "description": "画面中出现的一串抖音号数字或字母" }, "抖音名": { "type": "string", "description": "画面中出现的一串文字,代表该抖音账号的名称/昵称。它出现的位置通常靠近抖音号,并且以一个放大镜符号开始,如未发现则输出‘未知’" }, "视频标题": { "type": "string", "description": "画面结尾搜索框出现的一串文字" }, "视频描述": { "type": "string", "description": "300 字左右的视频描述" }, "视频标签": { "type": "array", "description": "概括视频所需的标签列表", "items": { "type": "string" } }, "场景标签": { "type": "array", "description": "尽可能详细描述视频场景的标签列表", "items": { "type": "string" } }, "对象标签": { "type": "array", "description": "描述视频中出现的物品、动物、人物、建筑等的标签列表", "items": { "type": "string" } }, "台词转写": { "type": "boolean", "description": "判断此视频是否需要进行台词转写,对于段子、搞笑、超短视频(小于60秒)等台词信息价值不高,或音频只有音乐、歌曲的视频返回 false;对于解说、科普、长视频等台词信息价值高的视频返回 true。" } }, "required": [ /* ... 列出所有必须的字段 ... */ ] } } }请仔细检查并根据需要调整 Prompt 和 Schema 定义,除此之外,你还可以通过修改请求 URL 来更换模型
2. 数据改刀 (Set Node - 数据改刀)
image992×1086 42.6 KB
Gemini 返回的 JSON 数据嵌套在几层结构里,我们需要用 Set 节点将其提取出来,方便后续使用。
Mode: Raw JSON Output
JSON Output: {{ $json.candidates[0].content.parts[0].text }} (提取 Gemini 返回的 JSON 文本)
Options: 确保 Parse as JSON 被勾选,这样输出的就是一个可以直接使用的 JSON 对象。
第六步:信息入库将 Gemini 分析得到的信息写入你的 Notion 数据库。你需要首先从我这里复制一个用于存放短视频的 Notion 视频库模板。
然后,回到 n8n 开始操作。
1. 创建页面 (Notion Node - 创建页面)
image954×1638 79.6 KB
Resource: Database Page
Operation: Create
Database ID: 选择或填入你用于存储视频信息的 Notion Database ID。
Title: 使用表达式 {{ $json['视频标题'] }} (引用上一步 “数据改刀” 节点输出的 JSON 中的 视频标题 字段)。
Properties: 点击 Add Property,将 “数据改刀” 节点输出的各个字段映射到 Notion 数据库对应的属性上。例如:
场景标签 (Multi-Select): {{ $json['场景标签'] }}
对象标签 (Multi-Select): {{ $json['对象标签'] }}
抖音号 (Select 或 Text): {{ $json['抖音号'] }}
视频描述 (Text): {{ $json['视频描述'] }}
视频标签 (Multi-Select): {{ $json['视频标签'] }}
文件名 (Text): {{ $('读取新视频').item.json.fileName }} (引用之前读取文件节点的原始文件名)
抖音名 (Select 或 Text): {{ $json['抖音名'] }}
Block: 可以添加一些固定的内容块,比如一个标题。
Add Block → Heading 2 → Text Content: 原视频:
2. 添加视频预览 (HTTP Request Node - 添加视频预览)
image1000×1596 78.7 KB
这一步是在新创建的 Notion 页面下方追加一个视频嵌入块,方便直接在 Notion 中预览。在这一步,我们插入的是你 Nas 里存储的视频,而不是抖音原视频,这确保了原始抖音视频被删除,你依然可以找回你的视频。
Method: PATCH
URL: 使用表达式构建,引用上一步 “创建页面” 节点返回的页面 ID ($json.id)。
=https://api.notion.com/v1/blocks/{{ $json.id }}/childrenAuthentication: Predefined Credential Type, Credential Type: Notion API (选择你配置好的 Notion 凭证)
Send Body: On
Specify Body: JSON
JSON Body: 构建追加 Embed Block 的请求体。
={ "children": [ { "object": "block", "type": "embed", "embed": { // 拼接视频的公开访问 URL "url": "{{ $('初始设置').params.assignments.assignments[2].value + $('读取新视频').item.json.fileName }}" } } ] }这里的 $(‘初始设置’).params.assignments.assignments[2].value 引用了 “初始设置” 节点中定义的存储桶域名。$(‘读取新视频’).item.json.fileName 引用了原始文件名。确保拼接后的 URL 是有效的、可以公开访问的视频链接。
第七步:文本转写 (可选)根据 Gemini 的判断,如果视频包含有价值的语音内容,则调用外部服务进行语音转文字。这里使用了 LemonFox 作为 Whisper API 的代理服务。
1. 判断是否要加台词 (If Node - 判断是否要加台词)
image1800×976 51.1 KB
检查 “数据改刀” 节点输出的 JSON 中 台词转写 字段的值。
Condition: {{ $('数据改刀').item.json["台词转写"] }} Boolean is true
如果为 true,则流程继续进行转写(输出 0 / true)。
如果为 false,则流程结束(输出 1 / false)。
2. 写入台词标题 (Notion Node - 写入台词标题)
image1020×1624 76.1 KB
如果需要转写,先在 Notion 页面追加一个“音频文本”的标题。
Resource: Block
Operation: Append
Block ID: 使用表达式引用 “创建页面” 节点返回的页面 ID: {{ $('创建页面').item.json.id }}
Block: Add Block → Heading 2 → Text Content: 音频文本
3. 提交视频到 LemonFox (HTTP Request Node - 提交视频到LemonFox)
image1074×1660 83 KB
将视频提交给 LemonFox 进行异步转写。
Method: POST
URL: https://api.lemonfox.ai/v1/audio/transcriptions
Send Headers: On
Authorization: Bearer {{ $('初始设置').params.assignments.assignments[1].value }} (引用 “初始设置” 节点中的 LemonFox Key)
Send Body: On
Content Type: multipart-form-data
Body Parameters:
response_format: text
file: {{ $('初始设置').params.assignments.assignments[2].value + $('读取新视频').item.json.fileName }} (提供视频的公开访问 URL,替换为你自己的域名和路径)
callback_url: {{ $execution.resumeUrl }} (这是关键,让 LemonFox 完成转写后回调 n8n 的这个 Webhook 地址,以继续执行流程)
4. 等待 LemonFox 回调 (Wait Node - 等待LemonFox)
image1014×1642 75.7 KB
这个节点会暂停 Workflow 的执行,直到 LemonFox 通过上一步设置的 callback_url 发送回请求。
Resume: Webhook
HTTP Method: POST (根据 LemonFox 的回调方式可能需要调整)
5. 写入台词 (Notion Node - 写入台词)
image982×1664 80.4 KB
当 LemonFox 回调时,它会将转写结果放在请求的 Body 中。这个节点将收到的文本追加到 Notion 页面。
Resource: Block
Operation: Append
Block ID: 同样引用 “创建页面” 节点返回的页面 ID: {{ $('创建页面').item.json.id }}
Block: Add Block → Text → Text Content: {{ $json.body }} (假设 LemonFox 将文本放在回调请求的 body 中,如果不是,需要根据实际回调数据结构调整表达式)
可以勾选 Code 格式化选项,让转写文本以代码块形式显示。
至此,整个 n8n Workflow 的配置就讲解完毕了。你需要根据自己的实际情况,替换掉 Workflow 中的 API Key、Notion Database ID、文件路径、公开访问域名等信息。
在配置完成后,激活这个 Workflow。之后,每当你通过 Tasker 将抖音下载的视频移动到指定文件夹,Synology Drive 将其同步到群晖,n8n 就会自动触发这一系列流程,最终将视频信息和(可选的)转写文本存入你的 Notion 知识库。
删除视频短视频 PKM 删除视频.json (2.2 KB)
这个 Workflow 还支持从 notion 删除视频时(使用删除按钮),自动删除 NAS 中的原始视频文件。
你只需将这个 Workflow 导入到你的 n8n 并激活。然后,将 Webhook 地址填写到你的 Notion 短视频数据库“删除”按钮那一列的自动化里就行了。
这个 Workflow 很简单,不做过多结束了。
在充分理解了这个 Workflow 之后,你可以试着将触发修改为其他方式。
比如,如果你没有群晖的话,可以用 Google Drive 或 One Drive 等公共云盘来代替,也就是每次下载抖音短视频后,将这些短视频自动同步到公有云盘。然后在 n8n 里,用 Google Drive 或 OneDrive 节点来触发整个工作流。
但这样的话,后续向 Notion 提交内容的节点要稍作调整,因为 Notion 可能不支持嵌入这些公有云盘里的文件,而只支持插入超链接。
另外,如果你想要用一个 Chat Trigger 触发也是可以的,比如发送一个抖音链接,就完成自动抓取、分析、存入 Notion。你只需要一个额外的第三方服务 TikHub。