用 OpenCV + PaddleOCR 从短视频中提取滚动小说文字,支持纯色底和复杂背景两种模式

短视频平台上活跃着大量"滚动小说"类型的内容——画面是纯色或图片背景,文字从下往上缓慢滚动,观众像读电子书一样"读"视频。这类视频的观看体验很好,但如果你想把这些文字保存下来(做笔记、翻译、或者重新整理),就需要从视频中提取文字。

本教程介绍的方案专门针对这种滚屏文字场景,使用 OpenCV 做背景建模、PaddleOCR 做中文字识别,配合跨帧去重和 LLM 通顺性修正,最终输出干净完整的文本。

和普通字幕提取的区别

这也是 OCR 视频提取,但它处理的场景和之前介绍的视频字幕提取不同:

普通字幕提取滚屏文字提取
文字位置固定在画面底部或中间从下往上持续滚动
背景通常是半透明黑底纯色底或复杂图片
帧间变化字幕切换时才变每帧都在移动
核心挑战检测字幕区域去重 + 排序(滚屏文字在帧间可能交错)

技术流程

整个提取流程分为 4 步:

  1. 抽帧 — ffmpeg 按指定帧率从视频中提取关键帧(默认每 5 秒 1 帧)
  2. 预处理 — 根据背景类型选择模式:
    • raw 模式:直接用原图做 OCR,适合白底、米色底、橙红底等纯色背景
    • diff 模式:多帧构建背景模型(取最大值),原图减去背景后再 OCR,适合照片、水印等复杂背景
  3. OCR 识别 — PaddleOCR 逐帧识别中文字符,边缘安全区校准(排除顶部标题栏、底部进度条等非正文区域)
  4. 跨帧去重 + LLM 修正 — 消除连续帧中重复的文字,对字符误识别做通顺性修正

安装依赖

需要 Python 3.9+、ffmpeg、以及几个 Python 包。

macOS

brew install ffmpeg
pip install opencv-python numpy paddleocr paddlepaddle

# 验证
python3 -c "import cv2, paddle; from paddleocr import PaddleOCR; print('OK')"

Windows

推荐 Miniconda 独立环境,版本需锁定(PaddlePaddle 3.x 在 Windows 上有兼容问题)。

# 创建 conda 环境
conda create -n ocr python=3.10 -y
conda activate ocr

# 关键:版本必须锁定
pip install "paddlepaddle==2.6.2" "paddleocr==2.9.1" opencv-python "numpy<2"

# 安装 ffmpeg(通过 winget)
winget install Gyan.FFmpeg
winget install Microsoft.VCRedist.2015+.x64

Linux

sudo apt install ffmpeg
pip install opencv-python numpy paddleocr paddlepaddle
💡 PaddleOCR 首次运行会自动下载 OCR 模型(约 200MB),耗时 1-3 分钟,属正常现象。之后运行不需要重新下载。

选择抽帧间隔

抽帧间隔是影响提取质量的最关键参数。原则是:观察视频中一屏文字从出现到完全滚出大约需要几秒。

文字停留时长选择间隔命令参数说明
8 秒以上5 秒(默认)--fps 0.2适合大多数视频,处理最快
5-8 秒3 秒--fps 0.333滚动稍快时使用
不确定先用 5 秒--fps 0.2发现漏字再改短
漏字明显1 秒--fps 1间隔越小越完整,但耗时更长
💡 换算公式:--fps = 1 / 间隔秒数。例如你想每 3 秒抽一帧 → `--fps 0.333`。

选择背景模式

模式适用场景速度原理
--mode raw白底、米色底、橙红底等纯色背景直接用原图 OCR
--mode diff照片、水印、渐变背景等复杂画面背景减除后 OCR

运行命令

纯色底视频

python3 scripts/extract.py video.mp4 -o output.txt -y --mode raw

复杂背景视频

python3 scripts/extract.py video.mp4 -o output.txt -y --mode diff

自定义抽帧频率

# 每 1 秒 1 帧(滚动较快或漏字时)
python3 scripts/extract.py video.mp4 -y --mode raw --fps 1

# 每 10 秒 1 帧(滚动较慢,节省时间)
python3 scripts/extract.py video.mp4 -y --mode raw --fps 0.1

参数说明:

  • -o output.txt — 输出文件路径
  • -y — 跳过交互确认(所有参数已在命令行指定时使用)
  • --mode raw/diff — 背景处理模式
  • --fps N — 抽帧率
  • --crop-top N — 手动裁剪顶部 N 行(排除标题栏,可选)
  • --crop-bottom N — 手动裁剪底部 N 行(排除进度条,可选)

结果处理

脚本输出原始文本后,还需要以下步骤让文本更干净:

  1. 标点规范化 — 将英文标点替换为中文标点(,"" "),注意数字和英文单词中的保留原样
  2. 行序修正 — 滚屏文字在帧之间可能交错,需要按内容逻辑重新排序
  3. 字符修正 — 修正 OCR 常见的形近字误识别(如 "己"/"已"、"末"/"未")
  4. 引号配对 — 通读全文确保双引号左右数量一致
⚠️ 如果脚本输出中有很多半行碎片(不完整的文字行),说明边缘安全区校准不准。检查 edge-margin 校准日志,或手动调 --crop-top/--crop-bottom

常见问题

纯色底用 raw 还是 diff?

纯色底(白色、米色、单色)直接用 --mode raw,速度快且效果一样好。diff 模式是为了处理复杂背景的,用在纯色底上没必要。

抽帧间隔怎么选?

关键看文字的滚动速度。播放视频,看一屏文字从出现到完全滚出需要几秒。通常 5 秒/帧是一个好的起点,处理完发现漏字再缩短间隔。

一行文字被切成两半怎么办?

可能是抽帧时机刚好卡在文字滚动到一半的时候。缩短抽帧间隔(如从 5 秒改为 3 秒)通常能解决。如果持续出现,检查 --edge-margin 参数。

📌 本教程介绍的方法完全在本地运行,视频文件不会上传到任何服务器。适合处理包含敏感内容的视频。如需提取普通字幕(非滚动),可参考 视频字幕提取教程