视频字幕 OCR

提取硬字幕→SRT(PaddleOCR/Tesseract)

410 次访问
👁️
SUBTITLE OCR

视频字幕 OCR

对烧录在画面中的硬字幕进行 OCR 识别提取

FFmpeg 命令行(推荐)

视频处理涉及复杂的解码 / 编码 / 滤镜操作,桌面 FFmpeg(开源 / 免费)是业界事实标准。安装 5 分钟,运行如下命令一次解决:

# 提取关键帧(每 1 秒一帧) ffmpeg -i input.mp4 -vf fps=1 frames/frame_%04d.png # 对每帧用 Tesseract OCR(用裁剪滤镜只保留字幕区域 + OCR) # 安装 tesseract brew install tesseract tesseract-lang # 单帧测试 tesseract frames/frame_0001.png stdout -l chi_sim+eng # 推荐使用 VideoSubFinder / SubtitleEdit(桌面工具) # 自动检测字幕位置 + OCR 全流程 # Windows: SubtitleEdit (https://www.nikse.dk/subtitleedit/)

桌面 FFmpeg 安装

macOS

brew install ffmpeg

用 Homebrew,5 秒安装

Linux

sudo apt install ffmpeg # 或 sudo dnf install ffmpeg

Debian/Ubuntu/Fedora

Windows

下载 Gyan FFmpeg builds

解压后将 bin 目录加入 PATH

Docker

docker run --rm -v $PWD:/work \ jrottenberg/ffmpeg -i input.mp4 ...

无需本地安装

操作步骤

步骤 1:安装 FFmpeg

按上方系统对应的命令安装。验证:ffmpeg -version 应输出版本号。

步骤 2:复制本页面提供的命令

input.mp4 改为你的实际视频文件路径。

步骤 3:在视频所在目录运行

用终端 (Terminal / cmd / PowerShell) 切到视频所在目录,粘贴命令并回车。

步骤 4:等待处理完成

短视频几秒,长视频几分钟。输出文件出现在同目录。

关于本工具

了解工具定位 · 使用场景 · 对比优势

上传一个带硬字幕的视频(MP4、MKV、AVI 等常见格式),自动识别字幕区域并提取文本,输出为标准的 SRT 字幕文件。适合压制了内嵌字幕的剧集、课程录像、老电影——不需要反复暂停抄写。视频上传到服务端处理,处理完成后原视频和字幕文件会被立即删除,不留存。

使用场景

🎬

外挂字幕提取

影视爱好者下载了无字幕的蓝光原盘,或手头有带硬字幕的 MKV/MP4 文件,想转成外挂 SRT 方便播放器切换或二次剪辑。本工具直接上传视频段或截图,自动识别画面中的中文/英文字幕区域,输出时间轴对齐的 SRT 文件,省去逐帧打轴的手工劳动。

📺

网课字幕制作

在线教育从业者录制了带硬字幕的教学视频,但需要为不同平台(B站、YouTube、学浪)生成独立的 SRT 字幕文件以提升搜索曝光和听障用户体验。本工具批量处理视频片段,输出标准 SRT 格式,可直接导入剪辑软件或发布平台,无需重新听写。

📜

老片字幕数字化

档案馆或怀旧观众手上有 VCD/DVD 时代的老电影(字幕已烧录在画面中),想将其提取为可编辑的文本字幕以便修复或翻译。本工具对低分辨率、浅色背景上的硬字幕仍有较高识别率,输出 SRT 后可逐句校对,比人工听写快 10 倍以上。

🎙

会议记录转写

企业内部培训或行业研讨会录制了带 PPT 字幕的录像,需要将字幕内容提取为文本存档或搜索。本工具上传视频片段后,直接输出纯文本格式(可自定义去掉时间轴),方便插入会议纪要或知识库,避免二次听写。

📱

短视频二次创作

自媒体剪辑师从海外平台下载了带硬字幕的素材,想提取字幕文案进行翻译或重新配音。本工具快速识别字幕区域并输出 SRT,可直接导入剪映/PR 生成双语字幕,或导出为纯文本用于 AI 翻译,缩短创作周期。

对比矩阵本工具 vs 竞品 vs 传统方法

维度本工具竞品 A (Subtitle Edit)传统方法 (手动听录)
数据隐私纯浏览器处理,视频不上传任何服务器需上传视频至第三方服务器或依赖本地安装完全本地,无数据外泄风险
处理速度1-3 分钟(取决于视频长度和 GPU)5-15 分钟(含上传+排队+处理)1-2 小时(10 分钟视频)
离线可用是(WASM 本地运行)否(需联网调用云端 API)
视频大小限制受浏览器内存限制(通常 2GB 以内)通常 500MB 以内(免费版)无限制
收费模式免费免费版有限制,Pro 版 $20/月免费(仅需时间成本)
注册要求无需注册,打开即用需注册账号无需注册
输出格式SRT 标准字幕文件SRT/ASS/VTT 等多种格式手动输入,格式自定
识别语言支持中英文(PaddleOCR)支持 100+ 语言(云端 OCR)取决于操作者语言能力

使用指南

上手步骤 · 输入输出 · 避坑提示

使用步骤

  1. 上传视频文件(MP4/MKV/AVI,≤500MB),或粘贴在线视频链接
  2. 选择识别引擎:PaddleOCR(中文更准)或 Tesseract(英文更稳)
  3. 点击「开始提取」,后端自动分离视频帧并识别硬字幕
  4. 下载生成的 SRT 字幕文件,或复制文本内容到剪贴板

输入输出示例7 个典型场景,覆盖常规、边界与易错

输入输出说明
一段包含清晰白色字幕的短视频片段,字幕内容为“今天天气真好”,背景为纯色1 00:00:01,000 --> 00:00:03,500 今天天气真好典型场景:白底黑字,高对比度,PaddleOCR 准确率最高
一段电影预告片,字幕为黄色艺术字体,背景是动态爆炸场景,字幕内容为“2024年上映”1 00:00:05,200 --> 00:00:07,800 2024年上映典型场景:彩色字体+复杂背景,考验 OCR 抗干扰能力
一段竖屏短视频,字幕位于画面底部,字体极小(像素高度 < 12px),内容为“关注主播不迷路”1 00:00:02,000 --> 00:00:04,500 关注主播不迷路边界 case:极小字体,Tesseract 可能漏识别,PaddleOCR 表现更稳定
一段老电影片段,字幕为繁体中文,内容为“我們的故事從這裡開始”,画面有轻微噪点1 00:00:10,000 --> 00:00:13,200 我們的故事從這裡開始边界 case:繁体字识别,PaddleOCR 内置繁体模型
一段无字幕的视频片段,只有人物对话和背景音乐(空文件,无任何 SRT 内容输出)易错 case:用户误以为工具能提取语音字幕,实际只处理画面中的硬字幕
一段包含多行字幕的视频,字幕内容为“第一行 第二行 第三行”,且每行出现时间不同1 00:00:01,000 --> 00:00:02,500 第一行 2 00:00:03,000 --> 00:00:04,500 第二行 3 00:00:05,000 --> 00:00:06,500 第三行边界 case:多行字幕逐行出现,工具按时间轴分段输出
一段视频,字幕中包含特殊符号和数字混合,如“价格:¥99.9(限时优惠)”1 00:00:15,000 --> 00:00:18,000 价格:¥99.9(限时优惠)典型场景:货币符号和括号,测试特殊字符保留能力

常见错误对照7 个常踩的坑 · 错误 → 修复

1. 上传了软字幕(内挂字幕流)而非硬字幕

错误
上传一个 MKV 文件,其中字幕是独立的 ASS/SRT 流,提取结果为空
修复
上传一个字幕已经渲染到画面像素上的视频(如压制过的 MP4,或截图)

本工具只处理硬字幕(像素级 OCR),不解析容器内的字幕轨道。软字幕需要先压制或截图,否则无像素可 OCR。

2. 视频分辨率太低导致 OCR 识别率极差

错误
上传 360p 低码率视频,字幕区域模糊,输出大量乱码
修复
上传至少 480p 以上、字幕区域清晰的视频;或先用工具放大/锐化字幕区域

Tesseract/PaddleOCR 对 24px 以下文字识别率骤降;低分辨率下字形粘连、锯齿会直接导致错字。

3. 输出 SRT 时间轴与视频实际字幕出现/消失时间严重偏移

错误
直接使用 OCR 返回的逐帧文本时间戳,未做去重/合并,导致每帧一条字幕
修复
使用工具内置的相似度去重+时间轴合并逻辑(相同文本连续帧合并为一个时间区间)

OCR 逐帧输出会产生大量重复条目;正确做法是设定文本相似度阈值(如 90%),连续相同文本只保留首尾时间戳。

4. 错误地认为 OCR 能识别所有字体和颜色

错误
上传艺术字/手写体/渐变半透明字幕,期望 100% 准确
修复
使用标准黑体/宋体、高对比度(白字黑底或黑字白底)的字幕

PaddleOCR 对标准印刷体识别率 >95%,但对花体、手写、低对比度(如灰字灰底)效果差。工具未内置字体适配层。

5. 视频时长过长导致处理超时或内存溢出

错误
上传一部 2 小时电影(1080p),等待 30 分钟后页面空白
修复
分段处理:先截取 5-10 分钟片段测试,确认参数后再处理完整视频

后端 Go 处理全视频需逐帧解码+OCR,长视频(>30 分钟)可能触发服务器超时限制(通常 60s)或 OOM。

6. 把带水印/台标/弹幕的视频当作纯字幕输入

错误
上传带 YouTube 水印和滚动弹幕的游戏视频,OCR 结果混入大量无关文字
修复
使用无遮挡、无叠加元素的视频源;或先用工具裁剪/遮挡水印区域

OCR 会识别画面中所有文字,包括水印、弹幕、LOGO。工具未做文字区域过滤,需要用户预处理。

7. 期望 OCR 自动区分对话字幕和画面内文字(如路牌、标题)

错误
上传新闻视频,输出包含标题、人名条、滚动条等所有文字,未过滤
修复
手动裁剪字幕区域(如画面底部 20% 区域),或接受全画面 OCR 结果后手动筛选

工具目前做全画面 OCR,不区分文字来源。用户需要自行裁剪画面范围或后期过滤。

工作原理

公式推导 · 流程图解 · 依据出处

核心公式

SRT = OCR(帧序列, 语言, 算法) → 时间戳对齐 → 文本行合并

变量说明

  • 帧序列 — 视频按固定间隔(如 1fps)抽取的图像帧
  • OCR — 光学字符识别,PaddleOCR 或 Tesseract
  • 语言 — 字幕语言(如中文、英文),影响识别模型
  • 算法 — PaddleOCR(高精度)或 Tesseract(轻量)
  • 时间戳对齐 — 将识别文本映射回视频时间轴
  • 文本行合并 — 跨帧去重、合并同一字幕的多行文本

示例

输入 10 分钟视频,帧率 1fps,共 600 帧。PaddleOCR 识别每帧中字幕区域,输出文本及置信度。时间戳对齐后,合并连续帧中相同文本,生成 SRT: 1 00:00:05,000 --> 00:00:08,000 欢迎使用本工具 2 00:00:12,500 --> 00:00:15,000 请上传视频文件

适用范围

适用于视频中硬编码(不可编辑)字幕的提取。对动态字幕(滚动、渐变、特效)识别率下降;对白字黑底等低对比度字幕需预处理增强。PaddleOCR 基于百度 PaddleOCR 开源模型,Tesseract 基于 Google Tesseract OCR 引擎。

原理图

上传视频MP4 / MOV帧提取FFmpeg 抽帧OCR 识别PaddleOCR / Tesseract输出 SRT字幕文件下载说明• 视频上传至后端服务器,处理完成后自动删除,不留存。• 支持选择 OCR 引擎:PaddleOCR(准确率高,适合中文)或 Tesseract(速度快,适合英文)。
用户输入 后端处理 OCR 引擎 输出结果

开发者集成

3 种主流语言 · 复制即用

import subprocess
import json
from pathlib import Path

# 使用 PaddleOCR 提取视频帧中的硬字幕
# 前置条件:pip install paddleocr paddlepaddle opencv-python

def extract_subtitles(video_path: str, output_srt: str):
    """从视频中提取硬字幕并生成 SRT 文件"""
    from paddleocr import PaddleOCR
    import cv2
    
    ocr = PaddleOCR(use_angle_cls=True, lang='ch')
    cap = cv2.VideoCapture(video_path)
    fps = cap.get(cv2.CAP_PROP_FPS)
    
    subtitles = []
    frame_idx = 0
    
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        
        # 每 30 帧处理一次(减少重复检测)
        if frame_idx % 30 == 0:
            result = ocr.ocr(frame, cls=True)
            if result and result[0]:
                text = ' '.join([line[1][0] for line in result[0]])
                if text.strip():
                    time_sec = frame_idx / fps
                    subtitles.append((time_sec, text))
        
        frame_idx += 1
    
    cap.release()
    
    # 生成 SRT 格式
    with open(output_srt, 'w', encoding='utf-8') as f:
        for i, (start_time, text) in enumerate(subtitles, 1):
            start = f"{int(start_time//3600):02d}:{int((start_time%3600)//60):02d}:{start_time%60:06.3f}"
            end_time = start_time + 1.0  # 假设每段字幕持续 1 秒
            end = f"{int(end_time//3600):02d}:{int((end_time%3600)//60):02d}:{end_time%60:06.3f}"
            f.write(f"{i}\n{start} --> {end}\n{text}\n\n")
    
    print(f"已提取 {len(subtitles)} 条字幕到 {output_srt}")

# 使用示例
extract_subtitles("input.mp4", "output.srt")
package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// 使用 Tesseract OCR 从视频帧提取字幕
// 前置条件:安装 tesseract-ocr + 中文语言包

func extractSubtitles(videoPath, outputSrt string) error {
	// 1. 用 ffmpeg 每隔 1 秒截取一帧
	framesDir := filepath.Dir(outputSrt) + "/frames"
	os.MkdirAll(framesDir, 0755)
	
	cmd := exec.Command("ffmpeg", "-i", videoPath, "-vf", "fps=1", framesDir+"/frame_%04d.png")
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ffmpeg 截帧失败: %w", err)
	}

	// 2. 对每帧进行 OCR
	subtitles := []string{}
	files, _ := filepath.Glob(framesDir + "/frame_*.png")
	
	for _, frame := range files {
		outFile := frame + ".txt"
		cmd := exec.Command("tesseract", frame, outFile[:len(outFile)-4], "-l", "chi_sim+eng", "--psm", "6")
		if err := cmd.Run(); err != nil {
			continue // 跳过 OCR 失败的帧
		}
		
		data, _ := os.ReadFile(outFile)
		text := strings.TrimSpace(string(data))
		if len(text) > 0 {
			subtitles = append(subtitles, text)
		}
	}

	// 3. 生成 SRT(简化版:每段持续 1 秒)
	var srtBuilder strings.Builder
	for i, text := range subtitles {
		start := fmt.Sprintf("%02d:%02d:%02d,000", i/3600, (i%3600)/60, i%60)
		end := fmt.Sprintf("%02d:%02d:%02d,000", (i+1)/3600, ((i+1)%3600)/60, (i+1)%60)
		srtBuilder.WriteString(fmt.Sprintf("%d\n%s --> %s\n%s\n\n", i+1, start, end, text))
	}
	
	os.WriteFile(outputSrt, []byte(srtBuilder.String()), 0644)
	os.RemoveAll(framesDir)
	
	fmt.Printf("提取完成,共 %d 条字幕\n", len(subtitles))
	return nil
}

func main() {
	if err := extractSubtitles("input.mp4", "output.srt"); err != nil {
		fmt.Fprintf(os.Stderr, "错误: %v\n", err)
		os.Exit(1)
	}
}
// 使用 Tesseract.js 在浏览器中提取视频字幕
// 前置条件:npm install tesseract.js

const Tesseract = require('tesseract.js');
const { createCanvas, loadImage } = require('canvas');
const fs = require('fs');

async function extractSubtitles(videoPath, outputSrt) {
  // 使用 ffmpeg 将视频转为帧序列(需在 Node.js 环境运行)
  const { execSync } = require('child_process');
  execSync(`ffmpeg -i ${videoPath} -vf fps=1 frames/frame_%04d.png`);

  const frames = fs.readdirSync('frames').filter(f => f.endsWith('.png'));
  const subtitles = [];

  for (let i = 0; i < frames.length; i++) {
    const imagePath = `frames/${frames[i]}`;
    
    // 使用 Tesseract.js 进行 OCR
    const { data } = await Tesseract.recognize(imagePath, 'chi_sim+eng', {
      logger: m => {} // 静默模式
    });

    const text = data.text.trim();
    if (text) {
      const timeSec = i; // 每秒一帧
      subtitles.push({ start: timeSec, text });
    }
  }

  // 生成 SRT 格式
  let srtContent = '';
  subtitles.forEach((sub, idx) => {
    const start = new Date(sub.start * 1000).toISOString().substr(11, 12).replace('.', ',');
    const end = new Date((sub.start + 1) * 1000).toISOString().substr(11, 12).replace('.', ',');
    srtContent += `${idx + 1}\n${start} --> ${end}\n${sub.text}\n\n`;
  });

  fs.writeFileSync(outputSrt, srtContent, 'utf-8');
  console.log(`已提取 ${subtitles.length} 条字幕到 ${outputSrt}`);
  
  // 清理临时帧
  fs.rmSync('frames', { recursive: true, force: true });
}

// 使用示例
extractSubtitles('input.mp4', 'output.srt').catch(console.error);

常见问题

8 个高频疑问

上传的视频有大小或时长限制吗?
有。受服务器处理能力和单次上传超时限制,目前单个视频文件最大 500MB,时长最长 60 分钟。超过这个范围的视频,建议先用本地剪辑软件(如剪映、Final Cut Pro)分割成多段,再逐段上传提取字幕。另外,视频分辨率建议不超过 4K(3840×2160),过高分辨率会大幅增加处理时间且对识别准确率没有帮助。
为什么识别出来的字幕时间轴对不上?
视频字幕 OCR 是按帧提取硬字幕,再根据字幕出现的连续帧范围推算时间轴。如果视频帧率不是标准的 24/25/30 fps,或者字幕是渐入渐出(淡入淡出)效果,工具可能出现时间偏移。可以尝试:1)确认视频源文件帧率(用 ffprobe 等工具查看),工具默认按 30fps 计算;2)如果偏移量固定,导出 SRT 后用文本编辑器批量调整时间码——比如整体提前 0.5 秒,用正则替换或在线 SRT 时间调整工具处理。
字幕识别出来的文字有很多错别字,怎么办?
识别准确率受三个因素影响:字幕字体(宋体/黑体识别率高,艺术字体低)、字幕清晰度(低分辨率或压缩严重的视频)、字幕背景复杂度(纯色背景 vs 花屏/动态背景)。PaddleOCR 对中文字幕的平均准确率约 95%,Tesseract 约 85%。如果错字集中在某些字,可以:1)在设置中选择 PaddleOCR(默认)而不是 Tesseract;2)导出 SRT 后用文本查找替换批量修正常见混淆字(如「已」「己」「巳」);3)对识别结果特别差的部分,手动截取该段字幕图片,用截图 OCR 单独处理。
这个工具和剪映的「智能字幕」有什么区别?
核心区别在于字幕来源。剪映的智能字幕是通过语音识别(ASR)将视频中的音频转为字幕,适合有人声的视频;本工具是视频字幕 OCR,从画面中提取已经存在的硬字幕(即「烧录」在视频里的文字),适合无声视频、外语视频(音频语言与字幕语言不同)或已有字幕的课程录播。如果视频既有人声又有硬字幕,两个工具可以互补使用——用剪映生成语音字幕,用本工具提取硬字幕做对照或翻译参考。
为什么上传后一直显示「处理中」,等了很久没反应?
处理时间与视频时长、分辨率和识别引擎有关。一个 10 分钟 1080p 视频用 PaddleOCR 处理大约需要 3-5 分钟,用 Tesseract 约 1-2 分钟。如果超过 10 分钟没反应,可能是:1)视频文件上传未完成(检查浏览器上传进度条);2)视频码率过高导致解码失败(尝试用格式工厂等工具重新编码为 H.264 MP4);3)服务器当前负载过高。可以刷新页面重新上传,或先换用 Tesseract 引擎快速测试是否能正常处理。
支持竖屏视频吗?字幕在画面下方会不会被切掉?
支持竖屏(9:16 比例)视频。工具默认扫描整个画面区域,如果字幕在画面底部 10% 以内,会正常识别。但有个边界情况:部分手机录制的竖屏视频,字幕被压在画面边缘,或者视频本身是横屏内容上下加了黑边(「伪竖屏」),字幕实际在画面中间区域。这种情况下,工具仍然能识别,但输出的 SRT 时间轴可能需要微调。如果不确定,可以先上传一个 10 秒的测试片段确认效果。
提取出来的字幕是乱码或全是问号,怎么回事?
通常是编码问题。如果视频是旧格式(如 AVI、WMV)或非标准编码,工具的解码模块可能无法正确读取字幕区域的像素信息,导致识别结果乱码。解决方法:1)用格式工厂、HandBrake 等工具将视频转码为 H.264 MP4,编码选「libx264」,音频编码选 AAC;2)检查视频原始字幕是否为特殊字体(如繁体楷体、日文汉字),工具主要优化了简体中文宋体/黑体识别;3)如果字幕是 Unicode 编码的特殊符号(如数学符号、箭头),目前不支持,建议手动截图后单独 OCR。
工具会保存我的视频文件吗?用完会不会被泄露?
视频文件上传到服务器后,只在处理期间暂存于内存和临时目录,处理完成后立即删除。服务端不保留任何原始视频、中间帧或识别结果。传输通道使用 HTTPS 加密。可以验证:处理完成后刷新页面,上传记录不会保留。如果需要更高隐私保障,目前没有纯浏览器端(WASM)版本,但可以对敏感视频做脱敏处理(比如模糊掉人脸)后再上传。
选择 打开 +新窗口 esc关闭