一条油猴脚本,把任意网页视频变成可复制、可下载的文字。有官方字幕秒取,没字幕用 AI 听写,3 小时长视频也能稳稳跑完。零安装、零后端、零本地模型。
三个真实场景,你对号入座:
- 想扒 B 站课程的字幕做笔记,UP 主没上传字幕,只能边看边暂停手打。
- 想拿 YouTube 视频的文字稿做翻译或摘要,官方字幕接口又不好直接调。
- 手上有个 3 小时的无字幕长视频(讲座、ASMR、直播回放),市面上的工具要么装 Python + ffmpeg,要么跑一半就崩。
这个脚本把三件事合到一起:取字幕、没字幕就听写、长视频也扛得住。
| 理由 | 具体表现 |
|---|---|
| 全网通用,不是一个站的专用工具 | B 站(含登录态 AI 字幕)、YouTube(含自动字幕)、任意网页 <video> 的 WebVTT,三套适配器自动认领 |
| 没有字幕才是它的主场 | 内置硅基流动 SenseVoice 云转写,把「无字幕视频」这条死路接活 |
| 3 小时长音频真的能跑完 | v9.0 分段解码:不播放、不整段解码,按分片目录逐片取逐片解,内存恒定,3 小时音频照样跑 |
| 转写时一声不响 | 分段解码根本不播放;兜底路线全程静音(增益 0)。最小化页面照样跑 |
| 进度看得见 | 五阶段进度条 + 实时字幕流(边转边长)+ 预计剩余时间 + 收起后的小胶囊 + 完成系统通知 |
| 纯前端,密钥不出浏览器 | 没有服务器,你的 API Key 只存在 Tampermonkey 本地沙箱,不上传任何第三方 |
| 有测试兜底 | 54 项 Node 单元测试 + 浏览器灰度页 + 播放录制状态机模拟器,改一行都跑一遍 |
如果这个脚本帮你省下了一次手打字幕的时间,点个 Star 就是最好的回报。
| 来源 | 支持情况 |
|---|---|
| B 站官方字幕 | WBI 签名稳定调用,人工字幕优先于 AI 字幕,中文优先于其他语种,多 P 视频自动跟 P |
| YouTube 字幕 | 解析播放器响应里的字幕轨道,TTML 双形态时间戳全兼容,自动字幕标注 AI |
| 通用网页 | 扫描 <video> 下的 `<track kind="subtitles |
拿到音频地址
│
├─ 有分片目录(B站 dash)─► ① 分段解码(v9.0 首选:逐片下载 + 逐片解码,内存恒定,完全不播放)
│
├─ ≤40MB ────────────────► ② 整段直传(原始文件直接送模型,最快)
│
└─ 其余 ──┬──────────────► ③ 解码切片(16kHz 解码,几十秒出结果)
│
└──────────────► ④ 静音播放录制(最后兜底,内存恒定)
- ① 分段解码(v9.0 首选):B 站音频是分片 MP4,开头一小段是「说明书」,紧跟一个「分片目录」,写着每一片的大小与时长。脚本读说明书 → 按目录并发取片 → 每片单独解码 → 攒够 2 分钟送一次识别。不播放、不整段解码,内存只占当前一片,跟视频多长无关。
- ② 整段直传:小文件不解码,原样丢给 SenseVoice。
- ③ 解码切片:一次性解码成 16kHz 再切片。v8.2 把这一步的内存降了下来(立体声省 2.75 倍、单声道省 5.5 倍)。
- ④ 静音播放录制:最后兜底。浏览器按倍速静音播放,边播边抓边转,内存恒定。
- 前一路不通自动走下一路,一条路堵不死。
- MIME 自愈:文件头魔数探针(ftyp / RIFF / EBML / OggS / ID3),服务器标错类型也能纠正后重试。
- 选路不再靠猜:读取音频真实时长与真实声道数再算内存占用,避免把 3 小时当 1 小时处理。
转写完直接翻。硅基流动 Qwen2.5-72B / 7B / DeepSeek-V3 三选一,批量 120 条一次调用。
TXT(纯文本,带 UTF-8 BOM,Windows 记事本不乱码)、SRT(带时间戳,可挂播放器)、一键复制。
| 方案 | 形态 | 短板 |
|---|---|---|
| 各类 B 站字幕油猴脚本 | 纯油猴 | 只认 B 站,无字幕就傻眼,不做语音识别 |
| Python CLI 工具 | 命令行 | 要装 Python + ffmpeg,有的还要 GPU |
| 浏览器扩展 | 扩展 | 常要配合 Native Host 或本地大模型后端 |
| 本地 Whisper 方案 | 扩展 | 要下 80 到 250MB 模型,吃内存,老机器跑不动 |
| 本项目 | 纯油猴 | 零后端、零本地模型,有字幕取字幕,没字幕云端听写,长视频走快路 |
第 1 步 · 装 Tampermonkey
Edge / Chrome / Firefox 应用商店搜「Tampermonkey」一键安装。
第 2 步 · 拿一个硅基流动 API Key(只用官方字幕的话可跳过)
用 GitHub 账号登录 cloud.siliconflow.cn 注册,新用户送 ¥16 代金券,跑 AI 转写完全够用。进控制台复制 sk- 开头的 Key。
第 3 步 · 装脚本
打开 bili-subtitle.user.js,把全文粘贴进 Tampermonkey 的「新建脚本」编辑框,保存。
第 4 步 · 用
打开任意带视频的网页,右下角出现 🎬 按钮 → 点开 → 点「⚡ 获取字幕」。
- 有官方字幕:秒出,直接复制或下载。
- 没字幕:点「🎙 AI 转写」,填好 Key 就开跑。
纯文字页面不会出现按钮,不打扰。
这是 v8.2.0 的主要工作,也是这个项目最能打的地方。
旧版的三重退化(60 分钟能用、3 小时不行的真相):
- 音频超过 40MB 就被推去「播放录制」,3 小时要真放 13 分钟。
- 播放位置卡顿 5 秒就判「放完了」,直接截断,还不报错。
- 界面每 0.8 秒重画全部字幕,主线程被拖住,抓音回调跟着丢帧,时间戳越漂越远。
v8.2.0 的解法:
| 手段 | 效果 |
|---|---|
| 解码目标 44100 → 16000 | 3 小时立体声从约 3.8GB 降到约 1.32GB,单声道降到约 659MB |
| 读音频真实时长再选路 | 不再拿文件体积猜码率,避免把 3 小时当 1 小时 |
| 读 MP4 容器里的真实声道数 | 估算不再少算一半;单声道长音频走解码快路,立体声超阈值走稳路 |
| 解码完成后按实际声道复核 | 估算与真实不符时记录提示,不静默冒 OOM 风险 |
| 抓音从 ScriptProcessor 换 AudioWorklet | 音频独立线程,页面卡顿也不丢采样点 |
| 停滞判定看缓冲状态 | 位置与缓冲同时停 20 秒才收尾,不再误杀 |
| 背压闸门 | 待转写切片积压就暂停播放,内存不涨 |
| 转写全程静音 | 播放推进、数据照抓,扬声器一声不出 |
真机验收步骤(沙箱跑不了,你的机器 5 分钟能验完):
- 找一个 3 小时左右的无字幕视频(例如
BV1424U6JEGL,3 小时 33 分)。 - 点 🎬 → ⚡ 获取字幕 → 看到「本视频无字幕」→ 点 🎙 AI 转写。
- 观察进度条:下载 → 读时长 → 解码(通常几十秒)→ 转写(分片走)→ 合并。
- 验收标准:转写期间没有声音;界面实时长出字幕;时间戳与音频对得上;导出 TXT / SRT 中文不乱码。
转写过程不再是黑箱:
① 下载 ② 读时长 ③ 解码/录制 ④ 转写 ⑤ 合并
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
音频 86MB · 时长 3:33:00 · 已处理 1:12:30 / 3:33:00 · 已用 2:14 · 预计还需 4:06
[00:00:03] 你好,欢迎来到本期节目
[00:00:08] 上一节我们讲到了电子排布
[00:00:15] 现在来看第二主族
- 五阶段进度条:走过的打勾,当前的加亮,总进度按权重折算成一条。
- 实时字幕流:最近 40 句边转边显示,看得见内容在长。
- 预计剩余时间:按实测速度外推,随进度自动修正。
- 胶囊小条:面板收起后显示「🎧 62% · 约 8 分钟」,不挡视频。
- 完成通知:转完发系统通知,中途可以最小化页面去干别的。
- 可取消:随时中断,已转好的部分照样保留。
| 选项 | 说明 |
|---|---|
| 硅基流动 API Key | AI 转写与翻译共用,只存本地 |
| 无字幕时自动转写 | 关掉则只提示,不自动开跑 |
| 字幕获取失败时自动转写 | 官方接口失败兜底 |
| 始终使用音频转写 | 无视自带字幕(适合字幕损坏的视频) |
| 转写语言 | 自动识别 / 中文 / 英文 / 日文 / 韩文 / 粤语 |
| 转写模型 | SenseVoiceSmall(快)/ SenseVoiceLarge(更准) |
| 分片时长 | 5 / 10 / 15 / 20 分钟一片 |
| 超长视频策略 | 自动(推荐)/ 始终整体解码(最快最吃内存)/ 始终播放录制(最稳最慢) |
| 播放录制倍速 | 2 / 4 / 8 / 16 倍速(仅兜底路线用得到) |
| 翻译为 / 翻译模型 | 不翻 / 中英日韩法德西葡俄阿 × Qwen2.5-72B / 7B / DeepSeek-V3 |
API Key 输入框右侧有 👁 可切换明文显示。
Q:提示「未配置硅基流动 API Key」?
打开 ⚙ 设置,粘贴 sk- 开头的 Key 保存。只用官方字幕不需要 Key。
Q:转写要多久? 取决于走哪条路。分段解码路(v9.0 首选)音频处理本身只占几十秒,总耗时基本等于识别服务的时间;解码切片路几十秒到几分钟;播放录制兜底路按「音频时长 ÷ 倍速」算。
Q:转写时会有声音吗? 不会。v8.2.0 起播放全程静音(增益 0),只让播放位置推进。
Q:能关掉页面吗? 最小化或切到别的标签页没问题。完全关闭标签页会中断。
Q:YouTube 无字幕为什么不能转写? YouTube 音频是带签名分片的流媒体,需要解流签名才能取到。脚本会提示改用官方自动字幕,自动字幕本身已支持。
Q:MSE / blob: 视频呢?
这是浏览器的媒体源扩展保护,页面里没有可直接下载的音频地址,无法取音。
Q:B 站要登录吗? 取 AI 字幕通常需要登录 B 站账号(浏览器已有登录态即可)。人工字幕一般不需要。
Q:数据安全吗? 脚本纯前端运行,无任何后端服务器。设置与 API Key 只存在浏览器本地,不会上传第三方。音频只在你调用转写时发送给硅基流动。
- ✅ v9.0 · 分段解码(已完成):按分片目录逐片下载、逐片独立解码,内存恒定,完全不播放,时间戳用目录给的精确起点。
- v9.1(下一步):分片断点续传(网络断了接着取,已转的部分不重来)、并发转写加速、每片进度更细。
- v9.2(规划):更多站点适配、字幕格式扩展(ASS / LRC)、暗色模式。
如果你希望优先做哪一项,欢迎在 Issues 里说一声。
node tests/run-tests.js # 单元测试:MD5 / WBI / SRT / VTT / TTML / WAV / MIME / 选路 / 声道 / 长音频硬化(69 项)
node tests/serve.js # 本地静态服务,端口 8765浏览器灰度页:
http://127.0.0.1:8765/tests/test.html—— UI 与音频管线灰度http://127.0.0.1:8765/tests/recorder-sim.html—— 播放录制状态机模拟,驱动自然结束 / 中途取消 / 意外暂停 / 停滞收尾 / 解锁成功 / 解锁取消六条路径,任何一条卡死即 FAIL
真实 API 冒烟(Key 只从环境变量读,不入仓库):
SILICONFLOW_API_KEY=sk-... node tests/sf-smoke.js- 本地优先:纯前端运行,无后端服务器,设置与 Key 只存浏览器本地。
- 密钥安全:API Key 由你自行配置,仅在调用硅基流动接口时使用;请勿写入公开 Issue 或他人脚本。
- 模型服务:无字幕转写依赖硅基流动 SenseVoice / Qwen / DeepSeek 等第三方服务,费用与可用性以服务商为准。
- 内容责任:提取的字幕仅作个人学习与无障碍辅助之用。请遵守《著作权法》与相关平台规则,未经授权不得转载、二次分发或商用。
- 商标:B 站、YouTube 等名称为其各自所有者的商标。
- 作者:ReTri(@huanweide)
- 仓库:github.com/huanweide/bili-subtitle-universal
- 许可:MIT License
- 赞助(自愿):GitHub Sponsors
如果这个工具帮到了你,给个 Star ⭐ 能让更多人找到它。 © 2026 ReTri