读取抖音视频内容
两级能力,按需选择:
| 级别 | 能拿到 | 耗时 | 用什么 |
|---|---|---|---|
| L1 摘要 | 标题、作者、发布时间、互动数据、抖音官方 AI 章节要点(带时间戳的逐章摘要)、评论、推荐流 | 约 30-60 秒 | scripts/read_douyin.py |
| L2 视频 | 画面关键帧 + 逐句口播讲稿(来自画面硬字幕 OCR,带时间戳) | 约 3-5 分钟 | scripts/capture_frames.py + scripts/ocr_subtitles.py |
| L2 图文 | 图文作品(/note/)的轮播图片(去重、按序命名)+ 标题/作者/互动数 |
约 1 分钟 | scripts/capture_note_images.py |
⚠️ 第一步永远是:判断视频还是图文
分享文本里写着「图文作品」四个字 = 图文;链接跳转后 /note/{id} = 图文,/video/{id} = 视频。
两者的内容位置完全不同,搞错了会读到别人的内容(见下方"已知的坑"):
视频(/video/) |
图文(/note/) |
|
|---|---|---|
| 内容在哪 | 画面字幕 + 口播音频 | 轮播图片里 |
body.innerText |
含官方 AI 章节要点 | 基本只有页脚,拿不到正文 |
| 官方 AI 章节要点 | ✅ 有 | ❌ 没有(该功能只对视频提供) |
| 怎么做 | capture_frames.py |
capture_note_images.py → 再由视觉能力读图 |
| 兜底信息 | — | <meta name="description"> 里有标题 + 作者 + 发布时间 + 点赞数 |
先用 L1。用户只是问"这视频讲了什么",L1 的官方章节要点就够,没必要跑 L2。 只有需要逐句原文、要引用具体表述、或视频没有 AI 章节要点时,才上 L2。 图文作品必须走 L2 —— 它的正文在图片里,L1 拿不到任何正文。
核心原理
L1:抖音视频页渲染后,document.body.innerText 里含抖音官方 AI 生成的分章要点。直接读文本,不解析 DOM 选择器(类名被混淆且频繁变更)。
L2:不下载视频文件,而是让真实浏览器播放视频,再用 canvas.drawImage(video) 在任意时间点取帧 —— 可以精确按时间轴采样,且完全避开预加载污染。这类知识讲解视频通常是双层文字:顶部章节标题条 + 底部口播字幕,裁切时两块都要。
环境准备
pip install playwright requests Pillow
python -m playwright install chromium # 可跳过:会优先复用系统已装的 Edge / Chrome
OCR 后端三选一(脚本 auto 会按 winrt → tesseract → none 自动挑):
# A. Windows 内置 OCR(推荐:离线、免费、中文好)
pip install winrt-runtime winrt-Windows.Media.Ocr winrt-Windows.Globalization \
winrt-Windows.Graphics.Imaging winrt-Windows.Storage \
winrt-Windows.Storage.Streams winrt-Windows.Foundation \
winrt-Windows.Foundation.Collections
# 另需系统中文 OCR 语言包:设置 → 时间和语言 → 语言 → 中文(简体) → 语言选项 → 光学字符识别
# B. 跨平台
# macOS: brew install tesseract tesseract-lang
# Ubuntu: sudo apt install tesseract-ocr tesseract-ocr-chi-sim
pip install pytesseract # 可选,装了会自动优先走 Python 接口
# C. 都不装:用 --backend none,把裁好的字幕图交给具备视觉能力的 agent 自己读
- 浏览器优先复用系统已装的 Edge / Chrome(
--browser auto会依次尝试 msedge → chrome → chromium),都没有才回落到 Playwright 自带 Chromium,省 500MB 下载。 想强制指定用--browser msedge/--browser chrome。
使用方式
本 skill 放在用户级 skills 目录里,任何项目、任何任务都能直接调用,与工作目录无关。
SK=<本 skill 的绝对路径>/scripts
# L1:元信息 + 官方章节要点(约 30-60 秒)
python "$SK/read_douyin.py" "<分享文本或链接>"
python "$SK/read_douyin.py" "<链接>" --json # 结构化输出
# L2 第一步:逐帧截图(约 1-2 分钟,不下载视频)
python "$SK/capture_frames.py" "<链接>" --out "<输出目录>" --interval 1.5
# L2 第二步:裁字幕区 + OCR + 生成讲稿(约 30 秒)
python "$SK/ocr_subtitles.py" --dir "<输出目录>"
# 没有可用 OCR 引擎时:只出图,交给具备视觉能力的 agent 直接读
python "$SK/ocr_subtitles.py" --dir "<输出目录>" --backend none
# L2 图文版:抓轮播图(约 1 分钟,自动去重 + 移除登录遮挡层)
python "$SK/capture_note_images.py" "<链接>" --out "<输出目录>"
用装了依赖的那个解释器——如果依赖装在虚拟环境里,就把 python 换成该环境的解释器路径,
或先激活环境。系统全局 Python 里通常没装 playwright / Pillow。
L2 输出目录内容:frames/*.jpg(关键帧)、frames.json(时间轴+时长)、subtitles/*.jpg(裁好的字幕条)、ocr_raw.txt(OCR 原始输出)、transcript.md(讲稿)、transcript.json(带时间戳的结构化分段)、manifest.md(--backend none 时的读图清单)
采样间隔建议 1.5 秒(字幕约 2-3 秒换一次,1.5 秒能保证每条至少被采到一次)。长视频可放宽到 2-3 秒省时间。
关键实现要点(改脚本前必读)
- 先预热
https://www.douyin.com/拿匿名 cookie(ttwid 等),再跳视频页,成功率显著提高。 - 必须处理登录弹窗(「登录后免费畅享高清视频」会遮住内容):
Escape+ 点关闭按钮(PC 布局 1600×900 下约x=763, y=167),反复几轮直到<video>出现。 wait_until用domcontentloaded,绝不用networkidle——抖音页面永不 idle,会一直挂到超时。page.goto要try/except包住:超时不致命,等 3-5 秒页面通常已渲染完,继续读文本/取帧即可。- 用视频时长校验是否拿到了正确视频:
video.duration应与页面显示时长一致(本例 284.887s ≈ 4:45)。这是 L2 里唯一可靠的"身份校验"。 - OCR 需要 BGRA8 格式,必须显式转换,否则抛异常。
已知的坑(都是实测踩出来的)
⚠️ 最危险的一个坑:图文作品用 /video/ 路径 → 读到别人的内容
/video/{id} 对图文作品来说是不存在的页面,抖音不会报错,而是回落到推荐流。
后果:ID 解析正确、页面正常渲染,但 body.innerText 里是别人的作品。
ID 对、内容错 —— 这是最难发现的错法,因为没有任何报错。
实测(2026-09-15):分享链接是【懂AI的小米的图文作品】联想 AI Agent 开发一面, 脚本却读出了《8种核心电影镜头语言》另一个作者的完整文案。
两道防线(都已实装):
extract_video_id()同时识别/video/与/note/,返回(id, kind);grab_page_text()按 kind 拼对应路径。- 身份校验:导航后的
page.url必须包含目标 ID,否则报错退出。read_douyin.py会exit(2),capture_note_images.py会打 error 日志。 → 凡是新增抓取逻辑,都要带上这道校验,不能只信"页面打开了"。
图文页正文不在 innerText 里
桌面端图文页的 body.innerText 只有导航和页脚(实测 2888 字符里基本全是备案号、
用户协议之类),正文全在轮播图片里。
→ 别指望用 read_douyin.py 拿到图文正文;直接上 capture_note_images.py 取图后读图。
→ 唯一能从 DOM 白拿的是 <meta name="description">,里面有
标题 + 作者 + 发布时间 + 点赞数。read_douyin.py 已实装:
kind=note 时用 <title> + meta 覆盖 parse() 的结果(否则 parse() 会误抓推荐流文本,
标题显示成别人的作品名),并在 stderr 提示改用取图脚本。
登录遮挡层:点坐标不可靠,用 JS 移除
图文页会弹「登录后免费畅享」模态框遮住内容。MODAL_CLOSE_COORDS 的坐标点击
实测经常失效(截图里模态框还在)。
→ 可靠做法:沿 DOM 向上找 position: fixed 的祖先节点并 display: none。
实现见 capture_note_images.py 的 KILL_OVERLAY_JS
(先按文案定位最内层文本节点,再向上找 fixed 祖先,避免误伤正文)。
判定标准:移除后 body.innerText 里应出现目标关键词(如标题中的词)。
别用 yt-dlp 下抖音
yt-dlp 的抖音提取器调 aweme/v1/web/aweme/detail/,抖音现在要求 a_bogus 签名(源码里写着 TODO: Run verification challenge code to generate signature cookies),因此加任何 cookie 都失败,报 Fresh cookies (not necessarily logged in) are needed。自己造匿名 ttwid(ttwid.bytedance.com/ttwid/union/register/ + callback)也无效。
别解析 iesdouyin 分享页
https://www.iesdouyin.com/share/video/{id} 的 window._ROUTER_DATA 还在,但 loaderData["video_(id)/page"] 里已没有 videoInfoRes 字段(抖音改版),基于它的解析方案(如 yzfly/douyin-mcp-server 的 douyin-video skill)全部失效。
别靠捕获 .mp4 下载视频
抖音播放器会预加载推荐流的其他视频,网络里抓到的 *.douyinvod.com 的 mp4 很可能不是目标视频(实测下到一个 270MB 的隔壁游戏视频)。用 canvas 取帧就没这个问题。
Windows PowerShell 5.1 的编码陷阱(所以本 skill 不碰 PowerShell)
无 BOM 的 .ps1 会被当 ANSI/GBK 解码,脚本里任何中文都会破坏语法(报"缺少右 }"之类的怪异错误)。而且本环境安全策略会拦截 PowerShell 脚本执行和 Add-Type。
→ OCR 走 Python 的 winrt 绑定,完全不碰 PowerShell。如果你要写 ps1,必须保证文件是纯 ASCII。
(曾有一个 ocr_batch.ps1 实现,已删除——在这套环境里跑不起来。)
winrt-py 的重载参数个数与文档不一致
实测(winrt 3.2.1):
decoder.get_software_bitmap_async()→ 必须 0 参decoder.get_software_bitmap_converted_async(fmt, alpha)→ 必须 2 参
传错个数会在调用时同步抛 TypeError: Invalid parameter count(不是 await 时)。
Windows OCR 会插入空格,且对艺术字体有形近字误差
- 中文之间会被插空格 → 必须
normalize()去掉所有空白再比对/去重 - 形近字误差是字体风格导致的,无法靠预处理消除:实测
autocontrast/ 二值化(140/180) /SHARPEN对识别结果没有提升,原图就是最好的。常见错例:标准→标推、解决→解块、核心→核弋/核答 - → 生成讲稿后应人工扫一遍改掉高频形近字错误,或用上下文校正
相关第三方 skill(调研记录,本 skill 未依赖)
yzfly/douyin-mcp-server的douyin-video:解析 iesdouyin 分享页取无水印地址 —— 已失效douyin-zh/douyin-dl(SkillHub):用 Playwright / agent-browser 取<video>src 下载 —— 方法方向对,但受预加载污染影响可能下错视频douyin-orchestrator(SkillHub):引用了三个不存在的子 skill,空壳
实测验证记录
| 日期 | 视频 | 结果 |
|---|---|---|
| 2026-09-12 | 7681979274496183552《大厂AI Agent面试题:自驱执行架构》4:45 | L1 ✅;L2:190 帧 @1.5s → 380 次 OCR(29 秒)→ 去重 143 条字幕,覆盖全片 |
| 2026-09-12 | 7683485349322169075《Agent项目做到什么程度…》3:25 | L1 ✅;L2:137 帧 @1.5s → 去重 95 条字幕。全程无需改代码,证明可复用 |
| 2026-09-12 | 同上 | 跨目录调用验证:从任意工作目录调用(脚本用绝对路径、--out 传相对路径),L1/L2 均正常,产出落到当前 cwd |
| 2026-09-15 | 7682600459021911205【懂AI的小米 · 图文】联想 AI Agent 开发一面 | 首次遇到图文作品:L1 无官方章节要点;/video/ 硬编码导致读到别人的内容(ID 对内容错,已修 + 加身份校验);read_douyin.py 图文标题改用 meta 覆盖(原先显示别人的作品名);新增 capture_note_images.py,实测抓到 2 张轮播图(1179×2429),JS 移除遮挡层 1 个节点,元描述兜底拿到标题+作者+946 赞。升级后三条路径全部回归验证通过(图文读取 / 视频读取 / 图文取图) |
两个视频都是 1080p 或 720p,video.duration 校验与页面显示时长一致(284.887s / 205.034s)。