
这次我们看一个很“实用向”的视频处理场景《无垢之神》COC跑团生肉总集篇这类长视频想要快速整理剧情、做字幕、出翻译怎么用本地工具解决。如果你只是偶尔看一两集手动找字幕组可能够用。但跑团视频通常一集两三个小时总集篇更长里面还有大量的PC对话、NPC扮演、骰点描述和KP旁白。靠人听写不现实。更靠谱的做法是搭一条“视频 - 音频 - 语音识别 - 字幕 - 翻译 - 压制”的本地处理链路。这套链路不依赖某个单一整合包而是由多个开源工具组合而成。这篇文章会从环境准备开始逐步演示音频提取、ASR转写、SRT字幕生成、翻译替换、OCR硬字幕识别、字幕压制、批量任务和API接口封装。硬件方面NVIDIA显卡可以获得更快速度纯CPU也能运行只是耗时会明显增加。文中不会写死某个显存数字因为最终占用取决于你选用的模型大小、视频时长和推理参数需要以实际测试为准。1. 核心能力速览在动手之前先把这套工具链的能力边界说清楚。它不是一个“解压即用”的跑团字幕生成器而是由多个开源组件组成的字幕处理管线。这样做的好处是每个环节都可替换。比如语音识别可以换成不同模型翻译可以用本地模型也可以接授权APIOCR可以看视频有没有硬字幕再决定是否启用。能力项说明项目类型跑团/实况视频的字幕处理工具链由多个开源组件组合实现核心功能语音识别转写、SRT字幕生成、字幕翻译、OCR硬字幕识别、ffmpeg字幕压制、批量任务硬件门槛CPU可运行建议NVIDIA GPUCUDA加速显存占用按模型大小和推理参数变化需实测启动方式Python命令行启动也可用FastAPI封装为接口服务接口API可选可通过FastAPI暴露转写、翻译、压制等接口批量任务支持目录批量处理可配合shell脚本或Python脚本实现主要组件faster-whisper、ffmpeg、Tesseract/PaddleOCR、FastAPI适合场景个人字幕制作、跑团录像内容检索、二次创作素材准备、学习用途如果你的目标只是给短视频加一个简单字幕这套方案会显得“重”。但如果你要处理的是三小时以上的跑团总集篇语音识别、字幕对齐、批量处理、错误修正这些能力就很重要。尤其是跑团视频里经常有多个玩家同时说话、BGM盖过人声、人名地名生僻词多这些问题单靠一个模型往往解决不干净需要把整个流程拆开分步调整。这里还要强调一点跑团视频通常包含大量对话场景时长越长转写耗时越长中间文件也越占磁盘。建议先把单个5分钟片段跑通再扩展到全集。不要一上来就直接处理整段两三个小时的总集篇否则模型下载、显存溢出、输出乱码这些问题会一起出现排查起来很分散。2. 适用场景与使用边界这套工具链适合以下几类用户追跑团生肉但不想一直等字幕组的人可以用ASR先把对白转成文本再配合词典理解剧情。字幕组成员希望先得到一版“机器初稿”再人工校对效率会比从零打轴高很多。做跑团视频内容整理的玩家想给录像建立可搜索的文字索引方便回看关键事件。做二创的创作者需要把生肉视频的对白提取出来准备翻译、配音或剪辑素材。在讨论技术流程之前必须先把合规边界讲清楚。生肉素材通常仍然属于原作者、直播主或发行方。如果你只是自己看做本地字幕没有问题。但如果你要把生成的字幕、翻译、压制后的视频公开发布到平台或者用于商业项目必须确认你有对应素材的授权尤其是涉及人物肖像、语音和音乐版权时更要先处理授权问题。不要在未授权的情况下传播完整录播或搬运字幕。另一个边界是技术效果。“无脑转写 - 机器翻译 - 压制”确实能得到文件但质量不会在线。跑团视频中的人名、神话名词、特殊术语需要人工维护术语表机器翻译只能解决“能看懂大概”无法解决文风、角色语气和上下文一致性。所以这套工具更合理的定位是“初稿生成器”不是“最终成片器”。此外不要把它当实时字幕工具用。这里的ASR流程是离线转写处理几分钟音频需要的时间往往大于音频本身。如果要做直播实时字幕需要另选流式ASR方案不在本文讨论范围内。3. 本地部署环境准备3.1 操作系统与基础软件先确认系统环境。Windows、Linux、macOS都能跑通这套流程但建议优先选择Linux或Windows的WSL环境因为很多音频处理和模型依赖在Linux下更省事。macOS可以用CPU推理但同样需要安装ffmpeg和Python。需要准备的基础软件Python 3.9 及以上版本。ffmpeg用于音频提取和字幕压制。如果启用OCR还需要Tesseract或PaddleOCR依赖。NVIDIA显卡用户需要确认驱动和CUDA环境。检查命令如下python --version ffmpeg -version nvidia-smi如果你没有NVIDIA显卡nvidia-smi会提示找不到命令这时忽略即可后续把设备参数设为cpu。需要注意这里不要照抄别人的显存数字最终的资源占用取决于你选用的模型版本和参数。3.2 Python 与组件依赖建议创建独立虚拟环境避免把依赖装进系统Python。用下面命令创建并激活python -m venv venv source venv/bin/activate # Linux / macOS venv\Scripts\activate # Windows激活后安装核心组件。语音识别部分使用faster-whisper接口服务使用FastAPI字幕压制直接调用ffmpeg命令行pip install --upgrade pip pip install faster-whisper pip install fastapi[standard] pip install requests如果做OCR按需安装pip install Pillow pytesseractOCR还有一种选择是PaddleOCR但它依赖较多并且需要单独安装PaddlePaddle。建议先以Tesseract为主等确实遇到日文/中文硬字幕识别效果不理想时再评估PaddleOCR。3.3 模型文件准备faster-whisper首次运行时需要下载对应大小的模型。常见模型尺寸有tiny、base、small、medium、large-v3。模型越大识别准确率通常越高但显存占用和推理时间也会增加。建议在小型测试集上确定模型尺寸而不是从一开始就追求最大模型。模型文件可以提前下载并放到本地缓存目录避免每次启动都检查网络。这里不做具体的下载路径假设实际以faster-whisper文档为准。如果你的环境无法访问默认模型源需要提前规划模型分发方式比如把模型文件拷贝到离线机器。4. 安装部署与启动方式4.1 项目目录结构不管你是处理单个视频还是总集篇都建议按下面的目录组织文件subtitle-tool/ ├── input/ # 原始视频 ├── output/ # 中间音频、SRT、压制后视频 ├── models/ # 手动放置的模型文件可选 ├── scripts/ # Python脚本和shell脚本 └── venv/ # Python虚拟环境这样做的原因是跑团总集篇处理会产生很多中间文件。如果所有文件堆在同一个目录后面清理、重跑、对比都会很痛苦。脚本和素材分离也方便写批量任务。4.2 编写转写脚本在scripts目录下创建一个transcribe.py功能是读取一段音频输出带时间戳的文本。代码不需要写得复杂先把最小流程跑通from faster_whisper import WhisperModel model_size small model WhisperModel(model_size, deviceauto, compute_typeauto) def transcribe(audio_path, languageja): segments, info model.transcribe( audio_path, languagelanguage, vad_filterTrue ) lines [] for segment in segments: lines.append( f[{segment.start:.2f} - {segment.end:.2f}] {segment.text.strip()} ) return \n.join(lines) if __name__ __main__: import sys audio_file sys.argv[1] print(transcribe(audio_file))参数说明languageja表示假设语音为日语如果你要处理的素材是英语改成en。vad_filterTrue可以过滤掉静音片段减少无效转写。deviceauto会在检测到CUDA时自动用GPU没有GPU则回退到CPU。运行方式python scripts/transcribe.py input/audio.wav第一次运行会下载模型耗时取决于网络和模型大小。后续再运行只要模型缓存还在就不会重复下载。4.3 视频字幕压制生成SRT之后可以用ffmpeg直接压制到视频里。最基础的命令如下ffmpeg -i input/video.mkv -vf subtitlesoutput/ja.srt -c:v libx264 -c:a copy output/video_ja.mp4这个命令假设输出视频用H.264编码音频直接拷贝。如果SRT文件名包含特殊字符或路径包含冒号需要先转义Windows下尤其要注意。压制后先打开结果确认字幕位置和字体。5. 功能测试与效果验证把“部署完成”当成阶段目标还不够必须跑一组测试用例。下面是一套通用验证流程建议按顺序执行。5.1 测试一音频提取从原始视频中提取单声道16kHz WAV音频这是大多数ASR模型比较友好的输入格式。ffmpeg -i input/COC_video.mkv -vn -ac 1 -ar 16000 input/audio.wav预期结果input/audio.wav生成时长和原视频基本一致。如果提取后的音频没有声音检查原始视频是否有声音轨、输出路径是否可写。这个步骤看起来简单但很容易被漏掉。跑团视频往往是录播音轨格式可能是AAC、Opus、PCM直接让ASR读视频文件也可以但先转成WAV能减少后续解码问题。如果视频里带有多音轨还需要用-map指定需要的音轨。5.2 测试二语音转写用刚才的transcribe.py转写一小段音频比如先截取前3分钟测试。ffmpeg -i input/COC_video.mkv -t 180 -vn -ac 1 -ar 16000 input/audio_3min.wav python scripts/transcribe.py input/audio_3min.wav判断成功的标准是输出文本和实际语音能对应上人名、常见跑团术语错误在可接受范围。如果输出大量乱码或空行先看音频里是不是有严重BGM、回声或多人同时说话。另一个原因是模型尺寸太小可以换成base或small再试。5.3 测试三SRT字幕导出上面的转写脚本只输出带时间戳的文本要压进视频需要生成标准SRT。创建一个独立的save_srt.pyfrom faster_whisper import WhisperModel model WhisperModel(small, deviceauto, compute_typeauto) def format_ts(seconds: float) - str: ms int((seconds % 1) * 1000) s int(seconds) h, rem divmod(s, 3600) m, sec divmod(rem, 60) return f{h:02}:{m:02}:{sec:02},{ms:03} def save_srt(audio_path, output_path, languageja): segments, _ model.transcribe( audio_path, languagelanguage, vad_filterTrue ) with open(output_path, w, encodingutf-8) as f: idx 1 for segment in segments: f.write(f{idx}\n) f.write(f{format_ts(segment.start)} -- {format_ts(segment.end)}\n) f.write(f{segment.text.strip()}\n\n) idx 1 if __name__ __main__: import sys save_srt(sys.argv[1], sys.argv[2])运行方式python scripts/save_srt.py input/audio_3min.wav output/test_ja.srt预期结果SRT文件可以用播放器加载时间轴能对应语音。如果时间轴偏移检查音频提取是否使用了相同的时间基准如果SRT里出现大量重复行可能需要在转写时增加beam_size或word_timestamps等参数具体以faster-whisper文档为准。5.4 测试四翻译替换SRT内容翻译是最难做到完全自动的一步。这里不指定某个具体在线翻译服务而是给一个通用调用模板。你需要先启动一个翻译服务或申请合规的翻译API然后替换endpoint和参数。import requests def translate_text(text: str, sourceja, targetzh): # endpoint/token需要按实际服务替换 resp requests.post( http://127.0.0.1:8001/translate, json{text: text, source: source, target: target}, timeout60, ) resp.raise_for_status() return resp.json()[translated_text]批量翻译SRT时不要一句一句请求最好把整段文本合并成短句数组一次性发送减少网络往返。翻译完成后同样按SRT格式输出。这里要重点检查人名和专有名词是否保持一致建议在翻译前把术语表替换成统一写法。5.5 测试五OCR识别硬字幕如果视频内已经烧录了日文硬字幕且你希望提取这些字幕文本可以截图后用OCR。比如截取第10分钟的一帧ffmpeg -ss 00:10:00 -i input/COC_video.mkv -frames:v 1 output/frame.png然后用Tesseract识别from PIL import Image import pytesseract text pytesseract.image_to_string(Image.open(output/frame.png), langjpn) print(text)预期结果是画面中的日文字幕被提取成文本。如果识别为空先检查截图里字幕是否清晰、是否被画面边缘裁切。Tesseract对复杂背景、艺术字、渐变字效果一般这类情况建议用PaddleOCR或者在截图时手动裁剪字幕区域。不要直接把OCR文本当时间轴使用。