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

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:movSystem.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 = 16KHzint 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 modelat org.vosk.Model.<init>(Model.java:14)
java.lang.Error: Invalid memory accessat 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多内存
在这里插入图片描述

参考链接

链接: vosk开源语音识别

链接: 基于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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/310771.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP/IP协议—TCP

TCP/IP协议—TCP TCP协议TCP通信特点TCP技术概念TCP定时器 TCP头部报文TCP连接三次握手&#xff08;建立连接&#xff09;四次挥手&#xff08;释放连接&#xff09;连接状态 TCP协议 传输控制协议&#xff08;TCP&#xff0c;Transmission Control Protocol&#xff09;是一种…

ubuntu16.04安装Eclipse C/C++

1.安装 JDK 官网源码安装 首先打开JDK官网&#xff0c;JDK1.8的下载网址为&#xff1a;https://www.oracle.com/cn/java/technologies/downloads/#java8-windows&#xff0c;进入到网址如下图所示&#xff1a; 向下滑动到 JDK1.8的下载界面&#xff0c;如下图所示&#xff1a…

(十)C++自制植物大战僵尸游戏设置功能实现

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/m0EtD 游戏设置 游戏设置功能是一个允许玩家根据个人喜好和设备性能来调整游戏各项参数的重要工具。游戏设置功能是为了让玩家能够根据自己的需求和设备性能来调整游戏&#xff0c;以获得最佳的游戏体验。不同的游戏和平…

前端框架模板

前端框架模板 1、vue-element-admin vue-element-admin是基于element-ui 的一套后台管理系统集成方案。 **功能&#xff1a;**https://panjiachen.github.io/vue-element-admin-site/zh/guide/#功能 **GitHub地址&#xff1a;**GitHub - PanJiaChen/vue-element-admin: :t…

Linux学习之路 -- 进程篇 -- PCB介绍 -- 进程的孤儿和僵尸状态

前面介绍了进程的各种状态&#xff0c;下面介绍比较特殊的两种状态 -- 孤儿和僵尸&#xff08;僵死&#xff09;。 一、僵尸状态 我们创建进程的目的其实就是想要进程帮我们执行一些任务&#xff0c;当任务被执行完后&#xff0c;进程的使命其实就已经完成了。此时我们就需要…

【机器学习300问】69、为什么深层神经网络比浅层要好用?

要回答这个问题&#xff0c;首先得知道神经网络都在计算些什么东西&#xff1f;之前我在迁移学习的文章中稍有提到&#xff0c;跳转链接在下面&#xff1a; 为什么其他任务预训练的模型参数&#xff0c;可以在我这个任务上起作用&#xff1f;http://t.csdnimg.cn/FVAV8 …

MySQL8.0.20 下载与安装

一、下载 MySQL服务器下载安装&#xff1a; 官网社区版地址&#xff1a; https://downloads.mysql.com/archives/installer/ 二、安装 安装注意事项---成功秘诀 安装密码不要设置复杂了&#xff0c;千万要记住密码&#xff0c;比如root和mysql就很好&#xff1b;不要随意卸…

科技云报道:AI大模型疯长,存储扛住了吗?

科技云报道原创。 AI大模型正在倒逼数字基础设施产业加速升级。 过去一年半&#xff0c;AI大模型标志性的应用相继出现&#xff0c;从ChatGPT到Sora一次次刷新人们的认知。震撼的背后&#xff0c;是大模型参数指数级的增长。 这种数据暴涨的压力&#xff0c;快速传导到了大模…

node.js服务器静态资源处理

前言&#xff1a;node.js服务器动态资源处理见 http://t.csdnimg.cn/9D8WN 一、什么是node.js服务器静态资源&#xff1f; 静态资源服务器指的是不会被服务器的动态运行所改变或者生成的文件. 它最初在服务器运行之前是什么样子, 到服务器结束运行时, 它还是那个样子. 比如平…

【数据结构】树与二叉树、树与森林部分习题与算法设计例题

目录 【数据结构】树与二叉树部分习题与算法设计例题一、单选题二、算法设计题判断二叉树是否为完全二叉树求二叉树的最小深度 以及 二叉树树高 树与二叉树知识点文章: 【数据结构】树与二叉树&#xff08;递归法先序、中序、后序、层次遍历二叉树、二叉树的建立以及求树高的方…

百货商场用户画像描绘and价值分析(下)

目录 内容概述数据说明技术点主要内容4 会员用户画像和特征字段创造4.1 构建会员用户基本特征标签4.2 会员用户词云分析 5 会员用户细分和营销方案制定5.1 会员用户的聚类分析及可视化5.2 对会员用户进行精细划分并分析不同群体带来的价值差异 内容概述 本项目内容主要是基于P…

华为欧拉系统(openEuler-22.03)安装深信服EasyConnect软件(图文详解)

欧拉镜像下载安装 iso镜像官网下载地址 选择最小化安装&#xff0c;标准模式 换华为镜像源 更换华为镜像站&#xff0c;加速下载&#xff1a; sed -i "s#http://repo.openeuler.org#https://mirrors.huaweicloud.com/openeuler#g" /etc/yum.repos.d/openEuler.r…

七月审稿之提升模型效果的三大要素:prompt、数据质量、训练策略(含Reviewer2和PeerRead)​

前言 我带队的整个大模型项目团队超过40人了&#xff0c;分六个项目组&#xff0c;每个项目组都是全职带兼职&#xff0c;且都会每周确定任务/目标/计划&#xff0c;然后各项目组各自做任务拆解&#xff0c;有时同组内任务多时 则2-4人一组 方便并行和讨论&#xff0c;每周文档…

SpringCloud之LoadBalancer负载均衡器的简单使用

SpringCloud之LoadBalancer负载均衡器的简单使用 loadbalancer用于对提供服务的集群做一个节点的选取规则。 如图所示&#xff0c;load balancer集成在调用方 示例 创建loadbalance-base模块,并引入相关依赖 <dependencies><dependency><groupId>org.spr…

LeetCode 热题 100 Day02

滑动窗口模块 滑动窗口类问题&#xff1a;总能找到一个窗口&#xff0c;从前往后移动来查找结果值。 这个窗口的大小可能是固定的&#xff0c;也可能是变化的。但窗口的大小一定是有限的。 https://www.cnblogs.com/huansky/p/13488234.html Leetcode 3. 无重复字符的最长子串 …

图书馆自习室|基于SSM的图书馆自习室座位预约小程序设计与实现(源码+数据库+文档)

图书馆自习室目录 基于SSM的图书馆自习室座位预约小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、小程序端&#xff1a; 2、后台 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a…

专业照片编辑软件ON1 Photo RAW 2024 mac/win

ON1 Photo RAW 2024 for Mac是一款集专业性与易用性于一体的照片编辑软件。它拥有简洁直观的用户界面&#xff0c;即便对于摄影新手&#xff0c;也能快速上手。软件支持RAW格式照片处理&#xff0c;能够完整保留照片原始信息&#xff0c;让后期调整更加灵活。 在功能方面&#…

视力筛查通知短信群发选择106平台时应注意什么!

选择106平台进行视力筛查通知短信群发时&#xff0c;需要注意以下几点&#xff1a; 1.平台的合规性与资质&#xff1a;首先&#xff0c;确保所选的106短信平台具有合法的运营资质和工信审批相关证书。避免与违法平台合作&#xff0c;确保服务的合规性。 2.平台的覆盖范围与到…

第07-2章 TCP/IP模型

7.7 TCP/IP模型详解 7.7.1 简介 应用层的PDU>APDU&#xff08;Application PDU&#xff09; 表示层的PDU>PPDU&#xff08;Presentation PDU&#xff09; 会话层的PDU>SPDU&#xff08;Session PDU&#xff09; 7.7.2 TCP/IP协议体系 &#xff08;1&#xff09;TCP…

解析数据科学,探索ChatGPT背后的奥秘

在当今这个由数据驱动和AI蓬勃发展的时代&#xff0c;数据科学作为一门融合多种学科的综合性领域&#xff0c;对于推动各行各业实现数字化转型升级起着至关重要的作用。近年来&#xff0c;大语言模型技术发展态势强劲&#xff0c;为数据科学的进步做出了巨大贡献。其中&#xf…