# Douyin Transcript Exporter

> 必须在豆包工作中执行，抓取抖音博主主页或视频的标题、文案、完整逐字稿及互动数据；可选写入飞书多维表格，或保存为本地文件。当用户要采集或导出抖音视频数据、逐字稿时使用。

- Skill: `jinchenma94/douyin-transcript-exporter` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add jinchenma94/douyin-transcript-exporter`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jinchenma94/douyin-transcript-exporter/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: jinchenma94 (https://skillmd.com/u/jinchenma94)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jinchenma94/douyin-transcript-exporter

---


# 抖音逐字稿导出

## 执行环境

必须在豆包工作中执行，并使用其内置的逐字稿获取能力。需要采集抖音主页公开信息时，可通过豆包工作的内置浏览器登录抖音；建议使用专门的小号。该登录仅用于读取公开主页的视频信息，不用于下载视频，也不影响逐字稿获取。

## 输入

| 输入项 | 必填 | 说明 |
|--------|------|------|
| 抖音博主主页 URL 或 单条视频 URL | 是 | 博主主页 `https://www.douyin.com/user/xxxxx`，或单条视频 `https://www.douyin.com/video/xxxxx`，或抖音分享短链 |
| 飞书多维表格 URL | 否 | wiki 链接或 base 链接，含 table 参数。**用户未提供时必须主动询问；用户明确表示不用表格时，保存到本地 JSON/CSV 文件** |
| 视频数量 | 否 | 默认最新 5 条；用户说"最新N条"时只采前N条 |
| 是否提取逐字稿 | 否 | 默认提取；用户说"只要基础数据"时跳过 |

## 采集字段（标准9列 + AI扩展2列）

**基础采集字段（9列，从抖音页面直接抓取）：**
账号名称（单选）、标题、介绍、逐字稿、点赞、评论、转发、发表日期、视频链接

**AI扩展字段（2列，基于逐字稿由AI生成）：**
- 选题方向（多选 select）：从预设标签中选择1-3个，如 AI协作方法、AI入门教程、企业AI落地、认知思维、提示词工程、个人成长、效率工具、数字化转型、学习方法、AI管理 等。若目标表格已有该字段的选项，必须从已有选项中选择，不自行新增。
- 主题总结（text）：用一句话（30-80字）概括视频核心观点或内容主旨，要求精准、不重复标题、提炼本质。

> 用户说"只要基础数据"时跳过AI扩展字段；目标表格不存在这两个字段时跳过（不自动创建扩展字段，除非用户明确要求）。

## 执行流程

### Step 0：前置检查与询问（必须先执行）

在开始任何采集操作之前，必须检查用户是否提供了以下必要信息，缺失时**必须主动向用户询问**，不得自行假设或跳过：

1. **检查抖音来源地址**：
   - 用户是否提供了博主主页 URL、单条视频 URL、或抖音分享短链？
   - **未提供时**：向用户询问"请问要采集哪个抖音博主的视频？请提供博主主页链接或视频链接。"
   - 提供了分享短链（如 `https://v.douyin.com/xxxxx/`）时，先用浏览器打开短链，获取跳转后的真实 URL（博主主页或视频详情页）。

2. **检查飞书多维表格地址**：
   - 用户是否提供了飞书多维表格 URL（wiki 链接或 base 链接）？
   - **未提供时**：向用户询问"请问采集结果要写入哪个飞书多维表格？请提供表格链接。如果不需要写入表格，我可以保存到本地文件。"
   - **用户明确表示不用表格 / 保存到本地**时：跳过分支，采集完成后将结果保存为本地 JSON 和 CSV 文件（见 Step 4 本地保存分支）。
   - **用户提供了表格地址**时：继续正常流程，写入飞书表格。

3. **确认其他可选参数**：
   - 视频数量：用户说"最新N条"时只采前N条，未说明时默认最新 5 条。
   - 是否提取逐字稿：用户说"只要基础数据"时跳过，未说明时默认提取。

4. **信息齐全后再开始**：以上必要信息确认齐全后，才进入 Step 1 环境检测。信息不齐全时不得开始采集。

### Step 1：环境检测

1. **检测 lark-cli 身份**：运行 `lark-cli api GET /open-apis/authen/v1/user_info --as user`，确认登录的是用户本人账号（而非沙箱自带的"来点羊蝎子"等测试账号）。
   - 如果沙箱 lark-cli 无权限，尝试系统路径的 lark-cli：Mac 上 `/opt/homebrew/bin/lark-cli`，Windows 上 `where lark-cli` 查找。
   - 两种身份都无权限时，告知用户需要先在飞书文档中授权或切换 lark-cli 登录账号。

2. **检测操作系统**：Mac 用 `mac_computer_use_tool`（plane="bu"），Windows 用 `computer_use_tool`（plane="bu"）。两者代码逻辑完全一致，均为 `import seed_browser_use as bu`。

### Step 2：抖音视频采集

读取 `references/douyin.md` 获取采集细节。核心步骤：

1. 用浏览器打开博主主页，检测是否已登录抖音。
   - 未登录时（页面显示登录弹窗、作品列表显示"服务异常"），调用 `interaction.request_action`（type="browserControl"）请求用户接管完成登录。
   - 登录后等待作品列表加载完成。

2. 滚动页面加载全部视频，从 DOM 中提取所有视频链接（`/video/xxxxx` 格式）和基础信息。
   - 主页文本中可直接获取每条视频的标题、文案、点赞数。
   - 用户指定"最新N条"时，只取前N个。

3. 逐个进入视频详情页（`https://www.douyin.com/video/xxxxx`），提取：
   - 评论数、转发数、收藏数（页面互动区数字，顺序：点赞→评论→收藏→转发）
   - 发表日期（页面底部"发布时间：YYYY-MM-DD HH:MM"）
   - 博主昵称（页面顶部作者信息）

4. 汇总为结构化数据列表，每条包含：video_id、url、title、description、likes、comments、shares、publish_date、author_name。

### Step 3：逐字稿提取（默认执行）

对每条视频链接调用 `web.fetch`，抖音页面会返回视频的完整口播逐字稿。

**【强制要求】必须获取完整逐字稿，禁止写任何占位符说明（如"完整内容已通过web.fetch获取"）。如果获取失败，该字段留空并标注失败原因，绝不能用占位文字冒充完整内容。**

1. **调用 web.fetch**：首次调用使用 `pagination.offset=0`，从返回结果中检查 `pagination_content` 的 `end_offset` 和 `total_length`。
   - 如果 `end_offset < total_length`，说明内容被截断，**必须继续分页读取**：下一次调用设置 `pagination.offset = 上一次的 end_offset`，重复直到 `end_offset >= total_length`。
   - 将所有分页返回的内容拼接为完整文本。

2. **分离逐字稿正文**：从完整内容中分离标题/文案部分和逐字稿正文部分（逐字稿正文通常在第一个空行之后）。

3. **内容完整性判断**（满足任一条件即视为不完整，必须回退）：
   - 逐字稿正文长度 < 50 字（短视频口播通常至少几十字）
   - 内容在句子中间突然中断（末尾不是句号/问号/感叹号/省略号等结束标点）
   - 返回内容中包含"完整内容"、"web.fetch"、"获取"等占位符文字
   - web.fetch 调用失败或返回空内容

4. **回退路径**：内容不完整时，回退到飞书妙记链路：先加载 `doubao-video-extract` skill，确认脚本路径后运行 `python3 scripts/minutes/social_video_to_minutes.py "<url>" --run-lark`。
   - 此方法会下载视频音频 → 上传飞书妙记 → 转写，耗时较长（每条1-3分钟）。
   - 回退仍失败时，逐字稿字段留空，在结果摘要中标注该条逐字稿获取失败。

5. 用户明确说"不要逐字稿"时跳过本步，逐字稿字段留空。

### Step 3.5：AI生成选题方向与主题总结（默认执行，需目标表格含对应字段）

基于每条视频的**标题 + 介绍 + 逐字稿**，由AI批量生成两个扩展字段：

1. **选题方向（多选）**：
   - 先用 `lark-cli base +field-list` 读取目标表格"选题方向"字段的已有选项列表。
   - 必须从已有选项中选择1-3个最贴合的标签，**禁止自行新增选项**。
   - 选择标准：视频核心主题落在哪个领域，优先选最主要的1个，次选相关的1-2个。
   - 若目标表格无"选题方向"字段，跳过本字段。

2. **主题总结（text）**：
   - 用一句话（30-80字）概括视频核心观点或内容主旨。
   - 要求：精准提炼本质，不重复标题原文，不写"这条视频讲了…"这类废话开头。
   - 若视频是纯分享/开箱/生活类，概括其核心信息或感受。

3. **执行方式**：
   - 将所有视频的标题、介绍、逐字稿整理为结构化列表，一次性交给AI批量生成，避免逐条调用浪费上下文。
   - 逐字稿截断策略：短视频（逐字稿<1500字）使用完整内容；长视频（逐字稿>1500字）可截断至前2000字（而非1000字），确保涵盖视频核心观点。若视频内容在开头铺垫较多，可适当增加截断长度。
   - 输出格式为 JSON：`[{"video_id":"xxx","选题方向":["标签A","标签B"],"主题总结":"..."},...]`
   - 生成后与原始数据合并，准备写入。

> 用户说"只要基础数据"或目标表格不含这两个字段时，跳过本步。

### Step 4：结果写入（飞书表格 / 本地文件）

根据 Step 0 中用户的选择，分为两个分支：

#### 分支 A：写入飞书多维表格（用户提供了表格地址时）

读取 `references/lark-write.md` 获取写入细节。核心步骤：

1. **解析表格链接**：`lark-cli base +url-resolve --url "<表格URL>" --as user`，获取 base_token、table_id、view_id。
   - wiki 链接也可直接解析，无需手动转换。

2. **对比字段**：`lark-cli base +field-list --base-token <token> --table-id <id> --as user`，检查目标表格是否包含全部基础9字段。
   - 缺失基础字段自动创建：账号名称用 `select`（单选，multiple=false），标题/介绍/逐字稿/视频链接用 `text`，点赞/评论/转发用 `number`，发表日期用 `datetime`。
   - 批量创建字段用数组形式：`--json '[{"name":"xxx","type":"xxx"},...]'`。
   - **AI扩展字段（选题方向、主题总结）**：若目标表格已存在则纳入写入；若不存在则**不自动创建**（除非用户明确要求），直接跳过这两个字段的写入。
   - 若"选题方向"字段存在，必须先读取其已有选项列表，AI生成时严格从已有选项中选择。

3. **增量去重**：查询表格中已有的"视频链接"字段值列表，与本次采集的视频链接对比，只写入不存在的新记录。
   - 用 `lark-cli base +record-list` 或 `+record-search` 获取已有记录。
   - 用户明确要求"全量覆盖"时跳过去重，直接追加。

4. **批量写入**：用 `lark-cli base +record-batch-create` 一次性写入新记录（单批最多200条）。
   - 日期字段用 `"YYYY-MM-DD HH:MM"` 字符串格式，或毫秒时间戳。
   - 单选字段（账号名称）用 `["选项名"]` 数组格式。
   - 写入后返回 record_id_list，确认写入成功数量。

5. **数据质量验证**（写入后必须执行）：
   - 用 `lark-cli base +record-list` 读取本次新写入的记录，检查以下质量问题：
     - **占位符检查**：逐字稿字段中是否包含"完整内容"、"web.fetch"、"已通过"等占位符文字（如有说明写入时内容不完整，必须重新获取并更新）
     - **长度检查**：逐字稿字段是否过短（<50字且非纯音乐/无口播视频）、标题/介绍字段是否为空
     - **关键字段检查**：视频链接、发表日期、账号名称是否正确写入
   - 发现质量问题时，立即重新获取该条数据并用 `+record-batch-update` 更新对应记录，直到验证通过。

#### 分支 B：保存到本地文件（用户明确表示不用表格时）

用户在 Step 0 中明确表示不用飞书表格时，将采集结果保存为本地文件，采用**每批单独目录 + 每个视频单独 Markdown 文件**的结构：

1. **批次目录**：在当前工作目录下创建 `douyin_data/` 文件夹，每批采集单独建一个子目录。
   - 目录命名：`{博主昵称}_{采集日期YYYYMMDD}_{视频数量}条/`，如 `瑶瑶_20260827_50条/`
   - 博主昵称含特殊字符时，替换为下划线或去掉特殊字符。

2. **每个视频单独 Markdown 文件**：目录下为每条视频创建一个 `.md` 文件。
   - 文件命名：`{序号}_{视频ID}.md`，如 `01_7655189977860862854.md`、`02_7654993145986808761.md`
   - 序号按采集顺序（最新在前）从 01 开始，不足10条用1位，超过99条用3位。
   - Markdown 文件内容格式：
     ```markdown
     # {视频标题}

     ## 基本信息
     - **账号名称**：{博主昵称}
     - **发表日期**：{YYYY-MM-DD HH:MM}
     - **视频链接**：{url}
     - **点赞**：{点赞数}
     - **评论**：{评论数}
     - **转发**：{转发数}

     ## 介绍/文案
     {视频介绍或文案全文}

     ## 选题方向
     {标签1}、{标签2}、{标签3}

     ## 主题总结
     {一句话主题总结}

     ## 逐字稿
     {完整口播逐字稿全文}
     ```

3. **汇总文件（可选）**：在批次目录下同时保存一个汇总的 `_all.json` 文件，包含所有视频的结构化数据，便于后续程序处理。
   - JSON 格式为数组，每条包含所有字段（video_id、url、账号名称、标题、介绍、逐字稿、点赞、评论、转发、发表日期、选题方向、主题总结）。

4. **数据质量验证**（保存后必须执行）：
   - 检查批次目录下 Markdown 文件数量是否与预期采集数量一致。
   - 抽样读取2-3个 Markdown 文件，检查：
     - **占位符检查**：逐字稿部分是否包含"完整内容"、"web.fetch"、"已通过"等占位符文字
     - **长度检查**：逐字稿是否过短（<50字且非纯音乐视频）、标题/介绍是否为空
     - **格式检查**：Markdown 结构是否完整（包含基本信息、介绍、选题方向、主题总结、逐字稿等章节）
   - 发现问题时，重新获取该条数据并更新对应 Markdown 文件，直到验证通过。

5. **交付文件**：用 `present_files` 工具将批次目录交付给用户，说明目录路径、视频数量、文件结构（每个视频一个 Markdown 文件）。

#### 结果摘要（两个分支通用）

向用户报告本次采集结果：
- 采集视频总数
- 写入方式：飞书表格（给出表格链接）/ 本地文件（给出文件路径）
- 飞书表格分支：新增写入数、跳过重复数
- 逐字稿获取失败数（如有）
- 数据质量验证结果（通过 / 已修复的问题数）

## 关键注意事项

- **前置检查（必须先执行）**：开头必须检查用户是否提供了抖音地址（博主主页或视频链接）和飞书表格地址。抖音地址缺失时必须询问；表格地址缺失时必须询问，用户明确表示不用表格时保存到本地（每批单独目录，每个视频一个 Markdown 文件）。信息不齐全时不得开始采集。
- **抖音分享短链处理**：用户提供 `https://v.douyin.com/xxxxx/` 短链时，先用浏览器打开获取跳转后的真实 URL，再进行采集。
- **抖音反爬**：必须通过真实浏览器采集，禁止用 curl/requests 直接请求抖音 API。登录态是获取完整数据的前提。
- **lark-cli 路径**：沙箱环境的 lark-cli 可能登录的是测试账号，优先使用用户系统安装的 lark-cli。Mac 默认路径 `/opt/homebrew/bin/lark-cli`。
- **主字段限制**：飞书多维表格的第一个字段（主字段）不能删除，只能重命名。如果目标表格的主字段是默认的"文本"且为空，应将其重命名为"标题"而非删除。
- **字段类型转换**：text 转 select 等类型转换可能需要先确认数据兼容性，转换后原有值会自动映射为选项（如果匹配）。
- **逐字稿完整性（最高优先级）**：单条逐字稿可能很长（数千字），飞书 text 字段支持大文本，无需拆分。**必须确保写入的是完整逐字稿，禁止写任何占位符说明（如"完整内容已通过web.fetch获取"）。** web.fetch 返回内容被截断时必须分页读取直到完整。
- **数据质量验证**：写入后必须检查是否有占位符、逐字稿长度是否合理、关键字段是否为空，发现问题立即修复。
- **AI扩展字段生成**：选题方向必须从目标表格已有选项中选择，禁止自行新增选项；主题总结控制在30-80字，提炼本质不重复标题。批量生成时短视频用完整逐字稿，长视频可截断至前2000字（而非1000字）以确保涵盖核心观点。

## 参考文档

- `references/douyin.md`：抖音采集的具体选择器、数据格式、登录处理、常见异常
- `references/lark-write.md`：飞书表格字段创建、记录写入、去重逻辑、CellValue 格式

