whisper.cpp给视频做AI字幕:一个Java后端的不正经AI实践
原始文案摘要
我的项目有一个功能是利用AI对视频内容分析并进行概括,当然我只是做的是文本概括,所以我需要用ffmepg分离出视频的音频,音频要用wav格式,然后我找到一款可以自己部署的音频转字幕文本的项目和模型,我不想调api,AI分析才要调大模型,所以我就找到了也就是这个whisper,不过我看原本的项目是Python的,不利于生成环境和集成在我的Java项目,所以我又了解了一番有人把他改成了一个更精简的c++版 whisper.cpp,因为我的是用笔记本部署项目,我是轻薄本没有独立GPU,这个版本对CPU调用能力更强,我查找到了几种结合在我的项目的方法,第一种就是利用编译好的程序利用命令运行,第二种是利用dll文件,用java调用c++库的技术去实现,这种方法性能更好,但因为我的项目还没到抠性能的地步,我最后采用了第一种方法,我的ffmepg也是调指令的方法实现的。我下载的是一个最小的模型包,~488 MB,这个模型我实验下来发现,中文识别率还是可以的,但是对英文特别是技术英文的缩写,基本上是一窍不通。
正文
前言
事情是这样的。最近在做一个项目,需要对视频内容做分析概括。说白了就是:用户上传一个视频,后端提取视频里的文字(字幕),然后扔给大模型去总结。
这里有个关键环节:怎么把视频里的语音转成文字。
调API当然是最简单的,但一来要钱,二来有网络依赖,三来数据还得上传到别人服务器。思来想去,还是本地部署一个语音识别模型靠谱。
于是就有了这篇文章——记录我作为一个Java后端,怎么用C++版本的whisper给视频加字幕,以及踩过的坑。
一、需求拆解
先理一下整个流程:
-
用户上传视频
-
后端用ffmpeg分离出音频
-
音频转成wav格式(whisper要吃wav)
-
用whisper把音频转成字幕文本
-
把文本扔给大模型做分析
今天主要说第2-4步,核心就是:怎么在Java项目里调用whisper。
二、选型:为什么是whisper.cpp
原始项目:openai/whisper
OpenAI官方出的whisper,Python写的,效果确实好。但问题也明显:
-
Python环境部署麻烦(虚拟环境、依赖包)
-
内存占用大
-
在无GPU的机器上跑起来吃力
-
和Java项目集成需要起Python服务
转机:whisper.cpp
有个大佬把whisper用C++重写了,就是 ggerganov/whisper.cpp。
优点:
-
零依赖:编译出来就是一个可执行文件
-
CPU优化好:在无GPU的轻薄本上也能跑
-
内存占用低:官方说比Python版省很多
-
集成简单:Java直接调命令行,或者用JNI调dll
缺点:
-
配置编译稍微有点门槛
-
英文缩写的识别确实差点意思(后面细说)
三、部署过程(参考掘金那篇文章)
我在掘金看到一篇教程:零依赖、高效率的语音转文字c++版 whisper.cpp,基本就是按这个来的。
1. 下载whisper.cpp
bash
git clone https://github.com/ggerganov/whisper.cpp cd whisper.cpp
2. 编译
bash
# 先下载模型(我选的是最小的tiny模型) bash ./models/download-ggml-model.sh tiny # 编译主程序 make
编译完会生成一个 main 可执行文件,这就是核心了。
3. 模型选择
whisper有多个模型,从tiny到large,体积和准确率递增。我用的是tiny模型,488MB左右。
| 模型 | 大小 | 中文识别 | 速度 | 英文缩写识别 |
|---|---|---|---|---|
| tiny | 488MB | 还行 | 快 | 差 |
| base | 1.4GB | 不错 | 中等 | 一般 |
| small | 4.6GB | 好 | 慢 | 较好 |
我最后选tiny,因为项目对速度有要求,而且主要识别中文。但后面发现一个问题:英文技术缩写基本识别不出来。
比如"API"会变成"阿皮"或"a p i","CPU"变成"西皮优"。这个后面再说。
四、集成到Java项目:我选的是命令行方案
方案一:命令行调用(我用的)
java
ProcessBuilder pb = new ProcessBuilder(
"/path/to/whisper.cpp/main",
"-m", "/path/to/models/ggml-tiny.bin",
"-f", "/path/to/audio.wav",
"-osrt", // 输出srt字幕文件
"-of", "/path/to/output"
);
Process process = pb.start();
int exitCode = process.waitFor();
优点:实现简单,几分钟搞定。
缺点:每次都要启动进程,有额外开销。
方案二:JNI调用dll(没采用)
把whisper.cpp编译成dll,用JNI调用。性能更好,但需要写C++胶水代码,我懒得折腾。
方案三:起个Python服务(没采用)
用Flask包装官方whisper,Java调HTTP接口。简单但多了网络开销,还得维护Python环境。
目前暂时用方案二顶着,等需求更强烈了再换大模型。
五、ffmpeg处理音频
音频处理也是调命令行:
java
ProcessBuilder pb = new ProcessBuilder(
"ffmpeg",
"-i", videoPath,
"-ar", "16000", // 采样率16000,whisper推荐
"-ac", "1", // 单声道
"-c:a", "pcm_s16le", // wav格式
audioPath
);
这一步没啥坑,ffmpeg稳定得很。
六、遇到的问题和解决
1. 英文缩写识别问题(未完全解决)
tiny模型对英文技术词汇识别确实差。试了几个方案:
方案一:换大模型
换base模型好一些,但速度慢了,体积也大了。
方案二:后处理替换
在Java里做正则替换,把常见的"阿皮"替换回"API"。这个可以解决部分问题,但不可能穷举所有缩写。
方案三:热词增强(whisper.cpp支持)
whisper.cpp支持用 --prompt 参数提示,效果有限。
目前暂时用方案二顶着,等需求更强烈了再换大模型。
2. 启动速度
每次调用都要加载模型,488MB加载到内存要一两秒。如果频繁调用,可以考虑:
-
把main做成常驻服务
-
用方案二的dll方式
但我的场景是用户上传视频,频率不高,所以无所谓。
3. 内存占用
tiny模型运行时占用内存约500MB,轻薄本8GB内存,完全扛得住。large模型就够呛了。
七、最终效果
整套流程跑下来:
-
上传一个10分钟的视频
-
ffmpeg处理音频(几秒)
-
whisper转字幕(small模型约3-5分钟)
-
得到srt字幕文件
-
扔给大模型分析
中文识别率80%左右,英文缩写得靠后处理。对于内部项目来说,够用了。
八、总结
| 步骤 | 工具 | 耗时 | 备注 |
|---|---|---|---|
| 音频分离 | ffmpeg | 几秒 | 稳定 |
| 语音转文字 | whisper.cpp | 3-5分钟/10分钟视频 | small模型 |
| 文本后处理 | Java正则 | 瞬间 | 补英文缩写 |
一点建议
-
如果是Java项目,命令行调用whisper.cpp是最快的集成方式
-
模型别贪大,够用就行(我的教训)
-
英文缩写识别不行,要么换大模型,要么后处理
-
轻薄本无压力,内存占用可控
成本统计
| 项目 | 价格 | 备注 |
|---|---|---|
| whisper.cpp | 0元 | 开源 |
| 模型文件 | 0元 | 免费下载 |
| ffmpeg | 0元 | 开源 |
| 总计 | 0元 | 白嫖真香 |
最后问一句:你的项目也需要本地语音识别吗?用的什么方案?评论区聊聊。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)