当前位置: 代码网 > it编程>编程语言>Java > springboot整合vosk实现简单的语音识别功能

springboot整合vosk实现简单的语音识别功能

2024年08月06日 Java 我要评论
ASRT是一个基于深度学习的语音识别工具,可以用于开发最先进的语音识别系统,是由AI柠檬博主(西安电子科技大学 · 西安市大数据与视觉智能重点实验室)从2016年起做的开源语音识别项目,基线为85%识别准确率,在某些条件下可做到95%左右的识别准确率。支持十九种语言 - 中文,英语,印度英语,德语,法语,西班牙语,葡萄牙语,俄语,土耳其语,越南语,意大利语,荷兰人,加泰罗尼亚语,阿拉伯, 希腊语, 波斯语, 菲律宾语,乌克兰语, 哈萨克语。每种语言的手提式模型只有是50Mb, 但还有更大的服务器模型可用。

vosk开源语音识别

vosk是开源的语音识别工具包。vosk支持的事情包括:

  1. 支持十九种语言 - 中文,英语,印度英语,德语,法语,西班牙语,葡萄牙语,俄语,土耳其语,越南语,意大利语,荷兰人,加泰罗尼亚语,阿拉伯, 希腊语, 波斯语, 菲律宾语,乌克兰语, 哈萨克语。

  2. 移动设备上脱机工作-raspberry pi,android,ios。

  3. 使用简单的 pip3 install vosk 安装。

  4. 每种语言的手提式模型只有是50mb, 但还有更大的服务器模型可用。

  5. 提供流媒体api,以提供最佳用户体验(与流行的语音识别python包不同)。

  6. 还有用于不同编程语言的包装器-java / csharp / javascript等。

  7. 可以快速重新配置词汇以实现最佳准确性。

  8. 支持说话人识别。

vosk-api

离线语音识别api,适用于android,ios,raspberry pi和具有python,java,c#等

链接: vosk-api github地址

有各语言的使用的示例

vosk-server

基于vosk和kaldi库的websocket,grpc和webrtc语音识别服务器

链接: vosk-server github地址

有各语言的使用的示例

vosk-api - java - springboot中的使用

导入依赖包

  <!-- 语音识别 -->
        <dependency>
            <groupid>net.java.dev.jna</groupid>
            <artifactid>jna</artifactid>
            <version>5.13.0</version>
        </dependency>
        <dependency>
            <groupid>com.alphacephei</groupid>
            <artifactid>vosk</artifactid>
            <version>0.3.45</version>
        </dependency>

        <!-- jave2(java音频视频编码器)库是ffmpeg项目上的java包装器。 -->
        <dependency>
            <groupid>ws.schild</groupid>
            <artifactid>jave-core</artifactid>
            <version>3.1.1</version>
        </dependency>

        <!-- 在windows上开发 开发机可实现压缩效果 window64位 -->
        <dependency>
            <groupid>ws.schild</groupid>
            <artifactid>jave-nativebin-win32</artifactid>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupid>ws.schild</groupid>
            <artifactid>jave-nativebin-win64</artifactid>
            <version>3.1.1</version>
        </dependency>

voskresult

public class voskresult {

    private string text;

    public string gettext() {
        return text;
    }

    public void settext(string text) {
        this.text = text;
    }
}

vosk模型加载

package com.fjdci.vosk;

import org.vosk.libvosk;
import org.vosk.loglevel;
import org.vosk.model;

import java.io.ioexception;

/**
 * vosk模型加载
 * @author zhou
 */
public class voskmodel {

    /**
     * 3. 使用 volatile 保证线程安全
     * 禁止指令重排
     * 保证可见性
     * 不保证原子性
     */
    private static volatile voskmodel instance;

    private model voskmodel;

    public model getvoskmodel() {
        return voskmodel;
    }

    /**
     * 1.私有构造函数
     */
    private voskmodel() {
        system.out.println("singlelazypattern实例化了");
        //string modelstr = "d:\\work\\project\\fjdci-vosk\\src\\main\\resources\\vosk-model-small-cn-0.22";
        string modelstr = "d:\\work\\fjdci\\docker\\vosk\\vosk-model-cn-0.22";
        try {
            voskmodel = new model(modelstr);
            libvosk.setloglevel(loglevel.info);
        } catch (ioexception e) {
            e.printstacktrace();
        }
    }

    /**
     * 2.通过静态方法获取一个唯一实例
     * dcl 双重检查锁定 (double-checkedlocking)
     * 在多线程情况下保持⾼性能
     */
    public static voskmodel getinstance() {
        if (instance == null) {
            synchronized (voskmodel.class) {
                if (instance == null) {
                    // 1. 分配内存空间 2、执行构造方法,初始化对象 3、把这个对象指向这个空间
                    instance = new voskmodel();
                }
            }
        }
        return instance;
    }

    /**
     * 多线程测试加载
     * @param args
     */
    public static void main(string[] args) {
        for (int i = 0; i < 5; i++) {
            new thread(() -> {
                voskmodel.getinstance();
            }).start();
        }
    }


}

语言识别工具类

package com.fjdci.vosk;

import lombok.extern.slf4j.slf4j;
import org.springframework.stereotype.component;
import org.vosk.model;
import org.vosk.recognizer;
import ws.schild.jave.encoderexception;
import ws.schild.jave.multimediaobject;
import ws.schild.jave.info.audioinfo;
import ws.schild.jave.info.multimediainfo;

import java.io.file;
import java.io.fileinputstream;
import java.io.inputstream;
import java.util.arraylist;
import java.util.list;
import java.util.optional;
import java.util.uuid;

@slf4j
@component
public class voiceutil {

    public static void main(string[] args) throws encoderexception {
        string wavfilepath = "d:\\fjfile\\annex\\xwbl\\tem_2.wav";
        // 秒
        long cutduration = 20;
        string waveform = acceptwaveform(wavfilepath, cutduration);
        system.out.println(waveform);
    }

    /**
     * 对wav格式音频文件进行语音识别翻译
     *
     * @param wavfilepath
     * @param cutduration
     * @return
     * @throws encoderexception
     */
    private static string acceptwaveform(string wavfilepath, long cutduration) throws encoderexception {
        // 判断视频的长度
        long starttime = system.currenttimemillis();
        multimediaobject multimediaobject = new multimediaobject(new file(wavfilepath));
        multimediainfo info = multimediaobject.getinfo();
        // 时长/毫秒
        long duration = info.getduration();
        audioinfo audio = info.getaudio();
        // 通道数
        int channels = audio.getchannels();
        // 秒
        long offset = 0;
        long fornum = (duration / 1000) / cutduration;
        if (duration % (cutduration * 1000) > 0) {
            fornum = fornum + 1;
        }
        // 进行切块处理
        list<string> strings = cutwavfile(wavfilepath, cutduration, offset, fornum);
        // 循环进行翻译
        stringbuilder result = new stringbuilder();
        for (string string : strings) {
            file f = new file(string);
            result.append(voiceutil.getrecognizerresult(f, channels));
        }
        long endtime = system.currenttimemillis();
        string msg = "耗时:" + (endtime - starttime) + "ms";
        system.out.println(msg);
        return result.tostring();
    }

    /**
     * 对wav进行切块处理
     *
     * @param wavfilepath 处理的wav文件路径
     * @param cutduration 切割的固定长度/秒
     * @param offset      设置起始偏移量(秒)
     * @param fornum      切块的次数
     * @return
     * @throws encoderexception
     */
    private static list<string> cutwavfile(string wavfilepath, long cutduration, long offset, long fornum) throws encoderexception {
        uuid uuid = uuid.randomuuid();
        // 大文件切割为固定时长的小文件
        list<string> strings = new arraylist<>();
        for (int i = 0; i < fornum; i++) {
            string target = "d:\\fjfile\\annex\\xwbl\\" + uuid + "\\" + i + ".wav";
            float offsetf = float.valueof(string.valueof(offset));
            float cutdurationf = float.valueof(string.valueof(cutduration));
            jave2util.cut(wavfilepath, target, offsetf, cutdurationf);
            offset = offset + cutduration;
            strings.add(target);
        }
        return strings;
    }

    /**
     * 进行翻译
     *
     * @param f
     * @param channels
     */
    public static string getrecognizerresult(file f, int channels) {
        stringbuilder result = new stringbuilder();
        model voskmodel = voskmodel.getinstance().getvoskmodel();
        // 采样率为音频采样率的声道倍数
        log.info("====加载完成,开始分析====");
        try (
                recognizer recognizer = new recognizer(voskmodel, 16000 * channels);
                inputstream ais = new fileinputstream(f)
        ) {
            int nbytes;
            byte[] b = new byte[4096];
            while ((nbytes = ais.read(b)) >= 0) {
                if (recognizer.acceptwaveform(b, nbytes)) {
                    // 返回语音识别结果
                    result.append(getresult(recognizer.getresult()));
                }
            }
            // 返回语音识别结果。和结果一样,但不要等待沉默。你通常在流的最后调用它来获得音频的最后部分。它刷新功能管道,以便处理所有剩余的音频块。
            result.append(getresult(recognizer.getfinalresult()));
            log.info("识别结果:{}", result.tostring());
        } catch (exception e) {
            e.printstacktrace();
        }
        return result.tostring();
    }

    /**
     * 获取返回结果
     *
     * @param result
     * @return
     */
    private static string getresult(string result) {
        voskresult voskresult = jacksonmapperutils.json2pojo(result, voskresult.class);
        return optional.ofnullable(voskresult).map(voskresult::gettext).orelse("");

    }

}

jave2 音频处理工具类

package com.fjdci.vosk;

import ws.schild.jave.encoder;
import ws.schild.jave.encoderexception;
import ws.schild.jave.inputformatexception;
import ws.schild.jave.multimediaobject;
import ws.schild.jave.encode.audioattributes;
import ws.schild.jave.encode.encodingattributes;
import ws.schild.jave.info.audioinfo;
import ws.schild.jave.info.multimediainfo;

import java.io.file;

public class jave2util {

    /**
     * @param src      来源文件路径
     * @param target   目标文件路径
     * @param offset   设置起始偏移量(秒)
     * @param duration 设置切片的音频长度(秒)
     * @throws encoderexception
     */
    public static void cut(string src, string target, float offset, float duration) throws encoderexception {

        file targetfile = new file(target);
        if (targetfile.exists()) {
            targetfile.delete();
        }

        file srcfile = new file(src);
        multimediaobject srcmultiobj = new multimediaobject(srcfile);
        multimediainfo srcmediainfo = srcmultiobj.getinfo();

        encoder encoder = new encoder();

        encodingattributes encodingattributes = new encodingattributes();
        //设置起始偏移量(秒)
        encodingattributes.setoffset(offset);
        //设置切片的音频长度(秒)
        encodingattributes.setduration(duration);
        // 输入格式
        encodingattributes.setinputformat("wav");

        //设置音频属性
        audioattributes audio = new audioattributes();
        audio.setbitrate(srcmediainfo.getaudio().getbitrate());
        //audio.setsamplingrate(srcmediainfo.getaudio().getsamplingrate());
        // 转换为16khz 满足vosk识别的标准
        audio.setsamplingrate(16000);
        audio.setchannels(srcmediainfo.getaudio().getchannels());
        //如果截取的时候,希望同步调整编码,可以设置不同的编码
//        audio.setcodec("pcm_u8");
        //audio.setcodec(srcmediainfo.getaudio().getdecoder().split(" ")[0]);
        encodingattributes.setaudioattributes(audio);
        //写文件
        encoder.encode(srcmultiobj, new file(target), encodingattributes);
    }

    /**
     * 转化音频格式
     *
     * @param oldformatpath : 原音乐路径
     * @param newformatpath : 目标音乐路径
     * @return
     */
    public static boolean transformusicformat(string oldformatpath, string newformatpath) {
        file source = new file(oldformatpath);
        file target = new file(newformatpath);
        // 音频转换格式类
        encoder encoder = new encoder();
        // 设置音频属性
        audioattributes audio = new audioattributes();
        audio.setcodec(null);
        // 设置转码属性
        encodingattributes attrs = new encodingattributes();
        attrs.setinputformat("wav");
        attrs.setaudioattributes(audio);
        try {
            encoder.encode(new multimediaobject(source), target, attrs);
            system.out.println("传唤已完成...");
            return true;
        } catch (illegalargumentexception e) {
            e.printstacktrace();
        } catch (inputformatexception e) {
            e.printstacktrace();
        } catch (encoderexception e) {
            e.printstacktrace();
        }
        return false;
    }

    
    
    public static void main(string[] args) throws encoderexception {

        string src = "d:\\fjfile\\annex\\xwbl\\ly8603f22f24e0409fa9747d50a78ff7e5.wav";
        string target = "d:\\fjfile\\annex\\xwbl\\tem_2.wav";

        jave2util.cut(src, target, 0.0f, 60.0f);

        string inputformatpath = "d:\\fjfile\\annex\\xwbl\\ly8603f22f24e0409fa9747d50a78ff7e5.m4a";
        string outputformatpath = "d:\\fjfile\\annex\\xwbl\\ly8603f22f24e0409fa9747d50a78ff7e5.wav";

        info(inputformatpath);

       // audioencode(inputformatpath, outputformatpath);


    }

    /**
     * 获取音频文件的编码信息
     *
     * @param filepath
     * @throws encoderexception
     */
    private static void info(string filepath) throws encoderexception {
        file file = new file(filepath);
        multimediaobject multimediaobject = new multimediaobject(file);
        multimediainfo info = multimediaobject.getinfo();
        // 时长
        long duration = info.getduration();
        string format = info.getformat();
        // format:mov
        system.out.println("format:" + format);
        audioinfo audio = info.getaudio();
        // 它设置将在重新编码的音频流中使用的音频通道数(1 =单声道,2 =立体声)。如果未设置任何通道值,则编码器将选择默认值。
        int channels = audio.getchannels();
        // 它为新的重新编码的音频流设置比特率值。如果未设置比特率值,则编码器将选择默认值。
        // 该值应以每秒位数表示。例如,如果您想要128 kb / s的比特率,则应调用setbitrate(new integer(128000))。
        int bitrate = audio.getbitrate();
        // 它为新的重新编码的音频流设置采样率。如果未设置采样率值,则编码器将选择默认值。该值应以赫兹表示。例如,如果您想要类似cd
        // 采样率、音频采样级别 16000 = 16khz
        int samplingrate = audio.getsamplingrate();

        // 设置音频音量
        // 可以调用此方法来更改音频流的音量。值为256表示音量不变。因此,小于256的值表示音量减小,而大于256的值将增大音频流的音量。
        // setvolume(integer volume)

        string decoder = audio.getdecoder();

        system.out.println("声音时长:毫秒" + duration);
        system.out.println("声道:" + channels);
        system.out.println("bitrate:" + bitrate);
        system.out.println("samplingrate 采样率、音频采样级别 16000 = 16khz:" + samplingrate);
        // aac (lc) (mp4a / 0x6134706d)
        system.out.println("decoder:" + decoder);
    }

    /**
     * 音频格式转换
     * @param inputformatpath
     * @param outputformatpath
     * @return
     */
    public static boolean audioencode(string inputformatpath, string outputformatpath) {
        string outputformat = getsuffix(outputformatpath);
        string inputformat = getsuffix(inputformatpath);
        file source = new file(inputformatpath);
        file target = new file(outputformatpath);
        try {
            multimediaobject multimediaobject = new multimediaobject(source);
            // 获取音频文件的编码信息
            multimediainfo info = multimediaobject.getinfo();
            audioinfo audioinfo = info.getaudio();
            //设置音频属性
            audioattributes audio = new audioattributes();
            audio.setbitrate(audioinfo.getbitrate());
            audio.setsamplingrate(audioinfo.getsamplingrate());
            audio.setchannels(audioinfo.getchannels());
            // 设置转码属性
            encodingattributes attrs = new encodingattributes();
            attrs.setinputformat(inputformat);
            attrs.setoutputformat(outputformat);
            attrs.setaudioattributes(audio);
            // 音频转换格式类
            encoder encoder = new encoder();
            // 进行转换
            encoder.encode(new multimediaobject(source), target, attrs);
            return true;
        } catch (illegalargumentexception | encoderexception e) {
            e.printstacktrace();
        }
        return false;
    }

    /**
     * 获取文件路径的.后缀
     * @param outputformatpath
     * @return
     */
    private static string getsuffix(string outputformatpath) {
        return outputformatpath.substring(outputformatpath.lastindexof(".") + 1);
    }


}

import com.fasterxml.jackson.annotation.jsoninclude;
import com.fasterxml.jackson.core.jsonprocessingexception;
import com.fasterxml.jackson.core.type.typereference;
import com.fasterxml.jackson.databind.deserializationfeature;
import com.fasterxml.jackson.databind.javatype;
import com.fasterxml.jackson.databind.objectmapper;

import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.map;


public class jacksonmapperutils {

    private final static objectmapper objectmapper = new objectmapper();

    public static objectmapper getinstance() {
        return objectmapper;
    }

    /**
     * 转换为 json 字符串
     *
     * @param obj
     * @return
     * @throws exception
     */
    public static string obj2json(object obj) throws exception {
        objectmapper mapper = new objectmapper();
        mapper.setserializationinclusion(jsoninclude.include.always);
        return mapper.writevalueasstring(obj);
    }

    /**
     * 转换为 json 字符串,忽略空值
     *
     * @param obj
     * @return
     * @throws exception
     */
    public static string obj2jsonignorenull(object obj) throws exception {
        objectmapper mapper = new objectmapper();
        mapper.setserializationinclusion(jsoninclude.include.non_null);
        return mapper.writevalueasstring(obj);
    }

    /**
     * 转换为 javabean
     *
     * @param jsonstring
     * @param clazz
     * @return
     * @throws exception
     */
    public static <t> t json2pojo(string jsonstring, class<t> clazz){
        try {
            objectmapper.configure(deserializationfeature.accept_single_value_as_array, true);
            return objectmapper.readvalue(jsonstring, clazz);
        } catch (jsonprocessingexception e) {
            e.printstacktrace();
        }
        return null;
    }

    /**
     * 字符串转换为 map<string, object>
     *
     * @param jsonstring
     * @return
     * @throws exception
     */
    public static <t> map<string, object> json2map(string jsonstring) throws exception {
        objectmapper mapper = new objectmapper();
        mapper.setserializationinclusion(jsoninclude.include.non_null);
        return mapper.readvalue(jsonstring, map.class);
    }

    /**
     * 字符串转换为 map<string, t>
     */
    public static <t> map<string, t> json2map(string jsonstring, class<t> clazz) throws exception {
        map<string, map<string, object>> map = (map<string, map<string, object>>) objectmapper.readvalue(jsonstring, new typereference<map<string, t>>() {
        });
        map<string, t> result = new hashmap<string, t>();
        for (map.entry<string, map<string, object>> entry : map.entryset()) {
            result.put(entry.getkey(), map2pojo(entry.getvalue(), clazz));
        }
        return result;
    }

    /**
     * 深度转换 json 成 map
     *
     * @param json
     * @return
     */
    public static map<string, object> json2mapdeeply(string json) throws exception {
        return json2maprecursion(json, objectmapper);
    }

    /**
     * 把 json 解析成 list,如果 list 内部的元素存在 jsonstring,继续解析
     *
     * @param json
     * @param mapper 解析工具
     * @return
     * @throws exception
     */
    private static list<object> json2listrecursion(string json, objectmapper mapper) throws exception {
        if (json == null) {
            return null;
        }

        list<object> list = mapper.readvalue(json, list.class);

        for (object obj : list) {
            if (obj != null && obj instanceof string) {
                string str = (string) obj;
                if (str.startswith("[")) {
                    obj = json2listrecursion(str, mapper);
                } else if (obj.tostring().startswith("{")) {
                    obj = json2maprecursion(str, mapper);
                }
            }
        }

        return list;
    }

    /**
     * 把 json 解析成 map,如果 map 内部的 value 存在 jsonstring,继续解析
     *
     * @param json
     * @param mapper
     * @return
     * @throws exception
     */
    private static map<string, object> json2maprecursion(string json, objectmapper mapper) throws exception {
        if (json == null) {
            return null;
        }

        map<string, object> map = mapper.readvalue(json, map.class);

        for (map.entry<string, object> entry : map.entryset()) {
            object obj = entry.getvalue();
            if (obj != null && obj instanceof string) {
                string str = ((string) obj);

                if (str.startswith("[")) {
                    list<?> list = json2listrecursion(str, mapper);
                    map.put(entry.getkey(), list);
                } else if (str.startswith("{")) {
                    map<string, object> maprecursion = json2maprecursion(str, mapper);
                    map.put(entry.getkey(), maprecursion);
                }
            }
        }

        return map;
    }

    /**
     * 将 json 数组转换为集合
     *
     * @param jsonarraystr
     * @param clazz
     * @return
     * @throws exception
     */
    public static <t> list<t> json2list(string jsonarraystr, class<t> clazz) throws exception {
        javatype javatype = getcollectiontype(arraylist.class, clazz);
        list<t> list = (list<t>) objectmapper.readvalue(jsonarraystr, javatype);
        return list;
    }


    /**
     * 获取泛型的 collection type
     *
     * @param collectionclass 泛型的collection
     * @param elementclasses  元素类
     * @return javatype java类型
     * @since 1.0
     */
    public static javatype getcollectiontype(class<?> collectionclass, class<?>... elementclasses) {
        return objectmapper.gettypefactory().constructparametrictype(collectionclass, elementclasses);
    }

    /**
     * 将 map 转换为 javabean
     *
     * @param map
     * @param clazz
     * @return
     */
    public static <t> t map2pojo(map map, class<t> clazz) {
        return objectmapper.convertvalue(map, clazz);
    }

    /**
     * 将 map 转换为 json
     *
     * @param map
     * @return
     */
    public static string maptojson(map map) {
        try {
            return objectmapper.writevalueasstring(map);
        } catch (exception e) {
            e.printstacktrace();
        }
        return "";
    }

    /**
     * 将 json 对象转换为 javabean
     *
     * @param obj
     * @param clazz
     * @return
     */
    public static <t> t obj2pojo(object obj, class<t> clazz) {
        return objectmapper.convertvalue(obj, clazz);
    }


}

语音模型下载地址 翻墙

https://alphacephei.com/vosk/models

链接: 模型下载地址

踩坑记录

java.io.ioexception: failed to create a model
        at org.vosk.model.<init>(model.java:14)

java.lang.error: invalid memory access
        at org.vosk.libvosk.vosk_recognizer_new(native method)
        at org.vosk.recognizer.<init>(recognizer.java:19)

链接: exception: failed to create a model 原因

在这里插入图片描述

vosk模型加载需要服务器有足够的内存

项目启动未加载模型时 使用了500m
在这里插入图片描述

项目加载模型时 使用了4g多内存
在这里插入图片描述

参考链接

链接:

链接: 基于whisper的音频转录服务汇总

链接: 几款免费的语音转文字工具推荐

链接: java 离线中文语音文字识别

链接: asr - python使用vosk进行中文语音识别

链接: nemo非常强大,覆盖了asr, nlp, tts,提供了预训练模型及完整的训练模块。其商业版本为riva。

链接: asrt语音识别文档
asrt是一个基于深度学习的语音识别工具,可以用于开发最先进的语音识别系统,是由ai柠檬博主(西安电子科技大学 · 西安市大数据与视觉智能重点实验室)从2016年起做的开源语音识别项目,基线为85%识别准确率,在某些条件下可做到95%左右的识别准确率。asrt包含了语音识别算法服务端(用于训练或部署api服务)和多种平台及编程语言的客户端sdk,支持一句话识别和实时流式识别,相关的代码已经开源在github和gitee上。
asrt语音识别系统的api已经为ai柠檬站内搜索引擎提供了语音识别服务,用于该站语音搜索功能的实现。

搭建一个离线的语音识别系统 并提供webapi访问

一些方向和思路:

  1. 确定语音识别引擎

首先,需要选择一个适合的语音识别引擎。常见的一些引擎有cmu sphinx、kaldi、百度语音、讯飞开放平台等等。选定引擎后,需要对其进行配置和训练,使其能够适应自己的应用场景。

  1. 搭建离线语音识别系统

接下来,需要进行搭建离线语音识别系统的工作。可以通过使用ubuntu等linux系统进行安装和配置。在系统中需要安装上一步中选择的语音识别引擎和相关依赖包。

  1. 提供web api访问

为了使得离线语音识别系统能够方便地被访问和使用,需要提供相应的web api。您可以使用flask等框架搭建web服务,并在其上下文中调用语音识别引擎进行语音识别工作。

最后,为了保证语音识别的精度和流畅度,还需要进行一系列优化和调试工作,例如声音降噪、语速控制、模型调优等等。希望以上方向可以帮助到您。

2 whisper

whisper 是一种自动语音识别模型,基于从网络上收集的 680,000 小时多语言数据进行训练。

whisper是一个语音识别引擎,可以用于开发语音控制应用程序,但它通常用于移动设备和嵌入式设备上,以提供离线语音识别的功能。如果您想使用java搭建离线语音识别,您可以尝试使用其他语音识别引擎,如cmu sphinx和kaldi。 这些引擎都支持离线语音识别,并提供java api供开发人员使用。

3 kaldi

开源中文语音识别项目介绍:asrframe

https://blog.csdn.net/sailist/article/details/95751825

腾讯ai lab开源轻量级语音处理工具包pika

专注e2e语音识别,腾讯ai lab开源轻量级语音处理工具包pika-csdn社区

有什么开源的python汉语语音转文字项目?

https://blog.csdn.net/devid008/article/details/129656356

离线语音识别第三方服务提供商

1 科大讯飞

https://www.xfyun.cn/service/offline_iat

科大讯飞离线包仅基于安卓,也不支持java离线版

还像可以调用本地dll 实现离线语音

2 百度语音识别

https://ai.baidu.com/tech/speech/realtime_asr

不支持离线

3 阿里云语音识别

https://ai.aliyun.com/nls/trans

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com