【JAVA】使用vosk和FunSAR、whisper-cli实现windows实时语音转文字,解放双手
- 使用VOSK
- 使用FUNASR
- 参考
- 模型下载
- 安装
- 包安装
- windows ffmpeg安装
- 代码
- 使用whisper.cpp
- 安装依赖
- cpp下载地址
- 下载模型
- 如何使用
- python代码调用
- 总结
使用VOSK
使用到的三方包
jna-5.11.0.jar jna-platform-5.11.0.jar vosk-0.3.45.jar
具体代码实现
packagesample;importorg.vosk.Model;importorg.vosk.Recognizer;importjavax.sound.sampled.*;importjava.awt.*;importjava.awt.datatransfer.StringSelection;importjava.awt.event.KeyEvent;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;/** * https://alphacephei.com/vosk/models * vosk.alphacephei.com * https://repo1.maven.org/maven2/com/alphacephei/vosk/0.3.45/ */publicclassVoskJavaExample{// 音频格式参数配置privatestaticfinalAudioFormat.EncodingENCODING=AudioFormat.Encoding.PCM_SIGNED;privatestaticfinalfloatRATE=16000.0f;// 采样率privatestaticfinalintSAMPLE_SIZE=16;// 采样位数privatestaticfinalintCHANNELS=1;// 声道数(1-单声道,2-立体声)privatestaticfinalbooleanBIG_ENDIAN=true;// 字节顺序publicstaticvoidmain(String[]args){writeOutResult(getVoiceDoc());}publicstaticvoidwriteOutResult(StringwavPath){try{// 1. 加载模型(替换为你的模型路径,如"vosk-model-cn-0.22")// Model model = new Model("D:\\download\\vosk-model-cn-0.22\\vosk-model-cn-0.22");Modelmodel=newModel("D:\\download\\vosk-model-small-cn-0.22\\vosk-model-small-cn-0.22");// 2. 初始化识别器(采样率必须与音频文件一致,此处为16000Hz)org.vosk.Recognizerrecognizer=neworg.vosk.Recognizer(model,16000.0f);// 3. 读取音频文件(需为符合要求的WAV文件)try(FileInputStreamfis=newFileInputStream(wavPath)){byte[]buffer=newbyte[4096];// 缓冲区大小intbytesRead;// 4. 逐段处理音频流while((bytesRead=fis.read(buffer))!=-1){// 调用acceptWaveform,传入字节数组和实际读取的长度if(recognizer.acceptWaveForm(buffer,bytesRead)){// 输出实时识别结果Stringresult=recognizer.getResult();System.out.println("实时结果:"+result);}}// 5. 处理剩余音频,输出最终结果Stringresult=recognizer.getFinalResult();System.out.println("最终结果:"+result);result=result.replaceAll("}","").replaceAll("\"text\" : \"","").replaceAll("\"","").replaceAll("\\{","").replaceAll(" ","");System.out.println("最终结果1:"+result);typeChinese(result);}// 释放资源model.close();recognizer.close();}catch(IOExceptione){e.printStackTrace();}}publicstaticStringgetVoiceDoc(){try{// 1. 设置音频格式AudioFormatformat=newAudioFormat(ENCODING,RATE,SAMPLE_SIZE,CHANNELS,(SAMPLE_SIZE/8)*CHANNELS,RATE,BIG_ENDIAN);// 2. 获取音频输入设备(麦克风)DataLine.Infoinfo=newDataLine.Info(TargetDataLine.class,format);if(!AudioSystem.isLineSupported(info)){System.err.println("不支持指定的音频格式");returnnull;}// 3. 打开并启动录音线路TargetDataLineline=(TargetDataLine)AudioSystem.getLine(info);line.open(format);line.start();System.out.println("开始录音...(按回车键停止)");// 4. 创建音频输入流AudioInputStreamaudioInputStream=newAudioInputStream(line);// 5. 创建输出文件FileaudioFile=newFile("D:\\download\\savedVoice\\recording.wav");// 6. 启动独立线程处理录音停止newThread(()->{try{// 等待用户输入停止System.in.read();line.stop();line.close();System.out.println("录音已停止");}catch(IOExceptione){e.printStackTrace();}}).start();// 7. 将音频流写入文件AudioSystem.write(audioInputStream,AudioFileFormat.Type.WAVE,audioFile);System.out.println("录音已保存到:"+audioFile.getAbsolutePath());}catch(LineUnavailableException|IOExceptione){e.printStackTrace();}return"D:\\download\\savedVoice\\recording.wav";}/** * 模拟输入中文文本(通过剪贴板+粘贴实现) * @param text 要输入的中文文本 */privatestaticvoidtypeChinese(Stringtext){Robotrobot=null;try{robot=newRobot();}catch(AWTExceptione){e.printStackTrace();}// 1. 将文本复制到系统剪贴板StringSelectionselection=newStringSelection(text);Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection,null);// 2. 模拟Ctrl+V粘贴robot.keyPress(KeyEvent.VK_CONTROL);// 按下Ctrlrobot.keyPress(KeyEvent.VK_V);// 按下Vrobot.delay(100);// 短暂延迟,确保粘贴生效robot.keyRelease(KeyEvent.VK_V);// 释放Vrobot.keyRelease(KeyEvent.VK_CONTROL);// 释放Ctrl// 3. 延迟一段时间,避免连续操作冲突robot.delay(300);}}代码最新版本
https://gitee.com/likexiang/source-code-records/blob/master/java/VoiceToTxt.java
使用FUNASR
参考
github链接:https://github.com/modelscope/FunASR/blob/main/README_zh.md
模型下载
punc使用的模型,punc_model的参数
【加标点】punc_ct-transformer_zh-cn-common-vocab272727-pytorch
https://www.modelscope.cn/models/iic/punc_ct-transformer_cn-en-common-vocab471067-large/files
主要使用的模型,model的参数
【Paraformer语音识别-中文-通用-16k-离线-large-长音频版】speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch
https://www.modelscope.cn/models/iic/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch
安装
包安装
python>=3.8
torch>=1.13
torchaudio
pip3 install -U funasr
pip3 install -U torchaudio
pip3 install -U torch
pip3 install -U ffmpeg
pip3 install -U bottle
windows ffmpeg安装
选择版本678,ffmpeg下载地址:https://github.com/BtbN/FFmpeg-Builds/releases
代码
起一个简易的http服务器,用于开放语音识别的借口,这写死了recording.wav的具体位置,然后使用java代码先把语音文件传过来,然后java再使用httpget获取识别结果。
fromfunasrimportAutoModelfrombottleimportroute,run,getfromdatetimeimportdatetime now=datetime.now()date_time_str=now.strftime("%Y年%m月%d日 %H时%M分%S秒")print("开始加载:",date_time_str)model=AutoModel(disable_update=True,model="D:\\voiceRecogize\\pythonVR\\speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404",punc_model="D:\\voiceRecogize\\pythonVR\\punc_ct-transformer_zh-cn-common-vocab272727-pytorch")# model = AutoModel(model="D:\\voiceRecogize\\pythonVR\\speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch",punc_model="D:\\voiceRecogize\\pythonVR\\punc_ct-transformer_zh-cn-common-vocab272727-pytorch")modelPunc=AutoModel(model="D:\\voiceRecogize\\pythonVR\\punc_ct-transformer_zh-cn-common-vocab272727-pytorch")now=datetime.now()date_time_str=now.strftime("%Y年%m月%d日 %H时%M分%S秒")print("加载完成:",date_time_str)# @route('/')# def index():# return "你说说看先!"@route('/:content')defback(content):res=model.generate(input="D:\\download\\serverFile\\recording.wav",hotword='关联单')# [{'key': 'recording', 'text': '我 在 群 里 讲 一 下', 'timestamp': [[390, 570], [570, 730], [730, 850], [850, 1010], [1010, 1250], [1250, 1350], [1350, 1765]]}]# print(res)# return '''回答记录如下:<br><br>%s '''% (res[0]["text"])finalResult=res[0]["text"].replace(" ","")re=modelPunc.generate(input=finalResult)print(re)returnre[0]["text"]run(host="0.0.0.0",port=8811)完整代码见:https://gitee.com/likexiang/source-code-records/tree/master/java/VoiceServerWithNettyAndJavafx
使用whisper.cpp
安装依赖
pip install pywhispercpp pyaudio pyautogui
cpp下载地址
这个release有两种,一种发布的源代码,一种发布的是bin文件,我们这里下载bin文件,如
https://github.com/ggml-org/whisper.cpp/releases#release-b5130
下载模型
https://hf-mirror.com/ggerganov/whisper.cpp/tree/main,从里面下载如下模型,模型文件名有:
ggml-base.binggml-medium.binggml-large-v3.binggml-large-v3-turbo.bin
如何使用
./whisper-cli -m ggml-large-v3-turbo.bin -f 11.wav -l zh --output-txtpython代码调用
frompywhispercpp.modelimportModelimportpyaudioimportwaveimportthreadingimporttimeimportpyautogui# ========= 配置区 =========MODEL_PATH=r"./ggml-large-v3-turbo.bin"# ggml模型路径LANGUAGE="zh"SAMPLE_RATE=16000# whisper.cpp强制要求16kHzCHANNELS=1FORMAT=pyaudio.paInt16# ========= 一次性加载模型(只执行一次) =========print("正在加载模型到内存...")model=Model(MODEL_PATH,n_threads=8,use_gpu=True,gpu_device=0)print("✅ 模型加载完成,常驻内存!")print("🎮 操作说明:按住【鼠标左键】录音,松开左键自动识别语音\n")# 录音全局状态is_recording=Falseaudio_frames=[]stream=Nonep=pyaudio.PyAudio()# 后台录音线程defmic_recorder():globalis_recording,audio_frames,stream stream=p.open(format=FORMAT,channels=CHANNELS,rate=SAMPLE_RATE,input=True,frames_per_buffer=512)whileTrue:ifis_recording:try:data=stream.read(512,exception_on_overflow=False)audio_frames.append(data)exceptExceptionase:print("音频读取异常:",e)else:time.sleep(0.01)# 保存录音为wav临时文件defsave_audio_wav(output_path="temp_rec.wav"):wf=wave.open(output_path,'wb')wf.setnchannels(CHANNELS)wf.setsampwidth(p.get_sample_size(FORMAT))wf.setframerate(SAMPLE_RATE)wf.writeframes(b"".join(audio_frames))wf.close()returnoutput_path# 语音识别函数(模型已经在内存,直接推理)defspeech_recognize(wav_file):segments=model.transcribe(wav_file,language=LANGUAGE)full_text=""forseginsegments:line=f"[{seg.start:.2f}s →{seg.end:.2f}s]{seg.text}"print(line)full_text+=seg.textreturnfull_text# 启动录音后台线程record_thread=threading.Thread(target=mic_recorder,daemon=True)record_thread.start()# 主循环监听鼠标左键try:whileTrue:left_down=pyautogui.isPressed('left')ifleft_downandnotis_recording:# 按下左键:开始录音,清空缓存print("\n🎙️ 开始录音 >>>")is_recording=Trueaudio_frames.clear()elifnotleft_downandis_recording:# 松开左键:停止录音,执行识别print("🛑 录音结束,正在识别...")is_recording=Falsetemp_wav=save_audio_wav()result=speech_recognize(temp_wav)print(f"✅ 完整识别文本:{result}\n")time.sleep(0.03)exceptKeyboardInterrupt:print("\n程序退出 Ctrl+C")finally:ifstream:stream.stop_stream()stream.close()p.terminate()总结
vosk还是比阿里的逊色不少,建议使用FunASR和whisper-cli,whisper-cli还可以自动识别标点符号