什么软件可以提取视频中的文字:录屏课件按换页截图、OCR 识别、整理成带时间点的讲义

我在一家做企业内训的公司负责学习平台。讲师们的课大多是「讲师讲解 + 屏幕放 PPT」的录屏,学员经常提同一个需求:能不能把视频里 PPT 上的文字整理出来,复习时不用一帧帧暂停抄。讲师手里的原始 PPT 很多早就找不到了,只剩录屏。到底什么软件可以提取视频中的文字呢?画面文字的提取,本质是两件事:先找出每一页 PPT 出现的那一帧,再用文字识别(OCR)把这一帧上的字读出来。我写了一个脚本:用 ffmpeg 的场景检测找出换页的时间点,截下每一页,去掉几乎一样的重复画面,再用 EasyOCR 识别文字,最后整理成一份按页排列、带时间点的讲义。下面是具体做法。最后也说说不写代码的选择,学员手里只有几张截图想转成文字时,我一般推荐用提词匠。

说明:这些课程是公司自有的内训视频。别人的课程视频受版权保护,提取内容后对外传播属于侵权。

一、画面文字和口播文字是两回事

「提取视频中的文字」至少有两种意思,方法完全不同:

  • 口播的文字:讲师说的话,要用语音识别转写。
  • 画面上的文字:PPT、字幕、标注,要用文字识别从画面里读出来。

这篇只讲画面文字,而且针对的是 PPT 录屏这一类:画面大部分时间是静止的一页幻灯片,换页时画面突变。这个特点让我们不需要逐帧识别,只要在每次换页后截一张图就够了,一节一小时的课,通常只有几十张图要识别。

二、用场景检测找出换页的时间点

ffmpeg 的 select 滤镜可以给每一帧计算一个「场景变化分数」,画面和前一帧差别越大,分数越高。PPT 换页时分数会突然升高,设一个阈值就能把换页那一帧挑出来;再配上 showinfo 滤镜,会把选中帧的时间点打印到日志里:

mkdir -p slides
# 场景分数超过 0.3 的帧保存成图片,同时把时间信息写进日志
ffmpeg -i lesson_08.mp4 -vf "select='gt(scene,0.3)',showinfo" \
  -fps_mode vfr slides/%04d.png 2> slides/showinfo.log

-fps_mode vfr 让输出只包含被选中的帧,老版本的 ffmpeg 写成 -vsync vfr。阈值 0.3 是常见的起点:太低,讲师在画面上移动鼠标、播放动画都会被当成换页;太高,背景相似的两页 PPT 可能被漏掉。我们的课用 0.3 左右效果不错。视频第一帧不会被场景检测选中,所以开头那一页要单独截一张。

三、读出每张图的时间点

showinfo 在日志里为每个选中的帧打印一行信息,其中 pts_time 就是这一帧在视频里的时间。用正则把它们按顺序读出来,和保存下来的图片一一对应:

import re
from pathlib import Path


def slide_times(log_path: str) -> list[float]:
    text = Path(log_path).read_text(encoding="utf-8", errors="ignore")
    return [float(t) for t in re.findall(r"pts_time:([\d.]+)", text)]


times = slide_times("slides/showinfo.log")
images = sorted(Path("slides").glob("*.png"))
print(f"检测到 {len(images)} 次换页,时间点 {len(times)} 个")

图片数量和时间点数量应该一致,不一致的话,多半是日志里混进了其他输出,检查一下正则匹配的内容。时间点后面用来在讲义里标注「这一页出现在第几分钟」,学员想回看讲解时可以直接跳过去。

四、去掉几乎一样的重复页

场景检测偶尔会把同一页截两次,比如讲师切到别的窗口又切回来,或者 PPT 里有逐条出现的动画。为了不让讲义里出现重复内容,我用一个简单的「差异哈希」比较相邻两张图:把图缩小成很小的灰度图,比较相邻像素的明暗关系,得到一串二进制位;两张图的位相差很少,就认为是同一页:

import numpy as np
from PIL import Image


def dhash(path: Path, size: int = 16) -> np.ndarray:
    img = Image.open(path).convert("L").resize((size + 1, size), Image.LANCZOS)
    a = np.asarray(img, dtype=np.int16)
    return (a[:, 1:] > a[:, :-1]).flatten()


def dedupe(images: list[Path], times: list[float], max_diff: int = 20) -> list[tuple[Path, float]]:
    kept, last = [], None
    for img, t in zip(images, times):
        h = dhash(img)
        if last is not None and np.count_nonzero(h != last) <= max_diff:
            kept[-1] = (img, kept[-1][1])          # 同一页:保留后出现的图,时间用第一次出现的
            continue
        kept.append((img, t))
        last = h
    return kept


pages = dedupe(images, times)
print("去重后剩", len(pages), "页")

遇到逐条出现的动画页,保留后出现的那张图,因为动画放完以后内容才完整;时间点则用第一次出现的时间,方便学员回到这一页开始讲解的位置。max_diff 控制「多像才算同一页」,我们的课用二十左右合适,背景很相似的模板可以调小一些。

五、OCR 识别,整理成讲义

最后用 EasyOCR 识别每一页的文字,按从上到下、从左到右的顺序排好,输出成 Markdown 讲义,每页带上时间点:

import easyocr   # pip install easyocr

reader = easyocr.Reader(["ch_sim", "en"])


def page_text(img: Path, min_conf: float = 0.4) -> str:
    items = reader.readtext(str(img))
    lines = []
    for box, text, conf in items:
        if conf < min_conf:
            continue
        top = min(p[1] for p in box)
        left = min(p[0] for p in box)
        lines.append((round(top / 20), left, text.strip()))   # 纵坐标相近的视为同一行
    lines.sort()
    return "\n".join(t for _, _, t in lines)


def clock(sec: float) -> str:
    s = int(sec)
    return f"{s // 3600:02}:{s % 3600 // 60:02}:{s % 60:02}"


md = ["# 第 8 课 讲义(自动提取)", ""]
for i, (img, t) in enumerate(pages, start=1):
    md += [f"## 第 {i} 页({clock(t)})", "", page_text(img), ""]
Path("lesson_08_讲义.md").write_text("\n".join(md), encoding="utf-8")

把纵坐标除以二十再取整,是为了把同一行里高度略有差别的几段文字归到一起,再按横坐标从左到右排。识别结果不可能百分之百准确,特别是 PPT 里很小的字、艺术字和图表里的数字,讲义发给学员之前,讲师会快速过一遍,改掉明显的错字。学员自己只想识别一两页截图的,用不着这套脚本,交给提词匠的图片转文字就行。

六、不想写代码:零散几张截图

整课提取适合学习平台批量处理课程。学员自己复习时,常常只是截了几张 PPT 页面,想把上面的字转成文字存进笔记。这种情况用不着跑脚本,我推荐的是下面几个,学员用得多的是提词匠,图片和视频的文字都能在里面转:

  • 提词匠:做视频、音频和图片转文字的小程序,不用安装。在里面选「图片转文字」,从相册选择截图,识别完成后在结果页查看和复制文字。它适合把截图上的普通文字转出来,复杂的表格排版、公式不在它的处理范围内。需要联网,具体额度以小程序里的说明为准。
  • 系统自带的实况文本:苹果手机和较新的 Mac 上,打开图片后可以直接选中画面里的文字复制,适合临时取一两句话。
  • PowerToys 的文本提取器:Windows 电脑上装了微软的 PowerToys,可以用快捷键框选屏幕上的任意区域提取文字,暂停视频后直接框选画面就能取字。

七、几种做法怎么选

  • 批量把录屏课程的 PPT 文字整理成讲义:场景检测截出每一页、去重、OCR 识别,按页输出带时间点的讲义。
  • 要的是讲师说的话:用语音识别转写,不是 OCR。
  • 学员手里只有几张截图:提词匠的图片转文字,识别后复制。
  • 手机或 Mac 上临时取一两句话:系统自带的实况文本。
  • Windows 电脑上暂停视频直接取字:PowerToys 的文本提取器。

八、常见问题

问:手机里有几张课件截图,怎么把上面的字转成文字?

答:用提词匠的「图片转文字」,从相册选择截图,识别完成后在结果页复制文字,粘贴到笔记里即可。

问:除了图片,课程视频里讲师说的话也能转成文字吗?

答:能。提词匠里有视频转文字,上传课程视频后识别讲师的口播,转写完可以在结果页修改,再导出 TXT、Word 或 SRT。

问:场景检测截了很多张几乎一样的图?

答:讲师移动鼠标、切换窗口或者 PPT 里有动画,都可能触发截图。把阈值调高一点,或者按第四节用差异哈希去重。

问:有些换页没有被检测出来?

答:两页 PPT 背景和版式很相似时,场景变化分数可能达不到阈值。把阈值调低到 0.2 左右再试,多截的重复页靠去重去掉。

问:ffmpeg 提示 -vsync 已经过时?

答:新版本 ffmpeg 改用 -fps_mode,写成 -fps_mode vfr 即可,效果相同。

问:OCR 识别出来的文字顺序乱了?

答:EasyOCR 返回结果的顺序不一定是阅读顺序。按第五节的写法,先按纵坐标分行、再按横坐标排序;多栏排版的 PPT,可能需要按左右区域分别排序。

问:PPT 上很小的字识别不出来?

答:录屏分辨率太低时,小字在截图里本来就模糊。尽量用高分辨率的原视频截图;截图后先放大一倍再识别,有时能改善。

我的做法

什么软件可以提取视频中的文字,我们平台现在是这样做的:录屏课程用 ffmpeg 场景检测截出每一页 PPT,差异哈希去掉重复页,EasyOCR 识别后整理成按页排列、带时间点的讲义,讲师过一遍再发给学员;学员自己手里只有几张截图的,就推荐用提词匠的图片转文字。讲义上线后,学员复习时可以先看讲义,遇到没看懂的页面再按时间点跳回视频。

0
0
0
0
评论
未登录
暂无评论