ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

本地管线挖掘剧情:从语音转写到实体关联的文本分析

本地管线挖掘剧情:从语音转写到实体关联的文本分析 “在最终章海兰德铁道学院在干什么”——如果只看原文这个问题往往要翻几十章内容把对话、行动、组织决策一点点拼起来。但换个角度这个问题本质上是一个非结构化文本分析任务把“学院最终都在做什么”变成可查询、可验证、可批量处理的数据问题。这篇文章不猜剧情也不下剧情结论而是用一整套本地可跑的工程管线把最终章里与“海兰德铁道学院”相关的行为线索抽出来视频转写、OCR 截图、全文检索、实体关联、本地 LLM 问答。跑通之后你不仅能回答这个标题还能把它复用到任何长篇作品、项目文档、会议记录的分析场景。这套管线完全离线可用核心组件包括 faster-whisper、PaddleOCR、SQLite、jieba 和 Ollama。它支持 CPU 推理也支持 GPU 加速支持单文件测试也支持批量任务支持本地接口 API方便接到自己的工具链里。整条链路不依赖云端服务不限制输入格式不绑定具体显卡品牌。对只是想梳理剧情线的内容读者来说它是把“人肉翻书”变成“代码检索”的辅助工具对做知识库、文档分析、视频内容归档的开发者来说它就是一个可以直接改造成业务代码的通用模板。本文会带读者完成以下内容先搭好 Python 环境和本地模型服务再把一本小说、一份字幕或一批视频截图转成纯文本接着把文本导入 SQLite 做检索用分词和实体共现判断“学院”与哪些角色、地点、事件高度关联最后用 Ollama 本地大模型做行为抽取与摘要问答。整个流程会给出可复制的代码示例、接口调用示例和批量任务脚本。1. 剧情分析的本地管线核心能力速览在动手之前先把这套“剧情考据管线”的能力边界说清楚。它不是一个已经训练好的剧情问答模型而是一组开源工具的组合。下面的表格列出了每个环节使用的工具、输入和输出。能力项说明项目类型本地剧情/长文本文本挖掘管线由多个开源组件组合文本来源视频/音频字幕、图片截图、TXT/EPUB/PDF 文本、SRT 字幕文件主要功能语音转写、OCR 识别、全文检索、实体共现、本地 LLM 问答、批量任务默认组件faster-whisper、PaddleOCR、SQLite、jieba、Ollama推理设备支持 CPU也支持 NVIDIA GPU具体显存占用按模型版本实测启动方式命令行 Python 脚本 Ollama 本地服务是否支持 API支持Ollama 提供 HTTP 接口可被 Python/curl 调用是否支持批量任务支持可遍历输入目录逐条处理建议加日志和失败重试是否需要联网首次下载模型需要联网后续推理可完全离线适合场景长篇小说剧情梳理、游戏最终章分析、网文角色行为追踪、视频字幕归档不适合场景对官方剧情结论做自动判定、大规模爬取未授权文本这套方案的重点不是“智能”而是“可查”。把最终章里所有和“海兰德铁道学院”有关的内容抽出来之后你会得到一本带时间戳、带来源路径、带上下文引用的小型数据库。后面的分析是基于数据而不是凭印象。2. 适用场景与使用边界先说适合谁。适合内容研究者、剧情考据爱好者和知识库开发者。假设你要分析一部几十万字的网文或一部几十集的动画想搞清楚某个学院在最后阶段调动了哪些人物、提出了什么方案、最终结果如何。手动搜索关键词可以得到零散片段但很难形成时间线。更麻烦的是同一个学院在不同章节可能有不同称呼比如“海兰德铁道学院”“海兰德学院”“铁道学院”同时在文本中出现。只用 CtrlF 会漏掉很多上下文。适合需要把视频/音频内容转成文字的人。很多剧情关键信息藏在配音、字幕和闪回画面里。faster-whisper 可以把视频轨里的语音转成带时间戳的文本PaddleOCR 可以把截图里的台词、公告、信件识别出来。两者合在一起基本能把最终章的场景文案全部落盘。适合需要批量处理多个章节或多个作品的人。这个管线支持遍历 input 目录下的所有文件自动输出到 output 目录。第一次跑通后后续喂入新文件就行。再说不适合什么。不适合用来直接生成“官方剧情答案”。本地模型会根据上下文生成摘要但摘要带有模型自身理解和官方设定不是一回事。它只是辅助人判断不能替代最终的人工复核。不适合处理未授权的版权内容。如果文本、视频、截图来自平台独占的付费内容请只用于个人学习笔记不要公开传播。涉及人脸、声音、实名信息的素材在使用前必须确认授权范围。这篇文章只讨论技术方法不鼓励任何绕过版权边界的操作。3. 本地部署环境准备与前置条件这套方案的核心运行环境是 Python 3.10外加一个 Ollama 本地模型服务。操作系统方面Windows、Linux、macOS 都可以跑但语音转写和 OCR 在 Linux 上的 CUDA 环境通常更好配置。3.1 硬件要求CPU可以跑建议至少 8 核在 CPU 上做语音转写会比较慢但能出结果。GPU有 NVIDIA 显卡且显存足够时推荐用 GPU 推理显存占用由模型版本、视频长度、并发数决定需以本机实测为准。内存至少 16GB 更稳妥转写长视频时内存占用会显著上升。磁盘预留 10GB 以上空间。模型文件、虚拟环境、输出文本都会占空间。3.2 软件依赖需要安装Python 3.10 或更高版本ffmpeg用于处理视频/音频流SQLite一般 Python 自带Ollama用于本地 LLM 服务Tesseract 或 PaddleOCR二选一中文场景建议 PaddleOCR3.3 创建项目目录和解压环境建议把输入素材、输出结果、数据库、脚本分成独立目录。mkdir -p analysis/input analysis/output analysis/db analysis/scripts cd analysis这样做的目的是让每个环节互不干扰。视频文件放在 input脚本输出统一写在 output数据库单独放 db后续做批量任务时不会把中间文件混在一起。3.4 安装 Python 依赖python -m venv .venv # Windows 激活方式 .venv\Scripts\activate # Linux/macOS 激活方式 source .venv/bin/activate pip install --upgrade pip pip install faster-whisper paddleocr paddlepaddle jieba requests如果是在 macOS 上使用 MPS 或纯 CPUPaddlePaddle 的安装命令可能需要根据官方文档调整。这里给出的是通用安装方式具体版本以本机环境为准。3.5 安装并启动 OllamaOllama 是一个本地模型运行工具安装完成后先启动服务再拉取一个适合中文摘要的模型。# 拉取一个 7B 级别的中文指令模型网络时间取决于带宽 ollama pull qwen2.5:7b-instruct # 启动服务默认监听 127.0.0.1:11434 ollama serve如果ollama serve已经作为后台服务运行终端会出现端口占用的提示这也是正常的。可以通过下面命令验证服务是否可用curl http://127.0.0.1:11434/api/tags能返回 JSON 列表说明 Ollama 服务已经就绪。4. 安装部署与启动验证依赖装完不要急着直接跑完整分析。应该先做三个门槛检查语音转写能否跑通、OCR 能否识别一张截图、Ollama 能否返回一句话。这三个小实验通过说明环境本身没问题。4.1 验证 faster-whisper 语音转写新建一个scripts/test_whisper.py脚本读取 input 目录下的一段短视频或音频文件输出带时间戳的文本。from faster_whisper import WhisperModel # 模型大小可选 tiny/base/small/medium/large-v3 # 第一次运行会自动下载模型 model WhisperModel(base, deviceauto, compute_typeint8) segments, info model.transcribe( input/final_chapter_demo.mp4, languagezh, word_timestampsTrue, vad_filterTrue, ) print(f检测语言: {info.language}, 概率: {info.language_probability:.2f}) for segment in segments: print(f[{segment.start:.2f} - {segment.end:.2f}] {segment.text.strip()})运行方式python scripts/test_whisper.py如果看到带时间戳的句子输出说明转写链路可用。没有输出时先检查文件路径、ffmpeg 是否安装、模型是否下载完整。4.2 验证 PaddleOCR 文字识别再建一个scripts/test_ocr.py脚本读取 input 目录下的一张截图输出图上文字。from paddleocr import PaddleOCR ocr PaddleOCR(use_angle_clsTrue, langch, show_logFalse) result ocr.ocr(input/screenshot_01.png, clsTrue) if result: for page in result: if page: for line in page: print(line[1][0]) else: print(未识别到文字)运行方式python scripts/test_ocr.py识别结果包含中文、数字、标点时说明 OCR 环境正常。识别乱码时可以先检查图片分辨率再检查 PaddleOCR 模型文件是否完整。4.3 验证 Ollama 文本生成新建一个scripts/test_ollama.py脚本直接调用 Ollama 的本地接口让模型返回一句简单回答。import requests url http://127.0.0.1:11434/api/generate payload { model: qwen2.5:7b-instruct, prompt: 用一句话解释什么是剧情时间线梳理, stream: False, options: { temperature: 0.7, num_predict: 200 } } resp requests.post(url, jsonpayload, timeout300) resp.raise_for_status() print(resp.json()[response])运行方式python scripts/test_ollama.py能返回一句中文内容说明本地 LLM 服务可用。如果请求超时先确认 Ollama 服务进程是否还在再看端口是否被防火墙拦截。5. 功能测试与效果验证把最终章变成可查询文本三个小实验通过后进入完整流程。这里按“文本采集 - 入库检索 - 实体关联 - LLM 行为抽取”的顺序展开。5.1 语音转写处理最终章的视频与音频假设最终章素材是一段约 20 分钟的视频包含了片头解说、角色对话和旁白。把这个视频放进input/final_chapter.mp4然后运行批量转写脚本。import os import glob from faster_whisper import WhisperModel model WhisperModel(base, deviceauto, compute_typeint8) files sorted(glob.glob(input/*.mp4)) print(f共发现 {len(files)} 个视频文件) for idx, path in enumerate(files, 1): base os.path.splitext(os.path.basename(path))[0] out_txt os.path.join(output, base .txt) out_srt os.path.join(output, base .srt) try: segments, _ model.transcribe( path, languagezh, vad_filterTrue, ) with open(out_txt, w, encodingutf-8) as f: for seg in segments: f.write(seg.text.strip() \n) print(f[{idx}/{len(files)}] 转写完成: {path}) except Exception as exc: print(f[{idx}/{len(files)}] 转写失败: {path} - {exc})转写成功后output/final_chapter.txt就是最终章字幕的纯文本版本。判断标准文件里出现完整句子且能够搜到“海兰德铁道学院”等实体词。如果出现大量空行说明vad_filterTrue可能过滤掉了部分弱语音可以改成vad_filterFalse再试。5.2 OCR 截图识别处理画面中的文字很多关键信息并不出现在语音里而是出现在画面中的公告、报纸、指示牌上。把最终章的截图放在input/screenshots/目录下运行 OCR 脚本。import os import glob from paddleocr import PaddleOCR ocr PaddleOCR(use_angle_clsTrue, langch, show_logFalse) files sorted(glob.glob(input/screenshots/*.png)) for path in files: base os.path.splitext(os.path.basename(path))[0] out_path os.path.join(output, base _ocr.txt) result ocr.ocr(path, clsTrue) lines [] for page in result or []: for line in page or []: lines.append(line[1][0]) with open(out_path, w, encodingutf-8) as f: f.write(\n.join(lines)) print(f{base}: 识别到 {len(lines)} 行文字)判断标准输出文件中包含与剧情相关的关键词。截图模糊、文字过小、旋转角度过大时识别效果会下降。可以先对截图做放大和灰度处理再进入 OCR。5.3 全文检索定位“海兰德铁道学院”的每一次出现文本采集完成后把所有 txt 文件导入 SQLite。这里使用最简单的方式以行为单位存储文本方便后续检索。import sqlite3 import glob conn sqlite3.connect(db/plot_analysis.db) conn.execute(CREATE TABLE IF NOT EXISTS lines (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT, line_index INTEGER, content TEXT)) for txt_path in sorted(glob.glob(output/*.txt)): source txt_path.split(/)[-1] with open(txt_path, r, encodingutf-8) as f: lines f.readlines() for idx, line in enumerate(lines): line line.strip() if line: conn.execute( INSERT INTO lines (source, line_index, content) VALUES (?, ?, ?), (source, idx, line), ) conn.commit() print(入库完成)随后检索“海兰德铁道学院”出现的上下文import sqlite3 conn sqlite3.connect(db/plot_analysis.db) rows conn.execute( SELECT source, line_index, content FROM lines WHERE content LIKE %海兰德铁道学院% ORDER BY source, line_index LIMIT 30 ).fetchall() for source, idx, content in rows: print(f{source} 第{idx}行: {content})判断标准检索结果能覆盖多集、多时间段而不是只出现在某一两个段落里。如果结果过少说明需要补充同义词比如“海兰德学院”“铁道学院”再查一次。5.4 实体关联用 jieba 寻找高频共现实体要回答“学院在干什么”不能只看学院自己的句子还要看它和谁一起出现。用 jieba 分词把一句话中的实体词抽取出来统计与“海兰德铁道学院”出现在同一个句子中的其他实体。import jieba import sqlite3 from collections import Counter # 添加自定义词典 jieba.add_word(海兰德铁道学院) jieba.add_word(海兰德学院) jieba.add_word(铁道学院) conn sqlite3.connect(db/plot_analysis.db) rows conn.execute(SELECT source, content FROM lines WHERE content LIKE %海兰德铁道学院%).fetchall() co_occur Counter() for source, content in rows: words jieba.lcut(content) for w in words: w w.strip() if len(w) 2 and w ! 海兰德铁道学院: co_occur[w] 1 for word, count in co_occur.most_common(20): print(word, count)判断标准高频共现词里应该能看到几个角色名、地名或事件名。这些词就是学院行动的“上下文锚点”。如果高频词全是“我们”“他们”“已经”等无意义词需要加入停用词表或者把候选词长度提高到 3 个字以上。5.5 本地 LLM 行为抽取让模型回答“学院在干什么”检索完上下文后把包含“海兰德铁道学院”的句子拼成一段上下文交给 Ollama 做行为抽取。import requests import sqlite3 conn sqlite3.connect(db/plot_analysis.db) rows conn.execute( SELECT content FROM lines WHERE content LIKE %海兰德铁道学院% ORDER BY source, line_index ).fetchall() context \n.join([r[0] for r in rows]) if len(context) 3000: context context[:3000] \n…… prompt f 下面是从剧情文本中检索到的与“海兰德铁道学院”相关的上下文 {context} 请基于以上上下文用 3 个要点概括在最终章海兰德铁道学院在干什么 要求 1. 只能基于上下文不要虚构事实。 2. 每个要点不超过 50 字。 3. 如果上下文不足请直接说“信息不足”。 resp requests.post( http://127.0.0.1:11434/api/generate, json{ model: qwen2.5:7b-instruct, prompt: prompt, stream: False, options: {temperature: 0.2, num_predict: 500}, }, timeout300, ) resp.raise_for_status() print(resp.json()[response])判断标准模型能输出与原始上下文一致的要点而不是编造出不存在的剧情。此时得到的要点只是“辅助结论”需要再回到原始文本里核对一遍。6. 接口 API 与批量任务设计整套管线可以只用命令行运行但如果要接到自己的知识库、定时任务或网页服务上就需要把关键环节接口化。Ollama 本身就提供 HTTP APIfaster-whisper 和 PaddleOCR 也可以在 Python 里封装成函数。6.1 Ollama API 调用示例Ollama 默认监听127.0.0.1:11434常用路径是/api/generate。一个完整请求体如下{ model: qwen2.5:7b-instruct, prompt: 请回答海兰德铁道学院在最终章做了哪些事, stream: false, options: { temperature: 0.2, num_predict: 300 } }Python 调用方式import requests url http://127.0.0.1:11434/api/generate payload { model: qwen2.5:7b-instruct, prompt: 请回答海兰德铁道学院在最终章做了哪些事, stream: False, options: { temperature: 0.2, num_predict: 300 } } resp requests.post(url, jsonpayload, timeout300) resp.raise_for_status() print(resp.json()[response])6.2 批量任务目录设计批量任务的关键是输入输出隔离。建议目录结构如下analysis/ ├── input/ │ ├── final_chapter.mp4 │ ├── episode_23.mp4 │ └── screenshots/ ├── output/ │ ├── final_chapter.txt │ └── episode_23.txt ├── db/ │ └── plot_analysis.db └── scripts/ ├── transcribe_all.py ├── ocr_all.py ├── build_db.py └── ask_ollama.py批量转写脚本要加日志和失败重试逻辑。最简单的做法是写一个process_one函数内部捕获异常外部循环里记录成功和失败数量。import os import glob import time from faster_whisper import WhisperModel model WhisperModel(base, deviceauto, compute_typeint8) def transcribe_one(path): segments, _ model.transcribe(path, languagezh, vad_filterTrue) base os.path.splitext(os.path.basename(path))[0] out_path os.path.join(output, base .txt) with open(out_path, w, encodingutf-8) as f: for seg in segments: f.write(seg.text.strip() \n) return out_path files sorted(glob.glob(input/*.mp4)) ok 0 fail 0 for p in files: try: out transcribe_one(p) print(f成功: {p} - {out}) ok 1 except Exception as exc: print(f失败: {p} - {exc}) fail 1 time.sleep(1) print(f完成成功 {ok} 个失败 {fail} 个)批量任务最容易踩的坑是模型第一次加载耗时较长但每个文件都重新加载模型。解决办法是让模型常驻内存在脚本开头只加载一次。同理OCR 模型也建议全局只初始化一次。7. 资源占用与性能观察方法这套管线不是单一程序资源占用要分模块看。7.1 怎么观察资源占用GPU 显存终端执行nvidia-smi或者在 Python 里使用torch.cuda.memory_allocated()观察。CPU 和内存Linux 用topWindows 用任务管理器。Ollama 服务Ollama 会在模型加载后常驻内存具体占用取决于模型大小和量化版本。需要特别说明的是显存占用会随着模型版本、输入视频长度、并发任务数变化。一个 7B 模型在量化后的占用和一个 13B 模型完全不同。更稳妥的做法是先跑一个 30 秒的短视频观察峰值显存和内存再决定是否用更大的模型。7.2 不同参数对性能的影响语音转写模型大小tiny最快但准确率较低large-v3更准但占用资源和时间明显上升。OCR 图片分辨率原图过大时可以先压缩再识别原图过小时先放大再识别。LLM 输出长度num_predict控制生成的 token 数输出越长等待时间越久。并发数Ollama 默认可以并发处理请求但并发过高会导致显存溢出。批量任务建议先并发数设为 1跑通后再逐步调大。7.3 降低资源占用的方法语音转写使用compute_typeint8占用显存显著低于 float16。OCR 和 whisper 不要在同一个进程里同时初始化大模型分步骤执行。LLM 使用量化版本比如qwen2.5:7b-instruct-q4_K_M比原版占用更小。长视频先切片再分批转写避免一次性加载太长的音频。8. 常见问题与排查方法问题现象可能原因排查方式解决方案faster-whisper 转写结果为空ffmpeg 未安装或视频文件损坏检查 ffmpeg 是否可用用播放器打开视频安装 ffmpeg重新下载素材文件OCR 识别乱码图片模糊、旋转角度过大、文字过小查看原图放大截图对图片做灰度化、放大、矫正后再识别SQLite 查不到关键词文本库未导入或关键词用词不一致检查 output 目录文件是否存在使用同义词再查重新执行入库脚本补充同义词检索Ollama 请求超时模型未加载完成或生成的 token 数过长查看 Ollama 日志缩短 prompt首次请求前先发送一个短测试请求降低 num_predict显存不足模型过大或并发请求过多运行 nvidia-smi 查看显存换成更小的模型减少并发数批量任务中途失败某个文件格式不被支持查看脚本日志定位失败文件对异常文件单独处理添加失败重试逻辑端口 11434 被占用Ollama 服务重复启动或端口被第三方程序占用执行lsof -i :11434或netstat -ano停掉冲突进程或修改 Ollama 监听端口上面这些问题是本地部署最常见的大部分都能通过日志定位。建议在所有脚本里统一打印时间、文件名和错误信息排查效率会提高很多。9. 最佳实践与使用建议第一次做剧情分析不要直接对整个长篇作品跑完整流程。先用最终章的 1 集视频或 10 页文本做小样本验证确认转写、OCR、检索、问答四个环节都能跑通再扩展规模。目录管理要严格。input、output、db、scripts 四个目录从开始就分开避免模型文件、中间文本、数据库混在一起。后续清理或重新处理时只需要清空 output 目录。自定义词典要维护。分析“海兰德铁道学院”这类专有名词时jieba 默认分词可能把它切成“海兰德 / 铁道 / 学院”。在脚本里加入jieba.add_word(海兰德铁道学院)检索结果会更完整。批量任务一定要加日志。一个文件失败不应该中断整个队列。推荐的策略是先顺序执行每个文件都 try/except 捕获异常跑通之后再改成多线程或异步。日志里至少记录文件名、成功/失败、耗时和输出路径。使用 Ollama 接口时不要把服务暴露到公网。本地服务默认只绑定127.0.0.1如果在服务器上使用建议通过反向代理加上鉴权避免未授权访问。合规方面要特别注意如果文本、图片、视频来自商业作品或他人创作只能用于个人分析不要公开传播完整原文如果素材包含真实人物、声音或私人信息使用前必须确认授权。不要用公共 API 上传敏感或未授权数据。10. 总结与下一步回到最初的问题“在最终章海兰德铁道学院在干什么”用这套管线跑完后你会得到一份可追溯的答案哪个时间点、哪个场景、哪些角色、哪些行为与学院相关。最终判断还是要回到原始文本里核对但检索和梳理过程已经做完不需要再翻几十章。最先要验证的功能是语音转写和 OCR 识别这两步决定了后续文本维度的完整性最容易踩的坑是模型首次加载时间过长和 OCR 图片质量不佳建议先用小文件测试。后续还可以继续扩展把输出结果导入 RAG 框架做带引用的问答系统用 NetworkX 建立角色共现图观察学院与各阵营的关系变化或者对每一章的摘要做时间线排序生成事件演化报告。工具链已经具备剩下的就是给素材建好输入目录然后跑起来试试。
返回列表