导入视频 → 本地语音识别提取字幕 → 自动总结内容 → 导出文本文档。 纯前端、零后端、零 API 费用。视频不会上传到任何服务器,语音识别在你的浏览器里完成。
🌐 在线使用:https://polaris929-cloud.github.io/Video2Text-Studio/
| 功能 | 说明 |
|---|---|
| 🎥 视频导入 | 拖拽或选择本地视频/音频文件,支持 MP4 / MOV / WebM / MP3 / M4A / WAV 等浏览器可解码的格式 |
| 🗣️ 语音识别 | 基于 Whisper(transformers.js + ONNX Runtime Web),在浏览器内本地推理,无需 API Key |
| 🌍 多语言 | 中文、英文、日语、韩语、粤语等 15 种语言,可自动检测 |
| ⚡ 硬件加速 | 自动优先使用 WebGPU,不支持时回退 WASM(CPU);所选精度缺失时会自动换用其它精度,不会卡住 |
| 📝 字幕文稿 | 带时间戳的字幕列表,点击任意一条可跳转到视频对应位置播放,支持搜索 |
| 🧠 内容总结 | 默认本地抽取式摘要(TextRank/MMR + 关键词,免配置);也可接入任意 OpenAI 兼容接口获得 AI 生成式摘要 |
| 📄 导出文档 | 一键导出 Markdown 文本文档、纯文本 TXT、字幕 SRT / VTT、结构化 JSON |
| 🔒 隐私优先 | 视频、音频、字幕全程留在本机;唯一的联网行为是下载模型与可选的 AI 摘要 |
| 💾 断点保留 | 识别结果自动存在浏览器本地,刷新页面不会丢;模型也会被浏览器缓存,第二次使用无需重新下载 |
打开 https://polaris929-cloud.github.io/Video2Text-Studio/ 即可,无需安装任何东西。
首次使用需要联网下载语音模型(Tiny 约 40 MB / Base 约 80 MB),之后会被浏览器缓存。
git clone https://github.com/Polaris929-cloud/Video2Text-Studio.git
cd Video2Text-Studio
npm install
npm run dev # 打开 http://127.0.0.1:5173构建静态产物:
npm run build # 类型检查 + 构建,输出到 dist/
npm run preview # 本地预览构建结果
npm test # 运行纯算法自测(导出格式 / 摘要算法)dist/ 是纯静态文件,可以丢到任意静态托管(GitHub Pages / Vercel / Netlify / Nginx)。
如果 vite preview 在你的机器上不可用,仓库还带了一个零依赖的静态服务器:
node scripts/serve.mjs 4173 dist # 然后打开 http://127.0.0.1:4173/node scripts/github-deploy.mjs <owner>/<repo> # 通过 GitHub API 建仓并推送(需要 gh 已登录)
node scripts/verify-pages.mjs <owner>/<repo> # 轮询 Actions 与 Pages 构建结果之所以提供这两个脚本:本机 hosts 把
github.com指向了 127.0.0.1,git/curl直连不可用, 只有gh的 API 通道能出去,所以用 Git Data API 完成了首次推送。 配好gh auth setup-git之后,日常更新直接用git push即可。
- 打开网站,把视频文件拖进虚线框(或点「选择视频文件」)。
- 按需在 ⚙ 识别设置 里选模型和语言:
- 想快 →
Tiny或Base(默认Base,日常够用) - 中文准确率优先 →
Small/Large-v3-Turbo(体积和耗时更大) - 明确选择视频语言(而不是「自动检测」)会更快更准
- 想快 →
- 点 开始识别,进度条会显示「提取音轨 → 加载模型 → 语音识别」三个阶段。
- 识别完成后:
- 左侧自动出现 内容总结(要点 + 关键词);
- 右侧是 字幕文稿,点击任意一条可让视频跳到那一句;
- 用右侧导出按钮下载 文本文档 (.md)、.txt、.srt、.vtt、.json。
- (可选)想用大模型生成更漂亮的摘要:点 ✨ AI 摘要,启用后填入服务商的 Base URL / 模型 / API Key,再点「用 AI 重新总结」。
默认的本地摘要是抽取式的——它从文稿里挑出最有信息量的句子并去冗余,不联网、不花钱,但没有"重新组织语言"的能力。
如果你有任意一家大模型的 API Key,可以在 ✨ AI 摘要 里接入,支持所有 OpenAI 兼容的 /chat/completions 接口,内置了这些预设:
- OpenAI(
gpt-4o-mini等) - DeepSeek(
deepseek-chat) - 阿里云百炼 / 通义千问(
qwen-plus) - 月之暗面 Kimi
- 智谱 GLM
- 本地 Ollama(
http://localhost:11434/v1,完全离线)
配置后长文稿会自动「分段总结 → 汇总」处理,不会超出上下文长度。
⚠️ 安全提示:API Key 只保存在你自己浏览器的localStorage中。本项目是纯静态站点,没有后端,任何人都收不到你的 Key。但请注意:启用 AI 摘要后,字幕文本会被发送给你所配置的服务商。介意的话就不要启用,用本地摘要即可。
src/
├─ App.tsx 主界面(导入 / 进度 / 字幕 / 摘要 / 导出)
├─ types.ts 共享类型
├─ workers/
│ └─ asr.worker.ts Web Worker:加载 Whisper 并执行识别
└─ lib/
├─ audio.ts 音轨提取 + 16 kHz 单声道重采样
├─ transcribe.ts Worker 客户端封装、时间戳归一化
├─ modelSources.ts 模型来源候选链与地址拼装(纯逻辑,可单测)
├─ summarize.ts 本地抽取式摘要(TextRank/MMR + 关键词)
├─ llm.ts OpenAI 兼容接口的 AI 摘要
├─ format.ts SRT / VTT / TXT / Markdown / JSON 导出
├─ constants.ts 模型与语言清单、默认设置
└─ storage.ts localStorage 持久化
scripts/
└─ fetch-models.mjs 构建时把内置模型下载到 public/models/
几个关键设计:
- 不需要 ffmpeg.wasm。 音轨提取直接用浏览器内置的
decodeAudioData+OfflineAudioContext重采样, 省掉约 30 MB 依赖,也就不需要配置SharedArrayBuffer所需的 COOP/COEP 响应头(GitHub Pages 无法自定义响应头)。 - Whisper 单次窗口是 30 秒,所以长视频必须切片。这里用的是带重叠的滑窗:下一片从「上一片最后一条字幕的结束时间」继续, 并在拼接时做尾部/头部去重,因此不会在切片边界丢词,也不会整段重复。
- 识别跑在 Web Worker 里,界面不会卡死;音频用
Transferable传递,避免大数组拷贝。 - 模型走国内 CDN:首选魔搭 ModelScope(国内直连,实测 8~11MB/s),官方源与本站同源(
public/models/)兜底; 下载进度会显示已下载体积 / 实时速度 / 预计剩余。原因见下面「模型从哪里来」。 - 构建用相对路径(
base: './'),因此产物可以直接部署在/Video2Text-Studio/这样的子路径下。
浏览器端加载模型踩过三个坑,这也是本项目最容易被"卡住"的地方:
huggingface.co在国内连不上(TCP 被阻断)。transformers.js 内部的 fetch 默认没有超时, 于是一个请求都发不出去时,界面会永远停在 0%,看起来就像死机。- HF 镜像站(hf-mirror 等)在浏览器里不可用 —— 它们返回的
Access-Control-Allow-Origin只允许https://huggingface.co,第三方站点跨域取模型会被 CORS 直接拦掉(对方响应头决定,客户端改不了)。⚠️ 用 curl / Node 测这些地址会显示acao=*看似正常,因为不带Origin头时它们的响应不一样 —— 这类问题必须用真实浏览器验证,否则会误判成"镜像可用"。 - GitHub Pages 国内下载太慢(实测约 100KB/s,76MB 的 Base 模型要好几分钟); 而 jsDelivr 这类 CDN 只能服务仓库内的文件,模型单文件 29~51MB,既超限也不适合入库。
最终方案:首选魔搭 ModelScope。它的路径形态正好是
https://www.modelscope.cn/models/<模型id>/resolve/master/<文件>,允许跨域、支持 Range 分片,
背后是国内 LFS CDN,实测 8~11MB/s(73MB 的 Base 模型约 8 秒);
官方源、本站同源模型、镜像依次兜底。在此之上还加了一层保护:
src/lib/modelSources.ts:模型来源候选链(魔搭 ModelScope → 本站同源 → 官方 → 镜像 → 自定义)、 每个来源专用的路径模板、精度回退链(纯逻辑,可在 Node 单测);src/workers/asr.worker.ts:给模型请求装上首字节超时 / 停滞超时 / 看门狗,每秒发一次心跳进度, 任何阶段"没动静"都会主动中止并换下一个来源,最终给出可读的错误而不是无限等待; 下载进度带上「已下载 / 总量 · 实时速度 · 预计剩余」,编译初始化阶段改用动态条纹 + "编译中…" (这段没有可上报的百分比,用假百分比会让人以为卡死);- 探测不等人:来源探测一旦探到可用来源就立刻开工,其余来源在后台收尾;精度探测同理
(主精度可用就不等 fp32)。早期版本把剩余探测全
await了,结果每次启动都被连不通的 huggingface.co 拖到超时才继续,白白多等 8 秒; scripts/fetch-models.mjs:构建时把 Tiny / Base 下载到public/models/作为同源兜底 (CI 里跑,带缓存,失败不阻断部署;public/models/不入库);- 推理设备默认
auto,会真实请求一次 WebGPU 适配器再决定用 WebGPU 还是 CPU, 避免在拿不到适配器的环境里白等一轮。
另外诊断过的一个隐形坑:不要手动覆盖 env.backends.onnx.wasm.wasmPaths。
transformers.js 的 dist 里自带匹配版本的 onnxruntime wasm;一旦指向别的版本(例如 onnxruntime-web@1.20.1),
会因文件名不匹配(如缺少 .jsep.wasm)而 404,表现同样是"卡在 0%"。
支持多大的视频?
主要受内存限制,一般 1~2 小时的视频没问题。时长只影响识别耗时(大致是 音频时长 × 0.1~1,取决于模型与是否用上 WebGPU)。
浏览器解码超大文件时可能内存告急,建议先用工具压缩。
提示"无法解码音轨"怎么办?
说明浏览器自带的解码器不认这个文件的音轨编码。常见于 MKV 封装、HEVC/H.265、AC-3/EAC-3 音轨、AVI 老格式。 解决办法:先用格式转换工具转成 MP4(H.264 + AAC),或直接提取成 MP3 / WAV / M4A 再上传。
识别一直停在 0% 不动 / 模型加载失败?
先看界面上的进度文案:它会明确告诉你正在连接哪个来源、已经等了多久、以及是否准备换源, 不会像以前那样一动不动。然后按提示排查:
- 把「模型来源」设为「自动」:会按 魔搭 ModelScope → 本站同源 → 官方 → 镜像 依次探测, 并告诉你最终用了哪个、响应多快;模型建议先用 Tiny 或 Base;
- 检查「推理设备」:拿不到 WebGPU 适配器的环境(无头浏览器、禁用 GPU、老显卡、远程桌面) 会在日志里提示,可在「识别设置 → 推理设备」里手动选 CPU(WASM);
- 要换别的模型(Small / Large-v3-Turbo 等):只要魔搭上有该模型的镜像就能直接下载; 也可以自建一个放 ONNX 模型的静态目录,在「识别设置 → 模型来源」里选 自定义地址 填进去;
- 构建自己的站点:同源兜底模型由
npm run fetch:models下载到public/models/(不入库), 部署工作流.github/workflows/deploy-pages.yml里已经接好这一步;本地想手动跑也可以直接执行该命令。
想内置更多模型?改
scripts/fetch-models.mjs里的MODELS,同时把新模型 id 加进src/lib/constants.ts的BUILTIN_MODELS。
模型下载很慢 / 一直等在下载上?
模型默认从魔搭 ModelScope(国内直连)取,实测 811MB/s:Tiny(约 39MB 权重)35 秒、
Base(约 73MB)约 8 秒。界面上会实时显示「已下载 / 总量 · 实时速度 · 预计剩余」,
不会再出现"百分比不动、也不知道还要等多久"的情况。
如果还是很慢:
- 把「识别设置 → 模型来源」设为 自动,让它按 魔搭 → 本站同源 → 官方 → 镜像 的顺序挑可用的;
- 换 Tiny(权重体积只有 Base 的一半);
- 自己有更快的托管(对象存储 / 自建静态目录)时,选「自定义地址」填进去,
路径需兼容
{模型id}/resolve/main/{文件名}; - 下载一次后由浏览器
Cache Storage缓存,之后再用不会重复下载。
下载完之后还有一步「初始化推理引擎」(界面显示为动态条纹 + 编译中…), 那是在本机编译 WASM 推理引擎,CPU 上首次需要几十秒,与网络无关;换 Tiny 会明显更快。
识别很慢?
- 优先用 Chrome / Edge 113+,在识别设置里把「计算设备」设为
WebGPU; - 选更小的模型(Tiny/Base)与
q8精度; - 关掉其他占用显卡的页面;
- 老电脑上 CPU 推理本来就慢,1 小时视频跑十几分钟是正常的。
识别结果不准?
- 明确指定视频语言,别用自动检测;
- 换更大的模型(Small / Large-v3-Turbo);
- 音质差、多人抢话、背景音乐大的素材,任何 ASR 都会掉点;
- 识别完可以直接在导出前用搜索定位,手动修正后再复制。
会上传我的视频吗?
不会。视频文件只在你本机被 decodeAudioData 解码成 PCM,识别也在本机完成,没有任何上传逻辑。
你可以打开浏览器开发者工具的 Network 面板自己验证:只有模型文件和(可选的)AI 摘要请求。
- 说话人分离(Speaker Diarization)
- 导出 Word (.docx) / PDF
- 字幕双语对照与翻译
- 支持直接粘贴视频链接(需要后端或 yt-dlp,欢迎 PR)
- 浏览器扩展版(在任意视频页面一键提取)
MIT © 2026 Polaris929-cloud
语音识别模型来自 OpenAI Whisper,经 transformers.js 在浏览器内运行; 模型权重遵循其各自的开源许可。