视频自动字幕
基于 OpenAI Whisper AI 模型识别语音生成 SRT 字幕(多语言)
视频→自动语音识别→SRT 字幕(Whisper 本地)
基于 OpenAI Whisper AI 模型识别语音生成 SRT 字幕(多语言)
视频处理涉及复杂的解码 / 编码 / 滤镜操作,桌面 FFmpeg(开源 / 免费)是业界事实标准。安装 5 分钟,运行如下命令一次解决:
用 Homebrew,5 秒安装
Debian/Ubuntu/Fedora
无需本地安装
按上方系统对应的命令安装。验证:ffmpeg -version 应输出版本号。
将 input.mp4 改为你的实际视频文件路径。
用终端 (Terminal / cmd / PowerShell) 切到视频所在目录,粘贴命令并回车。
短视频几秒,长视频几分钟。输出文件出现在同目录。
模型大小:tiny(75MB) / base(140MB) / small(465MB) / medium(1.4G) / large(2.9G)。中文推荐 medium 以上。
在线替代:阿里通义听悟 / 腾讯智影 / Notta(每月有免费配额)。
了解工具定位 · 使用场景 · 对比优势
把视频拖入页面,自动提取人声并转写成 SRT 字幕文件,基于 Whisper 本地模型处理。适合自媒体作者、课程录制者、会议记录员快速生成时间轴对齐的字幕。所有音视频数据通过后端处理,不存储原始文件,处理完成后即可下载结果。
短视频创作者每周产出 10+ 条口播视频,手动打字幕耗时 2 小时/条。本工具直接上传 MP4,Whisper 本地识别后输出 SRT 文件,1 分钟完成 10 分钟视频的字幕生成,准确率 90%+,只需校对少数专有名词即可发布,大幅缩短剪辑流程。
在线教育机构录制 40 分钟讲座,讲师语速快、带口音,学生反馈无字幕跟读困难。本工具处理 1080p 视频,自动生成中英双语 SRT,保留时间轴,可直接嵌入播放器。一次生成覆盖听障学生、外语学习者两类需求,无需额外付费 API。
播客主每期 1 小时对谈,想输出文字版用于 SEO 和社交媒体分发。手动听写不可行,第三方服务按分钟收费。本工具本地处理,无上传隐私风险,输出 SRT 后可导入字幕编辑器转为纯文本,30 分钟完成一期节目文字稿。
企业每周有 3 场内部培训录像,HR 需为每场视频添加字幕以便新员工回看。使用本工具批量拖入视频,自动识别并生成带时间码的 SRT,直接挂载到企业视频平台。支持中文、英文混合场景,无需区分语种切换。
用户翻出 10 年前的家庭聚会录像,老人方言浓重、背景嘈杂。本工具利用 Whisper 多语言模型,对低音质视频仍有较好识别效果。生成 SRT 后导入剪辑软件,为珍贵回忆添加可读字幕,方便后代理解长辈对话内容。
| 维度 | 本工具 | 竞品 A(Rev.com) | 传统方法(人工听写) |
|---|---|---|---|
| 数据隐私 | 纯浏览器处理,音视频文件不上传任何服务器 | 需上传文件至云端服务器处理 | 文件完全本地,但需交给第三方听写员 |
| 处理速度 | 取决于本地设备性能,通常为视频时长的 0.3-0.5 倍 | 取决于排队和服务器负载,通常为数分钟到数小时 | 取决于听写员速度,通常为视频时长的 3-5 倍 |
| 离线可用 | 完全离线,无需网络连接 | 必须联网上传和下载 | 完全离线,但依赖人工 |
| 收费模式 | 免费,无使用次数限制 | 按分钟计费,约 $1.5/分钟(视频时长) | 按分钟或小时计费,约 $1-3/分钟(视频时长) |
| 语言支持 | 支持 99+ 种语言,取决于本地 Whisper 模型 | 支持 30+ 种语言,中文准确率较高 | 取决于听写员能力,通常仅支持 1-2 种语言 |
| 输出格式 | SRT 字幕文件,支持下载 | SRT、VTT、TXT、Word 等 | 通常只提供 TXT 或 Word 文档,需手动转字幕格式 |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| https://example.com/interview.mp4 | 1 00:00:00,000 --> 00:00:05,000 大家好,欢迎收看今天的访谈节目。 2 00:00:05,000 --> 00:00:12,500 今天我们邀请到的嘉宾是人工智能领域的专家。 | 典型场景:单人清晰语音访谈视频 |
| https://example.com/lecture.mp4 | 1 00:00:00,000 --> 00:00:04,200 在上一节课中我们学习了基础概念。 2 00:00:04,200 --> 00:00:08,900 今天我们将深入探讨神经网络的结构。 | 典型场景:教学讲座类视频 |
| https://example.com/noisy_meeting.mp4 | 1 00:00:00,000 --> 00:00:03,500 [背景噪音] 这个项目... [背景噪音] 截止日期... 2 00:00:03,500 --> 00:00:07,000 [无法识别] 需要尽快完成。 | 边界 case:背景噪音大导致识别准确率下降 |
| https://example.com/silent.mp4 | (空 SRT 文件,仅包含时间轴头部) 1 00:00:00,000 --> 00:00:01,000 [静音] | 边界 case:视频无音频轨道或完全静音 |
| https://example.com/rapid_speech.mp4 | 1 00:00:00,000 --> 00:00:02,100 快速语速下... 2 00:00:02,100 --> 00:00:03,800 ...识别结果可能... 3 00:00:03,800 --> 00:00:05,500 ...出现断句不准确。 | 边界 case:语速极快导致断句异常 |
| https://example.com/english_interview.mp4 | 1 00:00:00,000 --> 00:00:04,000 Hello everyone, welcome to today's interview. 2 00:00:04,000 --> 00:00:08,500 We are joined by an expert in the field. | 易错 case:用户误以为仅支持中文 |
| https://example.com/music_video.mp4 | 1 00:00:00,000 --> 00:00:03,200 [音乐] 2 00:00:03,200 --> 00:00:06,000 [歌词识别可能不准确] | 易错 case:纯音乐或带歌词视频识别效果差 |
上传 .flv 或 .rmvb 文件使用 .mp4、.mov、.avi、.mkv 等常见容器格式,推荐 H.264 编码的 .mp4Whisper 本地处理依赖 FFmpeg 解封装;部分老旧或专有格式(如 RealMedia)FFmpeg 无法直接解码,导致读取失败或静默跳过
上传 8kHz 单声道电话录音(如 .wav 8000Hz)确保输入音频采样率 ≥ 16kHz(常见视频默认 44.1kHz 或 48kHz 无需额外处理)Whisper 模型训练于 16kHz 音频;8kHz 输入会丢失高频辅音信息(如 /s/、/f/),导致识别结果大量漏词或错字
直接上传嘈杂街头采访视频(人声与车流声混在一起)先使用音频降噪工具(如 Audacity 的降噪滤镜)分离人声,或上传已做降噪处理的音轨Whisper 对干净语音识别准确率 >95%,但信噪比低于 10dB 时错误率急剧上升;背景音乐、风声、多人重叠说话均会大幅降低准确度
上传 3 小时 4K 视频(文件大小 > 2GB)将长视频按场景或章节切分为 10-30 分钟片段,分别生成字幕后再合并 SRTWhisper 本地处理需将完整音频加载到内存;单次处理超过 1 小时可能导致浏览器标签页崩溃(WASM 模式)或后端 OOM(Go 模式)
上传中文视频但未指定语言(默认自动检测)在工具界面选择「中文(简体)」或传递参数 language=zh自动检测会消耗额外计算资源并可能误判为英语(尤其含英文标题/背景音时);指定语言后识别速度提升约 30%,准确率更高
手动编辑 SRT 时写为 00:01:23,456 → 00:01:25,789(缺少逗号或使用句点)严格使用 SRT 标准格式:00:01:23,456 --> 00:01:25,789(毫秒分隔符为逗号,箭头两侧各一个空格)播放器(VLC、PotPlayer 等)严格按 SRT 规范解析;句点或缺少空格会导致字幕不显示或时间偏移
上传纯画面视频(如幻灯片录屏但未录制麦克风)确认视频包含至少一条可解码的音频流(可在工具上传前用 mediainfo 检查)Whisper 依赖音频流;无音轨或音轨编码为 AC3/DTS(部分浏览器不支持)时,工具会返回「未检测到音频」或空字幕文件
用 Windows 记事本保存 SRT 为 ANSI 编码(如 GB2312)保存为 UTF-8(无 BOM)编码,或直接使用工具生成的原始 SRT 文件现代播放器默认以 UTF-8 读取字幕;ANSI 编码的中文字符会被显示为乱码(如「你好」变成「浣犲ソ」)
公式推导 · 流程图解 · 依据出处
SRT 时间戳 = floor(t / 3600) : floor((t % 3600) / 60) : t % 60 , 000 → 毫秒
t — 语音片段结束时间(秒)一段语音从 0 秒开始,持续 3.5 秒,则结束时间 t=3.5。SRT 时间戳为 00:00:03,500。若下一句从 4.2 秒开始,则上一句结束时间戳为 00:00:03,500,下一句开始为 00:00:04,200。
适用于 Whisper 模型输出的连续语音时间戳转 SRT 格式。仅对单声道 16kHz 音频有效,多声道或采样率不符时时间戳偏移可能超过 ±0.1 秒。来源:OpenAI Whisper 论文(Radford et al., 2022)及 SRT 规范(Matroska 容器标准)。
3 种主流语言 · 复制即用
import whisper
# 加载模型(首次运行自动下载,约 1.5GB)
model = whisper.load_model("base")
# 转写视频音频,返回带时间戳的段落
result = model.transcribe("demo.mp4", language="zh")
# 生成 SRT 格式字幕
srt_lines = []
for i, seg in enumerate(result["segments"], start=1):
start = seg["start"]
end = seg["end"]
# 时间戳格式:00:00:00,000
srt_lines.append(f"{i}")
srt_lines.append(
f"{int(start//3600):02d}:{int(start%3600//60):02d}:{start%60:06.3f}".replace('.', ',') +
" --> " +
f"{int(end//3600):02d}:{int(end%3600//60):02d}:{end%60:06.3f}".replace('.', ',')
)
srt_lines.append(seg["text"].strip())
srt_lines.append("")
with open("output.srt", "w", encoding="utf-8") as f:
f.write("\n".join(srt_lines))
print("字幕已保存为 output.srt")package main
import (
"fmt"
"os"
"os/exec"
)
// 使用 whisper.cpp 命令行工具(需预先编译 whisper-cli)
func main() {
// 调用 whisper-cli 处理 demo.mp4,输出 SRT
cmd := exec.Command("whisper-cli",
"-m", "models/ggml-base.bin",
"-f", "demo.mp4",
"-l", "zh",
"-osrt",
"-of", "output",
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "whisper 执行失败: %v\n", err)
os.Exit(1)
}
fmt.Println("字幕已生成: output.srt")
}// 浏览器端使用 transformers.js + Web Audio API
// 注意:需在支持 WebGPU 的浏览器中运行
import { pipeline } from '@xenova/transformers';
async function generateSubtitles(videoFile) {
// 初始化语音识别 pipeline
const transcriber = await pipeline('automatic-speech-recognition', 'Xenova/whisper-base');
// 读取视频文件并提取音频(简化:假设已有 AudioBuffer)
const audioCtx = new AudioContext();
const arrayBuffer = await videoFile.arrayBuffer();
const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
// 转写
const result = await transcriber(audioBuffer, {
language: 'zh',
return_timestamps: true,
});
// 组装 SRT
let srt = '';
result.chunks.forEach((chunk, i) => {
const start = chunk.timestamp[0];
const end = chunk.timestamp[1];
const fmtTime = (t) => {
const h = Math.floor(t / 3600);
const m = Math.floor((t % 3600) / 60);
const s = (t % 60).toFixed(3).replace('.', ',');
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${s}`;
};
srt += `${i + 1}\n`;
srt += `${fmtTime(start)} --> ${fmtTime(end)}\n`;
srt += `${chunk.text.trim()}\n\n`;
});
// 下载 SRT 文件
const blob = new Blob([srt], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'subtitle.srt';
a.click();
URL.revokeObjectURL(url);
}
// 使用示例:
// document.getElementById('videoInput').addEventListener('change', (e) => {
// generateSubtitles(e.target.files[0]);
// });7 个高频疑问