Unity3D開發AI桌面精靈/寵物系列 【三】 語音識別 ASR 技術、語音轉文本多平臺 - 支持科大訊飛、百度等 C# 開發

Unity3D 交互式AI桌面寵物開發系列【三】ASR 語音識別


該系列主要介紹怎么制作AI桌面寵物的流程,我會從項目開始創建初期到最終可以和AI寵物進行交互為止,項目已經開發完成,我會仔細梳理一下流程,分步講解。 這篇文章主要講有關于語音識別 ASR 方面的一些方法。


提示:內容純個人編寫,歡迎評論點贊,來指正我。

文章目錄

  • Unity3D 交互式AI桌面寵物開發系列【三】ASR 語音識別
  • 前言
  • 一、語音識別 (ASR) 概述
  • 二、Unity開發準備階段
    • 1.Unity平臺
    • 2.示例:訊飛平臺
  • 三、科大訊飛 ASR 短語音識別API
    • 1. 創建應用
    • 2. 查看免費測試服務量
    • 3. 查看 WebSocket 接口信息
    • 4. API 開發文檔查看
  • 四、功能開發階段
    • 1. Unity界面開發
    • 2. 代碼分析
    • 3. 代碼片段
    • 4. 數據配置
    • 5. 效果展示
    • 6. 問題反饋
    • 然后就,大功告成了!!!
  • 總結


前言

本篇內容主要講Unity開發桌面寵物的語音識別功能,大家感興趣也可以了解一下這個開發方向,目前還是挺有前景的,AI智能科技發展這么迅猛,緊跟步伐哈~

下面讓我們出發吧 ------------>----------------->


一、語音識別 (ASR) 概述

語音識別(Automatic Speech Recognition,ASR)是一種技術,指的是通過計算機程序和算法,將人類所說的語音信號轉化為文字或其他形式的電子文本的過程。ASR系統通過分析語音信號中包含的聲音波形、頻譜和語音特征等信息,識別并轉錄出語音中所包含的文字內容。這項技術在語音識別軟件、智能語音助手、語音搜索、電話客服系統等領域有著廣泛的應用。

在這里插入圖片描述

二、Unity開發準備階段

1.Unity平臺

  • 該系列全部使用Unity2021.3.44開發;
  • 該系列前后文章存在關聯,不懂的可以看前面文章;
  • 該系列完成之后我會上傳源碼工程,著急的小伙伴可以自己寫框架,我就先編寫各模塊的獨立功能。

2.示例:訊飛平臺

  • 注冊訊飛賬戶,已注冊的直接登錄;
  • 創建語音識別應用,然后 領取 語音識別 (短語音識別) 免費測試服務量綁定該應用,或者付費購買服務量;(個人認證可以領取免費服務量)
  • 前兩步我就不貼流程圖了,該系列在上節的語音喚醒文章中提到過注冊和領取相關功能免費服務量的流程;

  • 上述操作很簡單
  • 重點來了,科大訊飛平臺的ASR接口怎么接入,下面來看一下吧

三、科大訊飛 ASR 短語音識別API

1. 創建應用

在這里插入圖片描述在這里插入圖片描述

  • 點擊用戶下面的 “我的應用” 然后創建應用,命名語音識別的應用,創建成功后會生成一個APPKey或者APPID 保存好。(名字隨便起,記住APPID,后續要用到)

2. 查看免費測試服務量

在這里插入圖片描述

  • 個人測試的話領取免費開發測試服務量就可以了,商用的話就購買相應的服務量。

3. 查看 WebSocket 接口信息

在這里插入圖片描述

  • 記錄保存該各項數據,后續在WebSocket連接的時候要用到這些。

4. API 開發文檔查看

在這里插入圖片描述

  • 這里有開發文檔可以自行查看并學習,當然我是看過的,那么接下來就到了開發階段了!
  • ps: 記住這個接口地址,這是WebSocket的API 地址 (調用的網址),接下來會用到。

四、功能開發階段

1. Unity界面開發

在這里插入圖片描述

  • ① 用于顯示識別內容的 Text 文本
  • ② 用于按住進行錄音操作的 Button 按鈕
  • ③ 用于顯示按鈕的提示詞的 Text 文本
  • ④ 用于掛載ASR語音識別 腳本 的空物體

2. 代碼分析

在這里插入圖片描述

  • 參數:用于定義變量;
  • 語音輸入:用于錄制音頻片段;
  • 獲取鑒權Url:用于鑒權加密的API地址;
  • 語音識別:用于實現語音識別的API接口調用功能;
  • 工具方法:用于處理Unity中的音頻片段,轉換成訊飛標準格式;
  • 數據定義:用于定義發送數據和接收數據的數據結構,根據第三方平臺的參數數據。

3. 代碼片段

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;public class XunfeiSpeechToText : MonoBehaviour
{#region 參數/// <summary>/// host地址/// </summary>[SerializeField] private string m_HostUrl = "iat-api.xfyun.cn";/// <summary>/// 語言/// </summary>[SerializeField] private string m_Language = "zh_cn";/// <summary>/// 應用領域/// </summary>[SerializeField] private string m_Domain = "iat";/// <summary>/// 方言mandarin:中文普通話、其他語種/// </summary>[SerializeField] private string m_Accent = "mandarin";/// <summary>/// 音頻的采樣率/// </summary>[SerializeField] private string m_Format = "audio/L16;rate=16000";/// <summary>/// 音頻數據格式/// </summary>[SerializeField] private string m_Encoding = "raw";/// <summary>/// websocket/// </summary>private ClientWebSocket m_WebSocket;/// <summary>/// 傳輸中斷標記點/// </summary>private CancellationToken m_CancellationToken;/// <summary>/// 語音識別API地址/// </summary>[SerializeField][Header("語音識別API地址")]private string m_SpeechRecognizeURL;/// <summary>/// 訊飛的AppID/// </summary>[Header("填寫APP ID")][SerializeField] private string m_AppID = "訊飛的AppID";/// <summary>/// 訊飛的APIKey/// </summary>[Header("填寫Api Key")][SerializeField] private string m_APIKey = "訊飛的APIKey";/// <summary>/// 訊飛的APISecret/// </summary>[Header("填寫Secret Key")][SerializeField] private string m_APISecret = "訊飛的APISecret";/// <summary>/// 計算方法調用的時間/// </summary>[SerializeField] protected System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();#endregionprivate void Awake(){//注冊按鈕事件RegistButtonEvent();//綁定地址 地址就是訊飛平臺上的 WebSocket API地址m_SpeechRecognizeURL = "wss://iat-api.xfyun.cn/v2/iat";}#region 語音輸入/// <summary>/// 語音輸入的按鈕/// </summary>[SerializeField] private Button m_VoiceInputBotton;/// <summary>/// 錄音按鈕的文本/// </summary>[SerializeField] private Text m_VoiceBottonText;/// <summary>/// 錄音的提示信息/// </summary>[SerializeField] private Text m_RecordTips;/// <summary>/// 錄制的音頻長度/// </summary>public int m_RecordingLength = 5;/// <summary>/// 臨時接收音頻的片段/// </summary>private AudioClip recording;/// <summary>/// 注冊按鈕事件/// </summary>private void RegistButtonEvent(){if (m_VoiceInputBotton == null || m_VoiceInputBotton.GetComponent<EventTrigger>())return;EventTrigger _trigger = m_VoiceInputBotton.gameObject.AddComponent<EventTrigger>();//添加按鈕按下的事件EventTrigger.Entry _pointDown_entry = new EventTrigger.Entry();_pointDown_entry.eventID = EventTriggerType.PointerDown;_pointDown_entry.callback = new EventTrigger.TriggerEvent();//添加按鈕松開事件EventTrigger.Entry _pointUp_entry = new EventTrigger.Entry();_pointUp_entry.eventID = EventTriggerType.PointerUp;_pointUp_entry.callback = new EventTrigger.TriggerEvent();//添加委托事件_pointDown_entry.callback.AddListener(delegate { StartRecord(); });_pointUp_entry.callback.AddListener(delegate { StopRecord(); });_trigger.triggers.Add(_pointDown_entry);_trigger.triggers.Add(_pointUp_entry);}/// <summary>/// 開始錄制/// </summary>public void StartRecord(){m_VoiceBottonText.text = "正在錄音中...";StartRecordAudio();}/// <summary>/// 結束錄制/// </summary>public void StopRecord(){m_VoiceBottonText.text = "按住按鈕,開始錄音";m_RecordTips.text = "錄音結束,正在識別...";StopRecordAudio(AcceptClip);}/// <summary>/// 開始錄制聲音/// </summary>public void StartRecordAudio(){recording = Microphone.Start(null, true, m_RecordingLength, 16000);}/// <summary>/// 結束錄制,返回audioClip/// </summary>/// <param name="_callback"></param>public void StopRecordAudio(Action<AudioClip> _callback){Microphone.End(null);_callback(recording);}/// <summary>/// 處理錄制的音頻數據/// </summary>/// <param name="_data"></param>public void AcceptClip(AudioClip _audioClip){m_RecordTips.text = "正在進行語音識別...";SpeechToText(_audioClip, DealingTextCallback);}/// <summary>/// 處理識別到的文本/// </summary>/// <param name="_msg"></param>private void DealingTextCallback(string _msg){//在此處處理接收到的數據,可以選擇發送給大模型,或者打印測試,會在后續補充功能m_RecordTips.text = _msg;Debug.Log(_msg);}#endregion#region 獲取鑒權Url/// <summary>/// 獲取鑒權url/// </summary>/// <returns></returns>private string GetUrl(){//獲取時間戳string date = DateTime.Now.ToString("r");//拼接原始的signaturestring signature_origin = string.Format("host: " + m_HostUrl + "\ndate: " + date + "\nGET /v2/iat HTTP/1.1");//hmac-sha256算法-簽名,并轉換為base64編碼string signature = Convert.ToBase64String(new HMACSHA256(Encoding.UTF8.GetBytes(m_APISecret)).ComputeHash(Encoding.UTF8.GetBytes(signature_origin)));//拼接原始的authorizationstring authorization_origin = string.Format("api_key=\"{0}\",algorithm=\"hmac-sha256\",headers=\"host date request-line\",signature=\"{1}\"", m_APIKey, signature);//轉換為base64編碼string authorization = Convert.ToBase64String(Encoding.UTF8.GetBytes(authorization_origin));//拼接鑒權的urlstring url = string.Format("{0}?authorization={1}&date={2}&host={3}", m_SpeechRecognizeURL, authorization, date, m_HostUrl);return url;}#endregion#region 語音識別/// <summary>/// 語音識別/// </summary>/// <param name="_clip"></param>/// <param name="_callback"></param>public void SpeechToText(AudioClip _clip, Action<string> _callback){byte[] _audioData = ConvertClipToBytes(_clip);StartCoroutine(SendAudioData(_audioData, _callback));}/// <summary>/// 識別短文本/// </summary>/// <param name="_audioData"></param>/// <param name="_callback"></param>/// <returns></returns>public IEnumerator SendAudioData(byte[] _audioData, Action<string> _callback){yield return null;ConnetHostAndRecognize(_audioData, _callback);}/// <summary>/// 連接服務,開始識別/// </summary>/// <param name="_audioData"></param>/// <param name="_callback"></param>private async void ConnetHostAndRecognize(byte[] _audioData, Action<string> _callback){try{stopwatch.Restart();//建立socket連接m_WebSocket = new ClientWebSocket();m_CancellationToken = new CancellationToken();Uri uri = new Uri(GetUrl());await m_WebSocket.ConnectAsync(uri, m_CancellationToken);//開始識別SendVoiceData(_audioData, m_WebSocket);StringBuilder stringBuilder = new StringBuilder();while (m_WebSocket.State == WebSocketState.Open){var result = new byte[4096];await m_WebSocket.ReceiveAsync(new ArraySegment<byte>(result), m_CancellationToken);//去除空字節List<byte> list = new List<byte>(result); while (list[list.Count - 1] == 0x00) list.RemoveAt(list.Count - 1);string str = Encoding.UTF8.GetString(list.ToArray());//獲取返回的jsonResponseData _responseData = JsonUtility.FromJson<ResponseData>(str);if (_responseData.code == 0){stringBuilder.Append(GetWords(_responseData));}else{PrintErrorLog(_responseData.code);}m_WebSocket.Abort();}string _resultMsg = stringBuilder.ToString();//識別成功,回調_callback(_resultMsg);stopwatch.Stop();if (_resultMsg.Equals(null) || _resultMsg.Equals("")){Debug.Log("語音識別為空字符串");}else{//識別的數據不為空 在此處做功能處理}Debug.Log("訊飛語音識別耗時:" + stopwatch.Elapsed.TotalSeconds);}catch (Exception ex){Debug.LogError("報錯信息: " + ex.Message);m_WebSocket.Dispose();}}/// <summary>/// 獲取識別到的文本/// </summary>/// <param name="_responseData"></param>/// <returns></returns>private string GetWords(ResponseData _responseData){StringBuilder stringBuilder = new StringBuilder();foreach (var item in _responseData.data.result.ws){foreach (var _cw in item.cw){stringBuilder.Append(_cw.w);}}return stringBuilder.ToString();}private void SendVoiceData(byte[] audio, ClientWebSocket socket){if (socket.State != WebSocketState.Open){return;}PostData _postData = new PostData(){common = new CommonTag(m_AppID),business = new BusinessTag(m_Language, m_Domain, m_Accent),data = new DataTag(2, m_Format, m_Encoding, Convert.ToBase64String(audio))};string _jsonData = JsonUtility.ToJson(_postData);//發送數據socket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(_jsonData)), WebSocketMessageType.Binary, true, new CancellationToken());}#endregion#region 工具方法/// <summary>/// audioclip轉為byte[]/// </summary>/// <param name="audioClip"></param>/// <returns></returns>public byte[] ConvertClipToBytes(AudioClip audioClip){float[] samples = new float[audioClip.samples];audioClip.GetData(samples, 0);short[] intData = new short[samples.Length];byte[] bytesData = new byte[samples.Length * 2];int rescaleFactor = 32767;for (int i = 0; i < samples.Length; i++){intData[i] = (short)(samples[i] * rescaleFactor);byte[] byteArr = new byte[2];byteArr = BitConverter.GetBytes(intData[i]);byteArr.CopyTo(bytesData, i * 2);}return bytesData;}/// <summary>/// 打印錯誤日志/// </summary>/// <param name="status"></param>private void PrintErrorLog(int status){if (status == 10005){Debug.LogError("appid授權失敗");return;}if (status == 10006){Debug.LogError("請求缺失必要參數");return;}if (status == 10007){Debug.LogError("請求的參數值無效");return;}if (status == 10010){Debug.LogError("引擎授權不足");return;}if (status == 10019){Debug.LogError("session超時");return;}if (status == 10043){Debug.LogError("音頻解碼失敗");return;}if (status == 10101){Debug.LogError("引擎會話已結束");return;}if (status == 10313){Debug.LogError("appid不能為空");return;}if (status == 10317){Debug.LogError("版本非法");return;}if (status == 11200){Debug.LogError("沒有權限");return;}if (status == 11201){Debug.LogError("日流控超限");return;}if (status == 10160){Debug.LogError("請求數據格式非法");return;}if (status == 10161){Debug.LogError("base64解碼失敗");return;}if (status == 10163){Debug.LogError("缺少必傳參數,或者參數不合法,具體原因見詳細的描述");return;}if (status == 10200){Debug.LogError("讀取數據超時");return;}if (status == 10222){Debug.LogError("網絡異常");return;}}#endregion#region 數據定義/// <summary>/// 發送的數據/// </summary>[Serializable]public class PostData{[SerializeField] public CommonTag common;[SerializeField] public BusinessTag business;[SerializeField] public DataTag data;}[Serializable]public class CommonTag{[SerializeField] public string app_id = string.Empty;public CommonTag(string app_id){this.app_id = app_id;}}[Serializable]public class BusinessTag{[SerializeField] public string language = "zh_cn";[SerializeField] public string domain = "iat";[SerializeField] public string accent = "mandarin";public BusinessTag(string language, string domain, string accent){this.language = language;this.domain = domain;this.accent = accent;}}[Serializable]public class DataTag{[SerializeField] public int status = 2;[SerializeField] public string format = "audio/L16;rate=16000";[SerializeField] public string encoding = "raw";[SerializeField] public string audio = string.Empty;public DataTag(int status, string format, string encoding, string audio){this.status = status;this.format = format;this.encoding = encoding;this.audio = audio;}}[Serializable]public class ResponseData{[SerializeField] public int code = 0;[SerializeField] public string message = string.Empty;[SerializeField] public string sid = string.Empty;[SerializeField] public ResponcsedataTag data;}[Serializable]public class ResponcsedataTag{[SerializeField] public Results result;[SerializeField] public int status = 2;}[Serializable]public class Results{[SerializeField] public List<WsTag> ws;}[Serializable]public class WsTag{[SerializeField] public List<CwTag> cw;}[Serializable]public class CwTag{[SerializeField] public int sc = 0;[SerializeField] public string w = string.Empty;}#endregion}

4. 數據配置

在這里插入圖片描述

  • 將APPid、ApiKey、SecretKey替換成自己訊飛平臺上的 WebSocket 信息數據
  • 變量對應UI進行配置

5. 效果展示

在這里插入圖片描述

  • 按住按鈕進行錄音,松開后進行識別,返回的結果會顯示在UI界面上,就代表成功了。

在這里插入圖片描述

  • 控制臺會有打印結果的,也一樣代表 API 接入成功。
  • 注意使用時,打開電腦麥克風權限

6. 問題反饋

  • 運行后有任何問題都可以在評論區進行討論~
  • 代碼寫的不是很工整,多多指點,后續會進行整個系列的框架搭建
  • 下一期更新暫定:
    ① 其他平臺ASR接入功能,例如:百度等
    ② 大模型LLM的接入,例如:訊飛、百度、GPT等
    二選一哦!
  • 評論告訴我,下一期更新什么

然后就,大功告成了!!!

在這里插入圖片描述
比心啦 ?(^_-)

在這里插入圖片描述

總結

  • 提示: 大家根據需求來做功能,后續繼續其他功能啦,不懂的快喊我。
  • 大家可以在評論區討論其他系列下一期出什么內容,這個系列會繼續更新的
  • 點贊收藏加關注哦~ 蟹蟹

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76617.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76617.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76617.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java 狀態模式 詳解

狀態模式詳解 一、狀態模式概述 狀態模式(State Pattern)是一種行為型設計模式&#xff0c;它允許一個對象在其內部狀態改變時改變它的行為&#xff0c;使對象看起來似乎修改了它的類。 核心特點 狀態封裝&#xff1a;將每個狀態的行為封裝到獨立的類中狀態轉換&#xff1a…

Nginx 配置 HTTPS 與 WSS 完整指南

Nginx 配置 HTTPS 與 WSS 完整指南 本教程將手把手教你如何為網站配置 HTTPS 加密訪問&#xff0c;并通過反向代理實現安全的 WebSocket&#xff08;WSS&#xff09;通信。以 https://www.zhegepai.cn 域名為例&#xff0c;完整流程約需 30 分鐘完成。 一、前置準備 1.1 域名…

雙向鏈表的理解

背景 代碼中經常會出現雙向鏈表&#xff0c;對于雙向鏈表的插入和刪除有對應的API函數接口&#xff0c;但直觀的圖表更容易理解&#xff0c;所以本文會對rt-thread內核代碼中提供的雙向鏈表的一些API函數操作進行繪圖&#xff0c;方便后續隨時查看。 代碼塊 rt-thread中提供…

大文件上傳源碼,支持單個大文件與多個大文件

大文件上傳源碼&#xff0c;支持單個大文件與多個大文件 Ⅰ 思路Ⅱ 具體代碼前端--單個大文件前端--多個大文件前端接口后端 Ⅰ 思路 具體思路請參考我之前的文章&#xff0c;這里分享的是上傳流程與源碼 https://blog.csdn.net/sugerfle/article/details/130829022 Ⅱ 具體代碼…

Unity中的靜態合批使用整理

靜態批處理是一種繪制調用批處理方法&#xff0c;它組合不移動的網格以減少繪制調用。它將組合的網格轉換為世界空間&#xff0c;并為它們構建一個共享頂點和索引緩沖區。然后&#xff0c;對于可見網格&#xff0c;Unity 會執行一系列簡單的繪制調用&#xff0c;每個調用之間幾…

【機器學習中的基本術語:特征、樣本、訓練集、測試集、監督/無監督學習】

機器學習基本術語詳解 1. 特征&#xff08;Feature&#xff09; 定義&#xff1a;數據的屬性或變量&#xff0c;用于描述樣本的某個方面。作用&#xff1a;模型通過學習特征與目標之間的關系進行預測。示例&#xff1a; 預測房價時&#xff0c;特征可以是 面積、地段、房齡。…

C++學習之路:指針基礎

目錄 指針介紹與基本用法雙重指針函數指針空指針與野指針函數參數的指針傳遞最后 指針一般在C/C語言學習的后期接觸&#xff0c;這樣就導致指針給新手一種高深莫測、難以掌握的刻板印象。但實際上指針的使用很簡單&#xff0c;并且還能夠極大的提高程序的靈活性&#xff0c;幫助…

【服務日志鏈路追蹤】

MDCInheritableThreadLocal和spring cloud sleuth 在微服務架構中&#xff0c;日志鏈路追蹤&#xff08;Logback Distributed Tracing&#xff09; 是一個關鍵需求&#xff0c;主要用于跟蹤請求在不同服務間的調用鏈路&#xff0c;便于排查問題。常見的實現方案有兩種&#x…

Kafka+Zookeeper從docker部署到spring boot使用完整教程

文章目錄 一、Kafka1.Kafka核心介紹&#xff1a;?核心架構?核心特性?典型應用 2.Kafka對 ZooKeeper 的依賴&#xff1a;3.去 ZooKeeper 的演進之路&#xff1a;注&#xff1a;&#xff08;本文采用ZooKeeper3.8 Kafka2.8.1&#xff09; 二、Zookeeper1.核心架構與特性2.典型…

JUC系列JMM學習之隨筆

JUC: JUC 是 Java 并發編程的核心工具包,全稱為 Java Util Concurrent,是 java.util.concurrent 包及其子包的簡稱。它提供了一套強大且高效的并發編程工具,用于簡化多線程開發并提高性能。 CPU核心數和線程數的關系:1核處理1線程(同一時間單次) CPU內核結構: 工作內…

The Rust Programming Language 學習 (九)

泛型 每一個編程語言都有高效處理重復概念的工具。在 Rust 中其工具之一就是 泛型&#xff08;generics&#xff09;。泛型是具體類型或其他屬性的抽象替代。我們可以表達泛型的屬性&#xff0c;比如他們的行為或如何與其他泛型相關聯&#xff0c;而不需要在編寫和編譯代碼時知…

藍橋杯 混乘數字

問題描述 混乘數字的定義如下&#xff1a; 對于一個正整數 n&#xff0c;如果存在正整數 a 和 b&#xff0c;使得&#xff1a; n a b且 a 與 b 的十進制數位中每個數字出現的次數之和&#xff0c;與 n 中對應數字出現的次數相同&#xff0c;則稱 n 為混乘數字。 示例 對于…

CExercise04_1位運算符_2 定義一個函數判斷給定的正整數是否為2的冪

題目&#xff1a; 給定一個正整數&#xff0c;請定義一個函數判斷它是否為2的冪(1, 2, 4, 8, 16, …) 分析&#xff1a; &#xff1a; 代碼 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdbool.h>/* 給定一個正整數&#xff0c;請定義一個函數…

SSL證書不可信的原因有哪些?(國科云)

SSL證書用于在客戶端和服務器端之間建立一條加密通道&#xff0c;確保數據在傳輸過程中的安全性和完整性。然而&#xff0c;在實際應用中&#xff0c;我們有時會遇到SSL證書不可信的情況&#xff0c;嚴重影響了用戶對網站的信任度。那么&#xff0c;SSL證書不可信的原因究竟有哪…

[王陽明代數講義]琴語言類型系統工程特性

琴語言類型系統工程特性 層展物理學組織實務與藝術與琴生生.物機.械科.技工.業研究.所軟凝聚態物理開發工具包社會科學氣質砥礪學人生意氣場社群成員魅力場與心氣微積分社會關系力學 意氣實體過程圖論信息編碼&#xff0c;如來碼導引 注意力機制道裝Transformer架構的發展標度律…

自抗擾ADRC之二階線性擴展狀態觀測器(LESO)推導

1.龍伯格觀測器 實際工程應用中&#xff0c;狀態變量有時難以使用傳感器直接測量&#xff0c;在這種情況下&#xff0c;使用狀態觀測器估計系統實際狀態是非常常見的做法。最出名的狀態觀測器當屬龍伯格博士在1971年發表于TAC的An Introduction to Observer[1]一文中提出的基于…

從頭開發一個Flutter插件(二)高德地圖定位插件

開發基于高德定位SDK的Flutter插件 在上一篇文章里具體介紹了Flutter插件的具體開發流程&#xff0c;從創建項目到發布。接下來將為Flutter天氣項目開發一個基于高德定位SDK的Flutter定位插件。 申請key 首先進入高德地圖定位SDK文檔內下載定位SDK&#xff0c;并按要求申請A…

分布式鎖之redis6

一、分布式鎖介紹 之前我們都是使用本地鎖&#xff08;synchronize、lock等&#xff09;來避免共享資源并發操作導致數據問題&#xff0c;這種是鎖在當前進程內。 那么在集群部署下&#xff0c;對于多個節點&#xff0c;我們要使用分布式鎖來避免共享資源并發操作導致數據問題…

ubuntu中使用安卓模擬器

本文這里介紹 使用 android studio Emulator &#xff0c; 當然也有 Anbox (Lightweight)&#xff0c; Waydroid (Best for Full Android Experience), 首先確保自己安裝了 android studio &#xff1b; sudo apt update sudo apt install openjdk-11-jdk sudo snap install…

二語習得理論(Second Language Acquisition, SLA)如何學習英語

二語習得理論&#xff08;Second Language Acquisition, SLA&#xff09;是研究學習者如何在成人或青少年階段學習第二語言&#xff08;L2&#xff09;的理論框架。該理論主要關注語言習得過程中的認知、社會和文化因素&#xff0c;解釋了學習者如何從初學者逐漸變得流利并能夠…