找回密码
 立即注册
查看: 652|回复: 0

JAVA开发离线语音识别

[复制链接]

86

主题

0

回帖

894

积分

中级会员

积分
894
发表于 2024-4-24 17:21:59 | 显示全部楼层 |阅读模式

可以离线识别,但是暂时只有一个小的语音库,识别准确率特别低。


springboot框架搭的一个小demo。

原文地址还有前端页面html和js,有录音,播放,翻译等小功能,详情见下边原文地址。

  1. package com.example.gadgets.yysb;

  2. import com.alibaba.fastjson.JSONObject;
  3. import com.sun.media.sound.WaveFileReader;
  4. import com.sun.media.sound.WaveFileWriter;
  5. import org.springframework.util.Assert;
  6. import org.springframework.util.StringUtils;
  7. import org.vosk.LibVosk;
  8. import org.vosk.LogLevel;
  9. import org.vosk.Model;
  10. import org.vosk.Recognizer;

  11. import javax.sound.sampled.*;
  12. import java.io.*;
  13. import java.nio.file.Files;
  14. import java.nio.file.Paths;

  15. public class VoiceUtil {



  16.     //模型的地址,需要去官网下载:https://alphacephei.com/vosk/models,这里选择的是Chinese里的vosk-model-small-cn-0.22 微型版本
  17.     //经测试,微型版本转化准确率30%左右。如果语言不清楚,可能更低。明天下载个大的包试一下
  18.     private static String VOSKMODELPATH = "D:/yuyinshibie/vosk-model-small-cn-0.22";

  19.     public static String getWord(String filePath) throws IOException, UnsupportedAudioFileException {
  20.         Assert.isTrue(StringUtils.hasLength(VOSKMODELPATH), "无效的VOS模块!");
  21.         byte[] bytes = Files.readAllBytes(Paths.get(filePath));
  22.         // 转换为16KHZ
  23.         reSamplingAndSave(bytes, filePath);
  24.         File f = new File(filePath);
  25.         RandomAccessFile rdf = null;
  26.         rdf = new RandomAccessFile(f, "r");
  27.         System.out.println("声音尺寸:{}"+ toInt(read(rdf, 4, 4)));
  28.         System.out.println("音频格式:{}"+ toShort(read(rdf, 20, 2)));
  29.         short track=toShort(read(rdf, 22, 2));
  30.         System.out.println("1 单声道 2 双声道: {}"+ track);
  31.         System.out.println("采样率、音频采样级别 16000 = 16KHz: {}"+ toInt(read(rdf, 24, 4)));
  32.         System.out.println("每秒波形的数据量:{}"+ toShort(read(rdf, 22, 2)));
  33.         System.out.println("采样帧的大小:{}"+ toShort(read(rdf, 32, 2)));
  34.         System.out.println("采样位数:{}"+ toShort(read(rdf, 34, 2)));
  35.         rdf.close();
  36.         LibVosk.setLogLevel(LogLevel.WARNINGS);

  37.         try (Model model = new Model(VOSKMODELPATH);
  38.              InputStream ais = AudioSystem.getAudioInputStream(new BufferedInputStream(new FileInputStream(filePath)));
  39.              // 采样率为音频采样率的声道倍数
  40.              Recognizer recognizer = new Recognizer(model, 16000*track)) {

  41.             int nbytes;
  42.             byte[] b = new byte[4096];
  43.             int i = 0;
  44.             while ((nbytes = ais.read(b)) >= 0) {
  45.                 i += 1;
  46.                 if (recognizer.acceptWaveForm(b, nbytes)) {
  47. //                    System.out.println(recognizer.getResult());
  48.                 } else {
  49. //                    System.out.println(recognizer.getPartialResult());
  50.                 }
  51.             }
  52.             String result = recognizer.getFinalResult();
  53.             System.out.println("识别结果:{}"+ result);
  54.             if (StringUtils.hasLength(result)) {
  55.                 JSONObject jsonObject = JSONObject.parseObject(result);
  56.                 return jsonObject.getString("text").replace(" ", "");
  57.             }
  58.             return "";
  59.         }
  60.     }

  61.     public static int toInt(byte[] b) {
  62.         return (((b[3] & 0xff) << 24) + ((b[2] & 0xff) << 16) + ((b[1] & 0xff) << 8) + ((b[0] & 0xff) << 0));
  63.     }

  64.     public static short toShort(byte[] b) {
  65.         return (short) ((b[1] << 8) + (b[0] << 0));
  66.     }


  67.     public static byte[] read(RandomAccessFile rdf, int pos, int length) throws IOException {
  68.         rdf.seek(pos);
  69.         byte result[] = new byte[length];
  70.         for (int i = 0; i < length; i++) {
  71.             result[i] = rdf.readByte();
  72.         }
  73.         return result;
  74.     }

  75.     public static void reSamplingAndSave(byte[] data, String path) throws IOException, UnsupportedAudioFileException {
  76.         WaveFileReader reader = new WaveFileReader();
  77.         AudioInputStream audioIn = reader.getAudioInputStream(new ByteArrayInputStream(data));

  78.         AudioFormat srcFormat = audioIn.getFormat();
  79.         int targetSampleRate = 16000;

  80.         AudioFormat dstFormat = new AudioFormat(srcFormat.getEncoding(),
  81.                 targetSampleRate,
  82.                 srcFormat.getSampleSizeInBits(),
  83.                 srcFormat.getChannels(),
  84.                 srcFormat.getFrameSize(),
  85.                 srcFormat.getFrameRate(),
  86.                 srcFormat.isBigEndian());

  87.         AudioInputStream convertedIn = AudioSystem.getAudioInputStream(dstFormat, audioIn);
  88.         File file = new File(path);
  89.         WaveFileWriter writer = new WaveFileWriter();
  90.         writer.write(convertedIn, AudioFileFormat.Type.WAVE, file);
  91.     }

  92.     public static void main(String[] args) {
  93.         String path = "D:/yuyinshibie/test456.wav";
  94.         File localFile = new File(path);
  95.         try {

  96.             //开始解析
  97.             String text = getWord(path);
  98.             System.out.println("text:"+text);
  99.             localFile.delete();
  100.         } catch (IOException | UnsupportedAudioFileException e) {
  101.             e.printStackTrace();
  102.             localFile.delete();
  103.         }
  104.     }

  105. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|EnMaking

GMT+8, 2025-3-31 09:05 , Processed in 0.049104 second(s), 23 queries .

Powered by Qiqirobot

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表