已解决:安卓,怎么优雅接入科大讯飞语音评测功能?

写在前面:

网上关于讯飞接入的博客都很少,按说讯飞都是业界翘楚,不知为何,很少搜索到精品,一搜就是一个要求开会员的博客,我也是醉了。讯飞提供的文档也是不清晰,我是摸着石头过河,过来了,我就给大家总结一个方法,给大家免费看,只要是我的粉丝,我永远给大家免费的阅读支持。

之前接入过web端的语音评测,那叫个麻烦建议大家不要轻易尝试,如果大家有必要的需求,可以尝试,但是建议不要玩,容易入坑。文章结尾有对各平台使用讯飞的一些看法和建议,需要的可以到文章末尾去看。

正文开始:

首先,我们从官网上下载demo,此时如果你还没有注册讯飞账号,那你先去注册一个开发者账号,不得不说,作为大公司,讯飞还是有些气量的,每天给账号500个免费的评测额度,(数量不知道我理解的是否正确,至少我已经免费用了一年了),然后创建自己的应用,如下图创建好以后就有了appid,这些不细说了,讯飞的文档主要就是介绍这些了,至于技术上的事儿基本没咋提
在这里插入图片描述
然后我们开始打包下载讯飞的sdk,我们点击上图的应用名称,然后进入到如下页面,点击下载sdk,这里的sdk会把我们生成的应用秘钥打包进去,我们只需要在app中配置一个appid就可以了。
在这里插入图片描述
然后我们点亮我们需要的功能,点击下载就可以,我选择了语音合成和语音测评功能,如下图,不建议选择新版,就用普通版本就可以,功能接口都一样,新版盲猜有坑:
在这里插入图片描述
下载完以后,打开文件夹,会看到一堆文件夹,我们需要的就是libs,其他的不需要,也不需要运行他说的sample,因为运行这个项目可能会很耗费时间,没必要。但是我们还是可以使用AS打开这个sample项目,以便于我们查找一些功能的使用方法,当然这是我的操作,你们也可以只看我的教程,不过我的教程只讲评测的功能,其实有了评测的经验,再做别的也手到擒来。
在这里插入图片描述
首先我们新建一个安卓项目,添加阿里云的镜像依赖,然后重新下载依赖,然后我们把上图的libs中的所有内容拷贝至Android工程的libs目录下。如下图所示:
在这里插入图片描述
在这里插入图片描述
然后,我们鼠标右键Msc.jar文件,选择一个Add As Library,将jar包添加到库里,我已经添加过了,弹不出来这个选项所以不截图了。
同时,我们在main包下创建如下图所示的文件夹,并且将上述sdk中的文件复制过来,如下图:
在这里插入图片描述
然后我们开始开发:
打开清单文件,然后添加文档中提到的安卓权限:

<!--连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--读取联系人权限,上传联系人需要用到此权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外存储写权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置权限,用来记录应用配置信息 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
<!--定位信息是敏感信息,可通过Setting.setLocationEnable(false)关闭定位请求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人脸识别,还要添加:摄相头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />

然后,需要混淆的话,添加一下这个,不添加会将讯飞sdk同步混淆导致闪退,如果不配置混淆就可以忽略。

-keep class com.iflytek.**{*;}
-keepattributes Signature

然后进行初始化:将如下代码行添加到应用的自定义Application或者调用评测的Activity的oncreate方法中,context用this就行:

// 将“12345678”替换成您申请的APPID,申请地址:http://www.xfyun.cn
// 请勿在“=”与appid之间添加任何空字符或者转义符
SpeechUtility.createUtility(context, SpeechConstant.APPID +"=12345678");

然后就开始调用关键方法:
我把封装的类贴出来吧,可以拿来即用,我是通过h5调用的,使用activity也是可以直接调用的:

package com.lz.english.activity.webviewimport android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.webkit.JavascriptInterface
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.gson.Gson
import com.iflytek.cloud.EvaluatorListener
import com.iflytek.cloud.EvaluatorResult
import com.iflytek.cloud.SpeechConstant
import com.iflytek.cloud.SpeechError
import com.iflytek.cloud.SpeechEvaluator
import com.lz.english.activity.WebViewActivity
import com.lz.english.databinding.ActivityWebviewBinding
import com.lz.english.result.xml.XmlResultParser
import com.lz.english.utils.ToastUtils
import org.greenrobot.eventbus.EventBusprivate const val s1 = "ise_unite"private const val s = "ise_unite"class JsBridge(context: WebViewActivity,binding: ActivityWebviewBinding,mIse: SpeechEvaluator
) {private val TAG = "JsBride"// 创建语音评测对象,使用lateinit关键字标记为非空
//    private lateinit var mIse:SpeechEvaluator ;companion object {private const val REQUEST_RECORD_AUDIO_PERMISSION = 1}private lateinit var context: WebViewActivityprivate lateinit var binding: ActivityWebviewBindingprivate lateinit var mIse: SpeechEvaluatorinit {this.context = contextthis.binding = bindingthis.mIse = mIsesetParams()}// 评测监听接口private val mEvaluatorListener: EvaluatorListener = object : EvaluatorListener {override fun onResult(result: EvaluatorResult, isLast: Boolean) {Log.d(TAG, "evaluator result :$isLast")if (isLast) {val builder = StringBuilder()builder.append(result.resultString)Log.d(TAG, "evaluator result :${builder.toString()}")mLastResult = builder.toString()val resultParser = XmlResultParser()val result = resultParser.parse(mLastResult)val gsonStr = Gson().toJson(result)Log.e(TAG,gsonStr)if (null != result) {binding.webView.loadUrl("javascript:recordFinishCallback('${gsonStr}')")} else {ToastUtils.showToast("语音解析失败")}}}override fun onError(error: SpeechError) {Log.d(TAG, "evaluator over")}override fun onBeginOfSpeech() {// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入Log.d(TAG, "evaluator begin")binding.webView.loadUrl("javascript:androidStartRecord()")}override fun onEndOfSpeech() {// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入Log.d("WebView", "evaluator stoped")}override fun onVolumeChanged(volume: Int, data: ByteArray) {Log.d("WebView","当前音量:$volume")Log.d(TAG, "返回音频数据:" + data.size)}override fun onEvent(eventType: Int, arg1: Int, arg2: Int, obj: Bundle) {// 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因//	if (SpeechEvent.EVENT_SESSION_ID == eventType) {//		String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);//		Log.d(TAG, "session id =" + sid);//	}}}@JavascriptInterfacefun goBack() {EventBus.getDefault().post("view_goBack")}// 启动录音@JavascriptInterfacefun startRecord(content:String,timeout:String,vad_bos:String,vad_eos:String) {Log.e(TAG,"timeout::$timeout")Log.e(TAG,"vad_bos::$vad_bos")Log.e(TAG,"vad_eos::$vad_eos")if (ContextCompat.checkSelfPermission(this.context, Manifest.permission.RECORD_AUDIO)!= PackageManager.PERMISSION_GRANTED) {// 如果没有录音权限,请求权限ActivityCompat.requestPermissions(this.context,arrayOf(Manifest.permission.RECORD_AUDIO),REQUEST_RECORD_AUDIO_PERMISSION)} else {// 已经有录音权限,执行录音操作mIse?.setParameter(SpeechConstant.KEY_SPEECH_TIMEOUT, timeout)mIse?.setParameter(SpeechConstant.VAD_BOS, vad_bos)// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理mIse?.setParameter(SpeechConstant.VAD_EOS, vad_eos)// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音val int = mIse?.startEvaluating(content, null, mEvaluatorListener)if (mIse == null){Log.e(TAG,"mIse is null")}Log.e(TAG,"startRecord")Log.e(TAG,"ErrorCode:$int")}}// 停止录音@JavascriptInterfacefun stopRecord() {Log.e(TAG,"stoping...")mIse.stopEvaluating()}// 评测语种private var language: String? = null// 评测题型private var category: String? = null// 结果等级private var result_level: String? = nullprivate var mLastResult: String? = nullprivate fun setParams() {
//        mIse = SpeechEvaluator.createEvaluator(context, null);// 设置评测语言language = "en_us"// 设置需要评测的类型category = "read_sentence"// 设置结果等级(中文仅支持complete)result_level = "complete"// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理val vad_bos = "5000"// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音val vad_eos = "1800"// 语音输入超时时间,即用户最多可以连续说多长时间;val speech_timeout = "5000"// 设置流式版本所需参数 : ent sub plevif ("zh_cn" == language) {mIse?.setParameter("ent", "cn_vip")}if ("en_us" == language) {mIse?.setParameter("ent", "en_vip")}mIse?.setParameter(SpeechConstant.SUBJECT, "ise")mIse?.setParameter("plev", "0")// 设置评分百分制 使用 ise_unite  rst  extra_ability 参数, 其中ise_unite==0是5分制,==1是百分制mIse?.setParameter("ise_unite", "1")mIse?.setParameter("rst", "entirety")mIse?.setParameter("extra_ability", "syll_phone_err_msg;pitch;multi_dimension")mIse?.setParameter(SpeechConstant.LANGUAGE, language)mIse?.setParameter(SpeechConstant.ISE_CATEGORY, category)mIse?.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8")
//        mIse?.setParameter(SpeechConstant.VAD_BOS, vad_bos)
//        mIse?.setParameter(SpeechConstant.VAD_EOS, vad_eos)
//        mIse?.setParameter(SpeechConstant.KEY_SPEECH_TIMEOUT, speech_timeout)mIse?.setParameter(SpeechConstant.RESULT_LEVEL, result_level)mIse?.setParameter(SpeechConstant.AUDIO_FORMAT_AUE, "opus")// 设置音频保存路径,保存音频格式支持pcm、wav,mIse?.setParameter(SpeechConstant.AUDIO_FORMAT, "wav")mIse?.setParameter(SpeechConstant.ISE_AUDIO_PATH,context.getExternalFilesDir("msc")?.absolutePath + "/ise.wav")//通过writeaudio方式直接写入音频时才需要此设置//mIse?.setParameter(SpeechConstant.AUDIO_SOURCE,"-1");}
}

我来解释一下上面的工具类里的内容,可以看到方法上有一个注解@JavascriptInterface,这个注解是表示是给h5的js代码调用的,如果不涉及和前端js交互的话,这个注解可以删。其中评测最关键的方法,就是setParams方法,这个方法配置了一些打分参数等,注释已经很详细了,然后就是startRecord方法,这个方法就是开始录音的方法,这个方法还动态传入了几个参数,这几个参数是用来配置几个时长的,其中

timeout:String是用来设置最长录制几秒就自动停止录制并开始打分,
vad_bos:String是表示用户多长时间不说话则当做超时处理,
vad_eos:String是表示用户停止说话多长时间内即认为不再输入, 自动停止录音

还有一些配置在setParams方法中的参数,特别说一个分制的参数,有满分百分制和5分制,其中ise_unite==0是5分制,==1是百分制:

        // 设置评分百分制 使用 ise_unite  rst  extra_ability 参数, 其中ise_unite==0是5分制,==1是百分制mIse?.setParameter("ise_unite", "1")

然后就是关键的结果处理监听回调mEvaluatorListener了,这个是一个监听对象,这个对象复写了回调方法,来处理讯飞返回的结果,这里用到了一个类库,XmlResultParser,这个类库我们需要从讯飞的sdk中的sample中去copy过来,如图,我们把result文件夹完整复制
在这里插入图片描述
然后粘贴到自己项目包下的位置,如图,此时我们需要把这里面所有文件中引用的错误的包名路径修改成我们自己的正确的包名,然后再去工具类中引用XmlResultParser工具,这个工具,顾名思义,就是讯飞的程序员手撸了一个xml解析工具
在这里插入图片描述
sample自带的这个XmlResultParser工具,里面的实体类的数据不是很全,比如有一些流畅分,准确度分这些都没有,我们可以手动加一下,如图,打开result文件,我加了三个分值数据,在这里加的属性,必须得是人家返回结果包含的,不能随便加:
在这里插入图片描述
result这里加了以后,还需要在这里加一下解析:
在这里插入图片描述
然后怎么调用这个工具类呢?很简单,先在activity中创建一个mIse全局对象,在oncreate中赋值,我这里只写了赋值,声明的代码你自己写吧,然后传入这个对象,至于我用的这个工具对象jsBridge,你完全可以不按照我这个来,你可以直接吧工具类定义成object类型,怎么调用都可以。我是将上下文this传了过去,以防有ui操作,我还将binding传了进去,你们不需要可以不传,然后把mIse评测对象传了进去。

mIse = SpeechEvaluator.createEvaluator(this, null)
jsBridge = JsBridge(this, binding,mIse!!)

如果你觉得麻烦,甚至可以直接将工具类的那部分关键代码复制到你的activity里,省的麻烦,我之所以分离,是因为我的activity里逻辑太多了,看着有些头大。

然后附上我的运行图:
在这里插入图片描述

到此,就算大功告成了,写博客太累了,为了帮助大家理解,我仔细梳理了流程,花了有三个小时吧,要是我个人做记录,可能复制几个代码就够了,所以如果帮到阁下,还望给个关注,虽然关注也不挣钱,但是看到有人跟我有互动,我就知道这个世界,不止我一个人。

写在最后:

以下说一些个人观点,不想看或者不认同的就可以离开了:

关于科大讯飞:讯飞给了每天500的免费评测数量,这个气量,就比某些公司要强很多了,再加上讯飞的技术确实很好,所以基本在同行业市场上没有对手,比如云知声(个人免费半年,企业免费一年,有安卓sdk但是文档说明比葛优的头发还要稀疏),还有一些小众的比如有个叫什么驰声的这种完全没有免费额度的(而且sdk还是你在他们官网留下电话然后他们的销售给你打电话联系你,然后加你微信跟你拉个群让技术给申请一个appkey来使用),当然,讯飞的翻译功能也强于专业做翻译的同行不少,比如有道,有道的翻译比较死板,讯飞没有专攻翻译领域,否则应该就没有有道翻译的市场了。用过讯飞输入法的应该都知道,讯飞输入法自带语音转文字,甚至可以你直接说中文,他转英文文字,而且是多年前就很准确了,甚至他还能识别方言,其实要说国内的AI大模型,我唯一比较期待的就是讯飞的大模型了,关于文心一言和千义通问,我是不怎么看好的,因为这两为了竞争市场匆忙上线,上下文关联性以及对于中文理解能力跟ChatGPT比起来差得不是一点半点,甚至听说文心一言还推出了付费版本,这一点就挺搞笑的,有点搞不清楚自己的斤两,也有可圈可点的地方,那就是免费版支持图片生成,虽然生成的图不尽如人意吧,但是也算一个得分项。

关于浏览器端:因为浏览器对于录音功能的限制,也就只能局限于PC端用一用了,移动端用h5来访问录音功能,体验很不好。要开发移动端使用的,建议还是开发一个app,如果实在想做网页,也可以使用原生壳子加webview嵌套h5来实现讯飞语音的功能,这样可以使用原生的录音功能和讯飞sdk,这样实现起来用户使用很舒服,开发也很舒服。

关于uniapp:还有就是uniapp的客户端版不要接入科大讯飞的所有内容,这是因为科大讯飞已经封禁了新客户的http的请求方式,只能通过websocket的方式进行流式数据传输,而uniapp的录音分片功能不支持app端,只支持部分小程序,而uniapp的h5端就更不考虑了,uni开发是挺舒服的,但是遇到问题了,就知道uniapp还不如原生vue项目好做。其实如果非小程序需求,不建议使用uniapp做开发,除非是特别简单的页面需求,否则涉及一点点特殊定制的硬件功能,可能就歇菜了,举个简单例子,uniapp不支持使用formdata进行数据传输,而他提供了一个叫upload的方法,说是能代替进行formdata 传输,但是格式不能自定义,相当于白搞,再就是从uniapp的文档上就可以看到各种的不支持,有的功能不支持app端,有的不支持h5端,有的不支持小程序端,有的干脆只支持h5,有的只支持微信小程序,有的只支持抖音小程序,
说句唱衰的话,就uni这样的开发平台,你说该咋用,说他是跨平台解决方案弃之可惜吧,但是用着又如此食之无味,这大概也就是他这么多年没火起来的原因吧,给你们截个图你们就大概明白了,这个截图只是冰山一角,
在这里插入图片描述
所以想搞跨平台方案的,建议还是考虑清楚,毕竟貌似uni的团队并不打算维护这个uniapp了,那些社区里陈年的bug,貌似也打算让他继续陈年了,千万别相信uni市场上那些收费的插件,可能各平台版本更新一次插件就歇菜了,听说最近uni出了一个appx,貌似很吊的样子,说是性能和原生一样,众所周知,uniapp是一个webview的性能,性能很差,要是这个appx能做好,确实会很有市场,那将是要超越flutter的存在了,毕竟uni还能兼容小程序,但是要我相信dcloud团队能做好他,诸葛亮来当说客,我也得犹豫一下要不要信,我预估这个appx能用的周期应该是10年左右,但是技术更新换代这么快,10年也许写代码都不用太多的人力了,所以本人暂时先不考虑用了。

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

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

相关文章

java集合ArrayList和HashSet的fail-fast与fail-safe以及ConcurrentModificationException

在 java 的集合工具类中&#xff0c;例如对 ArrayList 或者 HashSet 进行删除元素后再遍历元素时&#xff0c;会抛出 ConcurrentModificationException 异常。 fail-fast ArrayList public class TestList {public static void main(String[] args) {ArrayList<Integer>…

【iOS ARKit】BlendShapes

BlendShapes 基础介绍 利用前置摄像头采集到的用户面部表情特征&#xff0c;ARKit 提供了一种更加抽象的表示面部表情的方式&#xff0c;这种表示方式叫作 BlendShapes,BlendShapes 可以翻译成形状融合&#xff0c;在3ds Max 中也叫变形器&#xff0c;这个概念原本用于描述通过…

Ubuntu18编译jdk8源码

环境 系统 ubuntu18 Linux ubuntu 5.4.0-150-generic #167~18.04.1-Ubuntu SMP Wed May 24 00:51:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux jdk源码openjdk-8u41-src-b04-14_jan_2020.zip bootJdk jdk-8u391-linux-x64.tar.gz ps -e|grep ssh sudo apt-get install ssh…

【MATLAB第92期】基于MATLAB的集成聚合多输入单输出回归预测方法(LSBoost、Bag)含自动优化超参数和特征敏感性分析功能

【MATLAB第92期】基于MATLAB的集成聚合多输入单输出回归预测方法&#xff08;LSBoost、Bag&#xff09;含自动优化超参数和特征敏感性分析功能 本文展示多种非常用多输入单输出回归预测模型效果。 注&#xff1a;每次运行数据训练集测试集为随机&#xff0c;故对比不严谨&…

京东广告算法架构体系建设--在线模型系统分布式异构计算演变 | 京东零售广告技术团队

一、现状介绍 算法策略在广告行业中起着重要的作用&#xff0c;它可以帮助广告主和广告平台更好地理解用户行为和兴趣&#xff0c;从而优化广告投放策略&#xff0c;提高广告点击率和转化率。模型系统作为承载算法策略的载体&#xff0c;目前承载搜索、推荐、首焦、站外等众多广…

Word插入音乐视频文件快速方法 exe zip doc apk txt pdf bat等

需求&#xff1a; Word插入文件有哪些极限操作&#xff1f;如何快速插入音乐视频等文件 问题解决&#xff1a; 使用拖动进行文件快速插入&#xff08;PPT Excle 同理&#xff09; 操作 1.让文件和word界面处于同一屏幕&#xff0c;可以使用分屏 2.鼠标选中文件左键或者使用笔…

一些反序列化总结

1 反序列化漏洞原理 如果反序列化的内容就是那串字符串&#xff0c;是用户可以控制的&#xff08;即变量的值&#xff09;&#xff0c;且后台不正当的使用了PHP中的魔法函数&#xff0c;就会导致反序列化漏洞&#xff0c;可以执行任意命令。Java 序列化指 Java 对象转换为字节序…

Flink问题解决及性能调优-【Flink根据不同场景状态后端使用调优】

Flink 实时groupby聚合场景操作时&#xff0c;由于使用的是rocksdb状态后端&#xff0c;发现CPU的高负载卡在rocksdb的读写上&#xff0c;导致上游算子背压特别大。通过调优使用hashmap状态后端代替rocksdb状态后端&#xff0c;使吞吐量有了质的飞跃&#xff08;20倍的性能提升…

2024年,你是否还在迷茫?

2024年&#xff0c;你是否还在迷茫&#xff1f; 别担心&#xff01;鸿蒙来了&#xff0c;这个未来技术的制高点&#xff0c;为你提供了答案&#xff01; 诸多大厂疯抢、24年预计鸿蒙相关的岗位需求将达到百万级、就业均薪达到19K&#xff0c;全国高校开课…… 种种现象都在表…

VirtualBox安装Ubuntu22.04

目录 1、新建虚拟机 1.1、设置内存大小 1.2、创建虚拟硬盘 2、虚拟机设置 2.1、设置启动顺序​编辑 2.2、选择iso镜像文件 2.3、设置网络(桥接网卡) 3、启动 3.1、设置语言环境 3.2、系统更新安装(不更新) 3.3、选择键盘布局(默认即可) 3.4、选择安装类型 3.5、网…

硬件知识(1) 手机的长焦镜头

#灵感# 手机总是配备好几个镜头&#xff0c;研究一下 目录 手机常配备的摄像头&#xff0c;及效果举例 长焦的焦距 焦距的定义和示图&#xff1a; IPC的焦距和适用场景&#xff1a; 手机常配备的摄像头&#xff0c;及效果举例 以下是小米某个手机的摄像头介绍&#xff1a…

EXCEL VBA抓取网页JSON数据并解析

EXCEL VBA抓取网页JSON数据并解析 链接地址&#xff1a; https://api.api68.com/CQShiCai/getBaseCQShiCaiList.do?lotCode10036&date2024-01-26 Sub test() On Error Resume Next Sheet.Select Sheet1.Cells.ClearContents [a1:g1] Split("preDrawIssue|preDrawTi…

用Visual Studio Code创建JavaScript运行环境【2024版】

用Visual Studio Code创建JavaScript运行环境 JavaScript 的历史 JavaScript 最初被称为 LiveScript&#xff0c;由 Netscape&#xff08;Netscape Communications Corporation&#xff0c;网景通信公司&#xff09;公司的布兰登艾奇&#xff08;Brendan Eich&#xff09;在 …

mysql 存储过程学习

存储过程介绍 1.1 SQL指令执行过程 从SQL执行的流程中我们分析存在的问题: 1.如果我们需要重复多次执行相同的SQL&#xff0c;SQL执行都需要通过连接传递到MySQL&#xff0c;并且需要经过编译和执行的步骤; 2.如果我们需要执行多个SQL指令&#xff0c;并且第二个SQL指令需要…

Topaz Video AI:无损放大,让你的视频更清晰!

在当今的数字时代&#xff0c;视频内容的重要性越来越受到人们的关注。无论是在社交媒体上分享生活片段&#xff0c;还是在商业领域中制作宣传视频&#xff0c;人们都希望能够展现出更高质量的视频内容。 然而&#xff0c;由于各种原因&#xff0c;我们经常会面临一个问题&…

C++版QT:分割窗口

目录 mainwindow.h mainwindow.cpp main.cpp Qt的分割窗口功能允许用户将一个窗口分割成多个区域&#xff0c;每个区域可以独立地显示不同的内容。这种功能在许多应用程序中非常有用&#xff0c;例如编辑器、浏览器和IDE等。 理解Qt的分割窗口&#xff0c;需要从以下几个方面…

音频格式之AAC:(2)AAC封装格式ADIF,ADTS,LATM,extradata及AAC ES存储格式

系列文章目录 音频格式的介绍文章系列&#xff1a; 音频编解码格式介绍(1) ADPCM&#xff1a;adpcm编解码原理及其代码实现 音频编解码格式介绍(2) MP3 &#xff1a;音频格式之MP3&#xff1a;(1)MP3封装格式简介 音频编解码格式介绍(2) MP3 &#xff1a;音频格式之MP3&#x…

IDEA jdk版本切换问题

打开 IntelliJ IDEA 的 Project Structure&#xff08;快捷键通常是 Ctrl Alt Shift S&#xff09;。 转到 Project Settings > Modules。 选择相应的模块&#xff0c;然后在 Sources 标签页下&#xff0c;查看 Language level 是否设置为 自己需要的jdk版本语言。 接…

20240125-边界外路径

题目要求 有一个m*n的网格&#xff0c;网格中有一个小球。小球初始位置位[startRow&#xff0c;startColumn]。您可以将小球移动到网格中相邻的四个单元格之一&#xff08;可能会越过网格边界移出网格&#xff09;。最多可以对小球进行maxMove移动。 给定 m、n、maxMove、sta…

uniapp导入uView组件库

目录 准备工作 1. 新建一个项目 2. 导入uview组件库 3. 关于SCSS 配置步骤 1. 引入uView主JS库 2. 在引入uView的全局SCSS 3. 引入uView基础样式 4. 配置easycom组件模式 添加效果实验运行即可成功 准备工作 1. 新建一个项目 2. 导入uview组件库 在进行配置之前&#x…