OpenAI ChatGPT Unity-Zugriff

OpenAI ChatGPT Unity-Zugriff

OpenAi-API-Unity-Methode

OpenAi-API-Unity-Download

GitHub: OpenAi-API-Unity-Homepage

GitHub: Download-Adresse des OpenAi-API-Unity-Installationspakets

既然 Unity 都给了下载地址都给了,怎么能少了 UE 呢。都在下面了

GitHub: OpenAi-API-Unreal Home

GitHub: Download-Adresse des OpenAi-API-Unreal-Installationspakets

反正我下载的是 0.2.9 版本 你们按需下载就行。
如果都下载不了的话 我 CSDN 上面上传的也有 巴拉一下就能找到。

Bitte fügen Sie eine Bildbeschreibung hinzu

为了防止出现意外 最好两个 安装包都下载。

Bitte fügen Sie eine Bildbeschreibung hinzu

lokale Konfiguration

打开我的电脑 在地址栏键入:
Windows:%USERPROFILE%/
Mac:~/

Bitte fügen Sie eine Bildbeschreibung hinzu

找到 .openai 文件夹并打开。
如果没有就自己新建一个。

Bitte fügen Sie eine Bildbeschreibung hinzu

找到 auth.json 文件夹并打开。
如果没有就自己新建一个。

Bitte fügen Sie eine Bildbeschreibung hinzu

找到 auth.json 文件夹并打开。
如果没有就自己新建一个。
下面是里面的内容注意:填写自己OpenAI key 的时候没有尖括号!没有尖括号!没有尖括号!
重要的事情说三遍。
{
    
    
  "private_api_key":"<YOUR_KEY>"
}

Bitte fügen Sie eine Bildbeschreibung hinzu

Unity-Module

新建一个新的项目 打开 Package Manager。

Bitte fügen Sie eine Bildbeschreibung hinzu

URL-Zugriff

点击 git URL 按钮

Bitte fügen Sie eine Bildbeschreibung hinzu

键入:https://github.com/hexthedev/OpenAi-Api-Unity.git
如果成功会有 Open AI 插件显示。
如果没下再试试下面的方法。

Bitte fügen Sie eine Bildbeschreibung hinzu

GZ-Zugriff

点击 gz 导入按钮

Bitte fügen Sie eine Bildbeschreibung hinzu

点击刚才下载好的 压缩包
如果成功会有 Open AI 插件显示。
如果没下再试试下面的的方法。

Bitte fügen Sie eine Bildbeschreibung hinzu

JSON-Zugriff

这个绝对能成!
点击 磁盘导入按钮。

Bitte fügen Sie eine Bildbeschreibung hinzu

解压刚才下载 OpenAi-Api-Unity-0.2.9.zip 压缩包
打开文件夹到根目录。
点击 package.json 文本并打开

Bitte fügen Sie eine Bildbeschreibung hinzu

你就会发现 成功了!旋转 跳跃。

Bitte fügen Sie eine Bildbeschreibung hinzu

Offene KI

在菜单栏 点击 OpenAi -> Examples -> Chat at Runtime

Bitte fügen Sie eine Bildbeschreibung hinzu

然后就会打开一个新的场景。
好了,点击运行。在这里你就可以,跟 OpenAI 对话了。

Bitte fügen Sie eine Bildbeschreibung hinzu

Bitte fügen Sie eine Bildbeschreibung hinzu

OpenAi-Api-Unity-Plugin-Dokumentation

GitHub: Dokumentadresse des OpenAi-Api-Unity-Plugins

Bitte fügen Sie eine Bildbeschreibung hinzu

OpenAi-Lokalisierungszugriff auf die Unity-Methode

Unity-Keyword-Spotting

当前脚本主要作用是:使用 Unity 自带的 PhraseRecognizer 类 进行关键字识别。
识别通过之后响应 之后的逻辑执行。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows.Speech;

/// <summary>
/// 关键字识别
/// </summary>
public class KeywordRecognition_ZH : MonoBehaviour
{
    
    
    public static KeywordRecognition_ZH _Instance;
    //语音识别短句
    private PhraseRecognizer _PhraseASR;


    [Header("精度")]
    public ConfidenceLevel _PrecisionASR = ConfidenceLevel.Medium;

    [Header("关键字数组")]
    public string[] _ListStrASR = {
    
     "启动", "关闭", "小哟" };

    //麦克风
    private string _Device;

    [Header("智能回答布尔")]
    public bool _OpenASRbool;

    void Start()
    {
    
    
        _Instance = this;

        //获取麦克风设备
        _Device = Microphone.devices[0];

        print(_Device);


        //用设备开始录音
        //设备的名称
        //指示当达到长度秒时录音是否应该继续录制,并从音频剪辑开始绕圈录制
        //录音产生的音频剪辑的长度 
        //44100 音频采样率
        //_AuduioASR = Microphone.Start(_Device, true, 999, 44100);

        if (_PhraseASR == null)
        {
    
    
            //创建语音识别
            _PhraseASR = new KeywordRecognizer(_ListStrASR, _PrecisionASR);
            //添加广播事件
            _PhraseASR.OnPhraseRecognized += MonitorASR;
            //开启语音识别
            _PhraseASR.Start();

            Debug.Log("创建识别器成功");
        }
    }


    /// <summary>
    /// 语音识别监听
    /// 提供关于短语识别事件的信息
    /// </summary>
    /// <param 识别信息="_Args"></param>
    private void MonitorASR(PhraseRecognizedEventArgs _Args)
    {
    
    
        switch (_Args.text)
        {
    
    
            case "启动":
                //每次回复前清空 输入问题
                GetOpenAI_ZH._Instance._InputProblemText.text = "";

                VoskSpeechToText._Instance._SpeakBool = true;
                VoskSpeechToText._Instance.ToggleRecording();

                _OpenASRbool = true;

                break;

            case "小哟":

                VoskSpeechToText._Instance._SpeakBool = true;
                VoskSpeechToText._Instance.ToggleRecording();
                _OpenASRbool = true;

                break;


            case "关闭":
                VoskSpeechToText._Instance._SpeakBool = false;
                VoskSpeechToText._Instance.ToggleRecording();
                break;


            default:
                break;
        }
        print(_Args.text);
    }

    private void OnDestroy()
    {
    
    
        //判断场景中是否存在语音识别
        if (_PhraseASR != null)
        {
    
    
            //语音识别释放
            _PhraseASR.Dispose();
        }

    }
}

Sprachsynthese und Text-to-Speech

根据百度提供的 API 文档进行文字转语音输出。
using Baidu.Aip.Speech;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.Http;
using UnityEngine;
using UnityEngine.Networking;

/// <summary>
/// 语音合成 & 文字转语音
/// </summary>
public class VoiceSynthesis_ZH : MonoBehaviour
{
    
    

    [Header("音源")]
    public AudioSource _Audio;

    [Header("AI 发声器")]
    public Pronouncer _Pronouncer = Pronouncer.Duyaya;

    //全局变量
    public static VoiceSynthesis_ZH _World;

    //网页文字转语音
    private string _Url;

    //百度语音识别SDK
    private Asr _AipClient;



    private void Start()
    {
    
    
        _World = this;
        //StartCoroutine(GetAudioClip("开始"));
    }


    //获取 Web网页音源信息并播放
    public IEnumerator GetAudioClip(string AudioText)
    {
    
    
        if (AudioText!=null)
        {
    
    

            _Url = "http://tsn.baidu.com/text2audio?tex=" + AudioText +
                  "&tok=自己的Token" +
                  "&cuid=a7a0e3326da873c6fb0609e6385a82b934c9cb11" +
                  "&ctp=1" +
                  "&lan=zh" +
                  "&spd=5" +
                  "&pit=5" +
                  "&vol=10" +
                  "&per=" + (((int)_Pronouncer).ToString()) +
                  "&aue=6";


            using (UnityWebRequest _AudioWeb = UnityWebRequestMultimedia.GetAudioClip(_Url, AudioType.WAV))
            {
    
    

                yield return _AudioWeb.SendWebRequest();
                if (_AudioWeb.isNetworkError)
                {
    
    
                    yield break;
                }
                AudioClip _Cli = DownloadHandlerAudioClip.GetContent(_AudioWeb);
                _Audio.clip = _Cli;
                _Audio.Play();
            }
        }      
    }

    /// <summary>
    /// 获取 Web网页音源信息并播放 附带延迟时间
    /// </summary>
    /// <param 播放文字="AudioText"></param>
    /// <param 延迟时间="_DelayedTimer"></param>
    /// <returns></returns>
    public IEnumerator GetAudioClip(string AudioText, float _DelayedTimer)
    {
    
    
        yield return new WaitForSeconds(_DelayedTimer);


        _Url = "http://tsn.baidu.com/text2audio?tex=" + AudioText +
              "&tok=自己的Token" +
              "&cuid=a7a0e3326da873c6fb0609e6385a82b934c9cb11" +
              "&ctp=1" +
              "&lan=zh" +
              "&spd=5" +
              "&pit=5" +
              "&vol=10" +
              "&per=" + (((int)_Pronouncer).ToString()) +
              "&aue=6";


        using (UnityWebRequest _AudioWeb = UnityWebRequestMultimedia.GetAudioClip(_Url, AudioType.WAV))
        {
    
    

            yield return _AudioWeb.SendWebRequest();
            if (_AudioWeb.isNetworkError)
            {
    
    
                yield break;
            }
            AudioClip _Cli = DownloadHandlerAudioClip.GetContent(_AudioWeb);
            _Audio.clip = _Cli;


            _Audio.Play();
        }
    }

    /// <summary>
    /// 语音识别
    /// </summary>
    /// <param 录取音频 = "_Clip" ></ param >
    /// < returns ></ returns >
    private IEnumerator Recognition(AudioClip _Clip)
    {
    
    
        //开放 音频 长度
        float[] _Sample = new float[_Clip.samples];

        //用片段中的样本数据填充数组
        _Clip.GetData(_Sample, 0);

        //数据转换
        short[] _IntData = new short[_Sample.Length];
        byte[] _ByteData = new byte[_IntData.Length * 2];
        for (int i = 0; i < _Sample.Length; i++)
        {
    
    
            _IntData[i] = (short)(_Sample[i] * short.MaxValue);
        }
        Buffer.BlockCopy(_IntData, 0, _ByteData, 0, _ByteData.Length);

        //返回Json数据  (数据 格式 码率)
        var _Result = _AipClient.Recognize(_ByteData, "pcm", 16000);

        //获取Json 数据中的 讲话内容
        var _Speaking = _Result.GetValue("result");

        //检测是否有内容
        if (_Speaking == null)
        {
    
    
            StopAllCoroutines();
            yield return null;
        }

        //讲话内容转换为 字符串
        string _UsefulText = _Speaking.First.ToString();
        print(_UsefulText);


        yield return null;
    }


    /// <summary>
    /// 访问令牌获取
    /// </summary>
    /// <returns></returns>
    private static class AccessToken

    {
    
    
        // 调用getAccessToken()获取的 access_token建议根据expires_in 时间 设置缓存
        // 返回token示例
        public static String TOKEN = "自己的Token";

        // 百度云中开通对应服务应用的 API Key 建议开通应用的时候多选服务
        private static String clientId = "百度云应用的AK";
        // 百度云中开通对应服务应用的 Secret Key 
        private static String clientSecret = "百度云应用的SK";

        public static String GetAccessToken()
        {
    
    
            String authHost = "https://aip.baidubce.com/oauth/2.0/token";
            HttpClient client = new HttpClient();
            List<KeyValuePair<string, string>> paraList = new List<KeyValuePair<string, string>>();
            paraList.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
            paraList.Add(new KeyValuePair<string, string>("client_id", clientId));
            paraList.Add(new KeyValuePair<string, string>("client_secret", clientSecret));

            HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
            String result = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
            return result;
        }
    }

    /// <summary>
    /// AI 发音器
    /// </summary>
    public enum Pronouncer
    {
    
    
        //普通女声
        Female,
        //普通男生
        Male,
        //特殊男声
        Teshunan,
        //情感合成男生
        Duxiaoyao,
        //情感合成女生
        Duyaya
    }


    private void Update()
    {
    
    
        if (Input.GetKeyDown(KeyCode.Escape))
        {
    
    
            Application.Quit();
        }
    }
}

Audioaufnahme und Echtzeit-Audioverarbeitung


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// 记录音频并为实时音频处理提供帧
/// 注意:打包成 Windows 后需要把 Windows 相关的 DLL 库放下相应的文件夹下
/// 例如 Windows :libgcc_s_seh-1.dll  libstdc++-6.dll  libvosk.dll  libwinpthread-1.dll
/// 放在 MonoBleedingEdge\EmbedRuntime 文件夹下
/// </summary>
public class VoiceProcessor : MonoBehaviour
{
    
    
    /// <summary>
    /// 指示麦克风是否被捕获
    /// </summary>
    public bool IsRecording
    {
    
    
        get {
    
     return _audioClip != null && Microphone.IsRecording(CurrentDeviceName); }
    }

    [Header("麦克风")]
    [SerializeField] private int _MicrophoneIndex;

    /// <summary>
    /// 录制音频的采样率
    /// </summary>
    public int SampleRate {
    
     get; private set; }

    /// <summary>
    /// 传送的音频帧的大小
    /// </summary>
    public int FrameLength {
    
     get; private set; }

    /// <summary>
    /// 传递音频帧的事件
    /// </summary>
    public event Action<short[]> OnFrameCaptured;

    /// <summary>
    /// 事件,当音频捕获线程停止时
    /// </summary>
    public event Action OnRecordingStop;

    /// <summary>
    /// 事件,当音频捕获线程启动时
    /// </summary>
    public event Action OnRecordingStart;

    /// <summary>
    /// 可用的录音设备
    /// </summary>
    public List<string> Devices {
    
     get; private set; }

    /// <summary>
    /// 所选录音设备的索引
    /// </summary>
    public int CurrentDeviceIndex {
    
     get; private set; }

    /// <summary>
    /// 所选录音设备的名称
    /// </summary>
    public string CurrentDeviceName
    {
    
    
        get
        {
    
    
            if (CurrentDeviceIndex < 0 || CurrentDeviceIndex >= Microphone.devices.Length)
                return string.Empty;
            return Devices[CurrentDeviceIndex];
        }
    }

    [Header("语音最小音量检测")]
    [SerializeField, Tooltip("检测语音输入的最小音量"), Range(0.0f, 1.0f)]
    private float _MinimumSpeakingSampleValue = 0.05f;

    [SerializeField, Tooltip("发送语音请求前检测到的沉默时间(以秒为单位)")]
    [Header("语音发送沉默时间")]
    private float _SilenceTimer = 1.0f;

    [SerializeField, Tooltip("使用音量阈值自动检测语音。")]
    [Header("语音检测布尔")]
    private bool _AutoDetect;

    private float _TimeAtSilenceBegan;
    private bool _AudioDetected;
    private bool _DidDetect;
    private bool _Transmit;


    AudioClip _audioClip;
    private event Action RestartRecording;

    void Awake()
    {
    
    
        UpdateDevices();
    }
#if UNITY_EDITOR
    void Update()
    {
    
    
        if (CurrentDeviceIndex != _MicrophoneIndex)
        {
    
    
            ChangeDevice(_MicrophoneIndex);
        }
    }
#endif

    /// <summary>
    /// 更新可用音频设备列表
    /// </summary>
    public void UpdateDevices()
    {
    
    
        Devices = new List<string>();
        foreach (var device in Microphone.devices)
            Devices.Add(device);

        if (Devices == null || Devices.Count == 0)
        {
    
    
            CurrentDeviceIndex = -1;
            Debug.LogError("没有连接有效的录音设备");
            return;
        }

        CurrentDeviceIndex = _MicrophoneIndex;
    }

    /// <summary>
    /// 更换录音设备
    /// </summary>
    /// <param name="deviceIndex">新音频捕获设备的索引</param>
    public void ChangeDevice(int deviceIndex)
    {
    
    
        if (deviceIndex < 0 || deviceIndex >= Devices.Count)
        {
    
    
            Debug.LogError(string.Format("指定的设备索引{0}不是有效的记录设备", deviceIndex));
            return;
        }

        if (IsRecording)
        {
    
    
            // 用新设备重新开始录制的一次性事件
            // 最后一个会话完成的时刻
            RestartRecording += () =>
            {
    
    
                CurrentDeviceIndex = deviceIndex;
                StartRecording(SampleRate, FrameLength);
                RestartRecording = null;
            };
            StopRecording();
        }
        else
        {
    
    
            CurrentDeviceIndex = deviceIndex;
        }
    }

    /// <summary>
    /// 开始录音
    /// </summary>
    /// <param name="sampleRate">记录的采样率</param>
    /// <param name="frameSize">要传送的音频帧的大小</param>
    /// <param name="autoDetect">音频是否应该根据音量连续记录</param>
    public void StartRecording(int sampleRate = 16000, int frameSize = 512, bool ?autoDetect = null)
    {
    
    
        if (autoDetect != null)
        {
    
    
            _AutoDetect = (bool) autoDetect;
        }

        if (IsRecording)
        {
    
    
            // 如果采样率或帧大小已经改变,重新开始记录
            if (sampleRate != SampleRate || frameSize != FrameLength)
            {
    
    
                RestartRecording += () =>
                {
    
    
                    StartRecording(SampleRate, FrameLength, autoDetect);
                    RestartRecording = null;
                };
                StopRecording();
            }

            return;
        }

        SampleRate = sampleRate;
        FrameLength = frameSize;

        _audioClip = Microphone.Start(CurrentDeviceName, true, 1, sampleRate);

        StartCoroutine(RecordData());
    }

    /// <summary>
    /// 停止录音
    /// </summary>
    public void StopRecording()
    {
    
    
        if (!IsRecording)
            return;

        Microphone.End(CurrentDeviceName);
        Destroy(_audioClip);
        _audioClip = null;
        _DidDetect = false;

        StopCoroutine(RecordData());
    }

    /// <summary>
    /// 用于缓冲传入音频数据和传送帧的循环
    /// </summary>
    IEnumerator RecordData()
    {
    
    
        float[] sampleBuffer = new float[FrameLength];
        int startReadPos = 0;

        if (OnRecordingStart != null)
            OnRecordingStart.Invoke();

        while (IsRecording)
        {
    
    
            int curClipPos = Microphone.GetPosition(CurrentDeviceName);
            if (curClipPos < startReadPos)
                curClipPos += _audioClip.samples;

            int samplesAvailable = curClipPos - startReadPos;
            if (samplesAvailable < FrameLength)
            {
    
    
                yield return null;
                continue;
            }

            int endReadPos = startReadPos + FrameLength;
            if (endReadPos > _audioClip.samples)
            {
    
    
                // 碎片式读取(绕到片段的开头)
                // 在片段末尾读取位
                int numSamplesClipEnd = _audioClip.samples - startReadPos;
                float[] endClipSamples = new float[numSamplesClipEnd];
                _audioClip.GetData(endClipSamples, startReadPos);

                // 在剪辑开始时读取位
                int numSamplesClipStart = endReadPos - _audioClip.samples;
                float[] startClipSamples = new float[numSamplesClipStart];
                _audioClip.GetData(startClipSamples, 0);

                // 组合成全画框
                Buffer.BlockCopy(endClipSamples, 0, sampleBuffer, 0, numSamplesClipEnd);
                Buffer.BlockCopy(startClipSamples, 0, sampleBuffer, numSamplesClipEnd, numSamplesClipStart);
            }
            else
            {
    
    
                _audioClip.GetData(sampleBuffer, startReadPos);
            }

            startReadPos = endReadPos % _audioClip.samples;
            if (_AutoDetect == false)
            {
    
    
                _Transmit =_AudioDetected = true;
            }
            else
            {
    
    
                float maxVolume = 0.0f;

                for (int i = 0; i < sampleBuffer.Length; i++)
                {
    
    
                    if (sampleBuffer[i] > maxVolume)
                    {
    
    
                        maxVolume = sampleBuffer[i];
                    }
                }

                if (maxVolume >= _MinimumSpeakingSampleValue)
                {
    
    
                    _Transmit= _AudioDetected = true;
                    _TimeAtSilenceBegan = Time.time;
                }
                else
                {
    
    
                    _Transmit = false;

                    if (_AudioDetected && Time.time - _TimeAtSilenceBegan > _SilenceTimer)
                    {
    
    
                        _AudioDetected = false;
                    }
                }
            }

            if (_AudioDetected)
            {
    
    
                _DidDetect = true;
                // 转换为16位int样本
                short[] pcmBuffer = new short[sampleBuffer.Length];
                for (int i = 0; i < FrameLength; i++)
                {
    
    
                    pcmBuffer[i] = (short) Math.Floor(sampleBuffer[i] * short.MaxValue);
                }

                // 引发缓冲区事件
                if (OnFrameCaptured != null && _Transmit)
                    OnFrameCaptured.Invoke(pcmBuffer);
            }
            else
            {
    
    
                if (_DidDetect)
                {
    
    
                    if (OnRecordingStop != null)
                        OnRecordingStop.Invoke();
                    _DidDetect = false;
                }
            }
        }


        if (OnRecordingStop != null)
            OnRecordingStop.Invoke();
        if (RestartRecording != null)
            RestartRecording.Invoke();
    }
}

Rede zum Text

使用麦克风 录取音频片段并根据模型进行 转录文字输出。
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Ionic.Zip;
using Unity.Profiling;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Vosk;

/// <summary>
/// 语音转文字
/// </summary>
public class VoskSpeechToText : MonoBehaviour
{
    
    
	//单例
	public static VoskSpeechToText _Instance;

	[Header("模型路径")]
	[Tooltip("模型的位置,相对于Streaming Assets文件夹。")]
	public string ModelPath = "vosk-model-small-cn-0.22.zip";

	[Header("麦克风")]
	[Tooltip("麦克风输入的源")]
	public VoiceProcessor VoiceProcessor;

	[Header("处理最大数量")]
	[Tooltip("将要处理的备选项的最大数量。")]
	public int MaxAlternatives = 3;

	[Header("最长记录时间")]
	[Tooltip("在重新开始之前我们应该记录多长时间?")]
	public float MaxRecordLength = 5;

	[Header("识别器启动布尔")]
	[Tooltip("识别器是否应该在应用程序启动时启动?")]
	public bool AutoStart = true;

	[Header("检测短语数组")]
	[Tooltip("将被检测到的短语。如果为空,将检测所有单词。")]
	public List<string> KeyPhrases = new List<string>();

	//Vosk模型的缓存版本。
	private Model _Model;

	//Vosk识别器的缓存版本。
	private VoskRecognizer _Recognizer;

	//条件标志,用于查看是否已经创建了识别器。
	//TODO:允许对识别器进行运行时更改。
	private bool _RecognizerReady;

	//保留所有音频数据,直到用户停止通话。
	private readonly List<short> _Buffer = new List<short>();

	//当控制器的状态改变时调用。
	public Action<string> OnStatusUpdated;

	//在用户完成讲话后调用,vosk处理音频。
	public Action<string> OnTranscriptionResult;

	//解压缩模型文件夹的绝对路径。
	private string _DecompressedModelPath;

	//字符串,包含Json Array格式的关键字
	private string _Grammar = "";

	//用于等待模型文件成功解压缩的标志。
	private bool _IsDecompressing;

	//用于等待脚本成功启动的标志。
	private bool _IsInitializing;

	//用于检查Vosk是否启动的标志。
	private bool _DidInit;

	//关键字识别布尔
	[Header("关键字识别布尔")]
	public bool _SpeakBool = true;

	//线程的逻辑

	//旗帜表示我们结束了
	private bool _Running;

	//麦克风数据的线程安全队列。
	private readonly ConcurrentQueue<short[]> _ThreadedBufferQueue = new ConcurrentQueue<short[]>();

	//线程安全的结果队列
	private readonly ConcurrentQueue<string> _ThreadedResultQueue = new ConcurrentQueue<string>();



	static readonly ProfilerMarker _VoskRecognizerCreateMarker = new ProfilerMarker("VoskRecognizer.Create");
	static readonly ProfilerMarker _VoskRecognizerReadMarker = new ProfilerMarker("VoskRecognizer.AcceptWaveform");

	//如果启用了“自动启动”,则可以启动语音转文本。
	void Start()
	{
    
    
		_Instance = this;
		if (AutoStart)
		{
    
    
			StartVoskStt();
		}
	}

	/// <summary>
	/// 启动Vosk语音转文本
	/// </summary>
	/// <param name="keyPhrases">关键字/短语列表。关键字需要存在于模型字典中,所以像“webview”这样的词被更好地检测为两个更常见的词“webview”.</param>
	/// <param name="modelPath">模型文件夹相对于StreamingAssets的路径。如果路径以.zip结尾,它将被解压缩到应用程序数据持久文件夹中</param>
	/// <param name="startMicrophone">"麦克风应该在vosk初始化之后吗?</param>
	/// <param name="maxAlternatives">检测到的可选短语的最大数目</param>
	public void StartVoskStt(List<string> keyPhrases = null, string modelPath = default, bool startMicrophone = false, int maxAlternatives = 3)
	{
    
    
		if (_IsInitializing)
		{
    
    
			Debug.LogError("正在初始化!");
			return;
		}
		if (_DidInit)
		{
    
    
			Debug.LogError("Vosk 已经初始化!");
			return;
		}

		//语言模型加载
		if (!string.IsNullOrEmpty(modelPath))
		{
    
    
			ModelPath = modelPath;
		}

		//关键字加载
		if (keyPhrases != null)
		{
    
    
			KeyPhrases = keyPhrases;
		}

		MaxAlternatives = maxAlternatives;
		StartCoroutine(DoStartVoskStt(startMicrophone));
	}

	//解压模型,加载设置,启动Vosk和可选地启动麦克风
	private IEnumerator DoStartVoskStt(bool startMicrophone)
	{
    
    
		_IsInitializing = true;
		yield return WaitForMicrophoneInput();

		yield return Decompress();

		OnStatusUpdated?.Invoke("加载模型来自: " + _DecompressedModelPath);
		//Vosk.Vosk.SetLogLevel(0);
		_Model = new Model(_DecompressedModelPath);

		yield return null;

		OnStatusUpdated?.Invoke("初始化");
		VoiceProcessor.OnFrameCaptured += VoiceProcessorOnOnFrameCaptured;
		VoiceProcessor.OnRecordingStop += VoiceProcessorOnOnRecordingStop;

		if (startMicrophone)
			VoiceProcessor.StartRecording();

		_IsInitializing = false;
		_DidInit = true;

		ToggleRecording();
		_SpeakBool = false;
		ToggleRecording();
	}

	//将keyphrases转换为json数组,并在末尾附加' [unk] '关键字,以告诉vosk过滤其他短语。
	private void UpdateGrammar()
	{
    
    
		if (KeyPhrases.Count == 0)
		{
    
    
			_Grammar = "";
			return;
		}

		JSONArray keywords = new JSONArray();
		foreach (string keyphrase in KeyPhrases)
		{
    
    
			keywords.Add(new JSONString(keyphrase.ToLower()));
		}

		keywords.Add(new JSONString("[unk]"));

		_Grammar = keywords.ToString();
	}

	//解压缩模型zip文件或返回解压缩文件的位置。
	private IEnumerator Decompress()
	{
    
    
		if (!Path.HasExtension(ModelPath)
			|| Directory.Exists(
				Path.Combine(Application.persistentDataPath, Path.GetFileNameWithoutExtension(ModelPath))))
		{
    
    
			OnStatusUpdated?.Invoke("使用现有的解压缩模型");
			_DecompressedModelPath =
				Path.Combine(Application.persistentDataPath, Path.GetFileNameWithoutExtension(ModelPath));
			Debug.Log(_DecompressedModelPath);

			yield break;
		}

		OnStatusUpdated?.Invoke("模型解压中...");
		string dataPath = Path.Combine(Application.streamingAssetsPath, ModelPath);

		Stream dataStream;
		// 从流资产路径读取数据。你不能直接在Android上访问流媒体资源。
		if (dataPath.Contains("://"))
		{
    
    
			UnityWebRequest www = UnityWebRequest.Get(dataPath);
			www.SendWebRequest();
			while (!www.isDone)
			{
    
    
				yield return null;
			}
			dataStream = new MemoryStream(www.downloadHandler.data);
		}
		// 在有效的平台上直接读取文件。
		else
		{
    
    
			dataStream = File.OpenRead(dataPath);
		}

		//读取Zip文件
		var zipFile = ZipFile.Read(dataStream);

		//等待zip文件完成解压缩
		zipFile.ExtractProgress += ZipFileOnExtractProgress;

		//更新状态文本
		OnStatusUpdated?.Invoke("读取Zip文件");

		//开始提取
		zipFile.ExtractAll(Application.persistentDataPath);

		//等到它完成
		while (_IsDecompressing == false)
		{
    
    
			yield return null;
		}
		//覆盖ZipFileOnExtractProgress中给出的路径以防止崩溃
		_DecompressedModelPath = Path.Combine(Application.persistentDataPath, Path.GetFileNameWithoutExtension(ModelPath));

		//更新状态文本
		OnStatusUpdated?.Invoke("解压完成!");
		//稍等一下,以防我们需要初始化另一个对象。
		yield return new WaitForSeconds(1);
		//处理zipfile读取器。
		zipFile.Dispose();
	}

	///更新zip文件提取过程时调用的函数。
	private void ZipFileOnExtractProgress(object sender, ExtractProgressEventArgs e)
	{
    
    
		if (e.EventType == ZipProgressEventType.Extracting_AfterExtractAll)
		{
    
    
			_IsDecompressing = true;
			_DecompressedModelPath = e.ExtractLocation;
		}
	}

	//等待麦克风初始化
	private IEnumerator WaitForMicrophoneInput()
	{
    
    
		while (Microphone.devices.Length <= 0)
			yield return null;
	}

	//可以从脚本或GUI按钮中调用以启动检测。
	public void ToggleRecording()
	{
    
    
 
		Debug.Log("Toogle记录");
		if (!VoiceProcessor.IsRecording)
		{
    
    
            if (_SpeakBool )
            {
    
    
				Debug.Log("开始记录");
				_Running = true;
				VoiceProcessor.StartRecording();
				Task.Run(ThreadedWork).ConfigureAwait(false);
			}
            else
            {
    
    
				Debug.Log("停止记录");
				_Running = false;
				VoiceProcessor.StopRecording();
			}
		}
		else
		{
    
    
			Debug.Log("停止记录");
			_Running = false;
			VoiceProcessor.StopRecording();
		}
	}

	//调用Unity线程上的On短语识别事件
	void Update()
	{
    
    
		if (_ThreadedResultQueue.TryDequeue(out string voiceResult))
		{
    
    
		    OnTranscriptionResult?.Invoke(voiceResult);
		}
	}

	/// <summary>
	/// 当检测到新的音频时,从语音处理器回调
	/// </summary>
	/// <param name="samples"></param>
	private void VoiceProcessorOnOnFrameCaptured(short[] samples)
	{
    
    	
                _ThreadedBufferQueue.Enqueue(samples);
	}

	/// <summary>
	/// 录音停止时从语音处理器回调
	/// </summary>
	private void VoiceProcessorOnOnRecordingStop()
	{
    
    
                Debug.Log("停止");
	}

	//将音频逻辑输入语音识别器
	private async Task ThreadedWork()
	{
    
    
		_VoskRecognizerCreateMarker.Begin();
		if (!_RecognizerReady)
		{
    
    
			UpdateGrammar();

			//仅检测指定的已定义关键字。
			if (string.IsNullOrEmpty(_Grammar))
			{
    
    
				_Recognizer = new VoskRecognizer(_Model, 16000.0f);
			}
			else
			{
    
    
				_Recognizer = new VoskRecognizer(_Model, 16000.0f, _Grammar);
			}

			_Recognizer.SetMaxAlternatives(MaxAlternatives);
			//_recognizer.SetWords(true);
			_RecognizerReady = true;

			Debug.Log("识别器准备好了");
		}

		_VoskRecognizerCreateMarker.End();

		_VoskRecognizerReadMarker.Begin();

		while (_Running)
		{
    
    
			if (_ThreadedBufferQueue.TryDequeue(out short[] voiceResult))
			{
    
    
				if (_Recognizer.AcceptWaveform(voiceResult, voiceResult.Length))
				{
    
    
					var result = _Recognizer.Result();
					_ThreadedResultQueue.Enqueue(result);
				}
			}
			else
			{
    
    
				// 等待一些数据
				await Task.Delay(100);
			}
		}

		_VoskRecognizerReadMarker.End();
	}
}

Vosk akzeptiert die Antwort

针对模型输出结果的响应输出。
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// Vosk 返回结果
/// </summary>
public class VoskResultText : MonoBehaviour 
{
    
    
    [Header("Vosk 语音转文本")]
    public VoskSpeechToText _VoskSpeechToText;
    [Header("返回文本")]
    public InputField _ResultText;

    void Awake()
    {
    
    
        //监听
        _VoskSpeechToText.OnTranscriptionResult += OnTranscriptionResult;
    }

    /// <summary>
    /// 语音转录文字方法
    /// </summary>
    /// <param name="obj"></param>
    private void OnTranscriptionResult(string obj)
    {
    
    
        //Debug.Log(obj);
        var result = new RecognitionResult(obj);
        for (int i = 0; i < result.Phrases.Length; i++)
        {
    
    
            //说话内容 不为空
            if (result.Phrases[i].Text!=""|| result.Phrases[i].Text!=" ")
            {
    
    
                if (i > 0)
                {
    
    
                    _ResultText.text += ", ";
                }
                //如果是多个结果的话 只要第一个结果
                _ResultText.text += result.Phrases[0].Text.Replace(" ", "");
                //说话内容 并剔除所有空格
                Debug.Log(_ResultText.text);
                var _StrRe = result.Phrases[0].Text.Replace(" ", "");
                //ResultText.text = _StrRe;

                if (_StrRe != "小哟" || _StrRe != "小哟小哟")
                {
    
    
                    //如果是多个结果的话 只要第一个结果
                    _ResultText.text = _StrRe;
                }
                if (KeywordRecognition_ZH._Instance._OpenASRbool)
                {
    
    
                    //智能回答
                    GetOpenAI_ZH._Instance._InputProblemText.text = _StrRe;
                    GetOpenAI_ZH._Instance.SendData();

                    //录音关闭
                    VoskSpeechToText._Instance._SpeakBool = false;
                    VoskSpeechToText._Instance.ToggleRecording();

                    //回答响应布尔
                    KeywordRecognition_ZH._Instance._OpenASRbool = false;
                }
                return;
            }
        }
    }
}

OpenAI

访问 Open AI 需要一个接收 Json 数据的类,一个发送 Json 数据的类,我都会放在下面。
还有几个文档链接大家注意看。
Chat API 访问 URL:https://api.openai.com/v1/chat/completions

极简回答:
《核心》:访问 OpenAI 网址、使用 POST 方法进行参数传递、等待响应、可视化显示。

Link: Adresse des AI-API-Dokuments öffnen

Link: Open AI API-Beispieladresse

Link: Offene Plattformadresse der Open AI API

Beispiel zum Senden einer Nachricht

     //发送消息 示例
    {
    
    
        "model":"gpt-3.5-turbo",
        "messages":
        [
            {
    
    
                "role":"user",
                "content":"你是谁"
            }
        ],
        "max_tokens":2048,
        "temperature":0.5,
        "top_p":1,
        "frequency_penalty":1,
        "presence_penalty":1,
        "stop":"stop"
    }

Beispiel einer Antwortnachricht

	//返回消息 示例
    {
    
    
        "id":"chatcmpl-7CQ1C0ZL7XUOdqPcblJDxxPnOmI1c",
        "object":"chat.completion",
        "created":1683194306,
        "model":"gpt-3.5-turbo-0301",
        "usage":{
    
    
            "prompt_tokens":12,
            "completion_tokens":15,
            "total_tokens":27
        },
        "choices":
        [
            {
    
    
                "message":
                {
    
    
                    "role":"assistant",
                    "content":"我是一个AI语言模型,由OpenAI开发。"
                },
                "finish_reason":"stop",
                "index":0
            }
        ]
    }

Offener KI-Zugang

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.UI;
using static AcceptJson_ZH;
using static PostDataJson_ZH;
/// <summary>
/// Open AI 访问
/// </summary>
public class GetOpenAI_ZH : MonoBehaviour
{
    
    
    public static GetOpenAI_ZH _Instance;

    //API key
    private string _OpenAI_Key = "Open AI Key";

    // Chat API 访问 URL
    private string _OpenAIUrl = "https://api.openai.com/v1/chat/completions";
    //配置参数
    [SerializeField] private PostDataJson_ZH _PostDataSetting;


    [Header("输入的信息")]
    [SerializeField] public InputField _InputProblemText;

    [Header("回复的信息")]
    [SerializeField] public Text _RobotChatText;

    [Header("输入列表")]
    private List<GameObject> _InputList=new List<GameObject>();

    //回答模型
    [HideInInspector]
    public ModelType _ModelType {
    
     get; set; }

    //模型菜单显示 布尔
    private bool _ModelMenuActive;

    private void Awake()
    {
    
    
        _Instance = this;
    }

    private void Start()
    {
    
    
        _InputList.Add(GameObject.Find("发送"));
        _InputList.Add(_InputProblemText.gameObject);
    }

    /// <summary>
    /// 回答模型选择方法
    /// </summary>
    /// <param 当前执行 Button="_ModelTypeButton"></param>
    public void ModelTypeSet(Button _ModelTypeButton)
    {
    
    
        if (_ModelTypeButton.name == "gpt-3.5-turbo")
        {
    
    
            _ModelType = ModelType.gpt35turbo;
        }
        else if (_ModelTypeButton.name == "gpt-3.5-turbo-0301")
        {
    
    
            _ModelType = ModelType.gpt35turbo0301;
        }
        else if (_ModelTypeButton.name == "gpt-4")
        {
    
    
            _ModelType = ModelType.gpt4;
        }
        else if (_ModelTypeButton.name == "gpt-4-0314")
        {
    
    
            _ModelType = ModelType.gpt40314;
        }
        else if (_ModelTypeButton.name == "gpt-4-32k")
        {
    
    
            _ModelType = ModelType.gpt432k;
        }
        else if (_ModelTypeButton.name == "gpt-4-32k-0314")
        {
    
    
            _ModelType = ModelType.gpt432k0314;
        }
        else if (_ModelTypeButton.name == "text-davinci-003")
        {
    
    
            _ModelType = ModelType.textdavinci003;
        }
    }


    /// <summary>
    /// 发送信息
    /// </summary>
    public void SendData()
    {
    
    
        if (_InputProblemText.text.Equals(""))
            return;

        //问题
        string _Problem = _InputProblemText.text;

        StartCoroutine(GetPostData(_Problem));
        //_InputText.text = "";
    }


    /// <summary>
    /// POST 方法请求
    /// </summary>
    /// <param 问题="_SendMessage"></param>
    /// <returns></returns>
    private IEnumerator GetPostData(string _SendMessage)
    {
    
    
         OpenAI 访问
        //var _Request = new UnityWebRequest(_OpenAIUrl, "POST");

        // OpenAI 访问
        using (UnityWebRequest _Request = new UnityWebRequest(_OpenAIUrl, "POST"))
        {
    
    
            //规则归一化
            PostDataJson_ZH _PostData = new PostDataJson_ZH
            {
    
    
                //model =  "gpt-3.5-turbo",
                max_tokens = _PostDataSetting.max_tokens,
                temperature = _PostDataSetting.temperature,
                top_p = _PostDataSetting.top_p,
                frequency_penalty = _PostDataSetting.frequency_penalty,
                presence_penalty = _PostDataSetting.presence_penalty,
                stop = _PostDataSetting.stop
            };

            //模型设置
            switch (_ModelType)
            {
    
    
                //gpt-3.5-turbo、gpt-3.5-turbo-0301、gpt-4、gpt-4-0314、gpt-4-32k、gpt-4-32k-0314、text-davinci-003
                case ModelType.gpt35turbo:
                    _PostData.model = "gpt-3.5-turbo";
                    break;
                case ModelType.gpt35turbo0301:
                    _PostData.model = "gpt-3.5-turbo-0301";
                    break;
                case ModelType.gpt4:
                    _PostData.model = "gpt-4";
                    break;
                case ModelType.gpt40314:
                    _PostData.model = "gpt-4-0314";
                    break;
                case ModelType.gpt432k:
                    _PostData.model = "gpt-4-32k";
                    break;
                case ModelType.gpt432k0314:
                    _PostData.model = "gpt-4-32k-0314";
                    break;
                case ModelType.textdavinci003:
                    _PostData.model = "text-davinci-003";
                    break;
                default:
                    break;
            }
            //消息赋予
            PostDataJson_ZH.MessagesItem _Messages = new PostDataJson_ZH.MessagesItem();
            _Messages.role = "user";
            _Messages.content = _SendMessage;
            _PostData.messages.Add(_Messages);

            //数据转换
            string _JsonText = JsonUtility.ToJson(_PostData);
            print(_JsonText);

            byte[] _Data = System.Text.Encoding.UTF8.GetBytes(_JsonText);
            //数据上传 等待响应
            _Request.uploadHandler = new UploadHandlerRaw(_Data);
            _Request.downloadHandler = new DownloadHandlerBuffer();

            //数据重定向
            _Request.SetRequestHeader("Content-Type", "application/json");
            _Request.SetRequestHeader("Authorization", string.Format("Bearer {0}", _OpenAI_Key));

            //等待响应 开始与远程服务器通信
            yield return _Request.SendWebRequest();



            //数据返回
            if (_Request.responseCode == 200)
            {
    
    
                //接收返回信息
                string _Message = _Request.downloadHandler.text;
                //数据转换
                AcceptJson_ZH _Textback = JsonUtility.FromJson<AcceptJson_ZH>(_Message);

                //确保当前有消息传回
                if (_Textback != null && _Textback.choices.Count > 0)
                {
    
    
                    //OpenAI 输出 清空
                    _RobotChatText.text = "";
                    //打印
                    print(_Textback.choices[0].message.content);
                    //回答消息填写
                    _RobotChatText.text = _Textback.choices[0].message.content;

                    //文字转语音 回答
                    StartCoroutine(VoiceSynthesis_ZH._World.GetAudioClip(_Textback.choices[0].message.content));
                }
            }
        }
    }


    /// <summary>
    /// 获取当前选中物体的序列
    /// </summary>
    /// <param 当前输入="input"></param>
    /// <returns></returns>
    private int IndexNow(GameObject _Input)
    {
    
    
        int _IndexNow = 0;
        for (int i = 0; i < _InputList.Count; i++)
        {
    
    
            if (_Input == _InputList[i])
            {
    
    
                _IndexNow = i;
                break;
            }
        }
        return _IndexNow ;
    }

    /// <summary>
    /// 获取下一个物体
    /// </summary>
    /// <param 当前输入="_Input"></param>
    /// <returns></returns>
    private GameObject NextInput(GameObject _Input)
    {
    
    
        int _IndexNow = IndexNow(_Input);
        if (_IndexNow + 1 < _InputList.Count)
        {
    
    
            return _InputList[_IndexNow + 1].gameObject;
        }
        else
        {
    
    
            return _InputList[0].gameObject;
        }
    }


    void Update()
    {
    
    

        if (Input.GetKeyDown(KeyCode.Escape))
        {
    
    
            Application.Quit();
        }

        if (Input.GetKeyDown(KeyCode.Q))
        {
    
    
            _ModelMenuActive = !_ModelMenuActive;

            //显示设置
            if (_ModelMenuActive)
            {
    
    
                GameObject.Find("模型选择").transform.localScale = Vector3.one;
            }
            else
            {
    
    
                GameObject.Find("模型选择").transform.localScale = Vector3.zero;
            }
        }

        //输入切换
        if (Input.GetKeyDown(KeyCode.Tab))
        {
    
    
            //如果是当前数组中的元素
            if (_InputList.Contains(EventSystem.current.currentSelectedGameObject))
            {
    
    
                //正序
                GameObject _Next = NextInput(EventSystem.current.currentSelectedGameObject);
                EventSystem.current.SetSelectedGameObject(_Next);
            }
            //如果不是当前数组元素
            //默认开启第一个元素
            else
            {
    
    
                //第一个输入开启
                EventSystem.current.SetSelectedGameObject(_InputProblemText.gameObject);
            }
        }
    }
}

Json-Datenunterstützungsklasse senden

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Open AI 发送 数据
/// </summary>
[System.Serializable]
public class PostDataJson_ZH 
{
    
    
    [Header("使用模型")]
    [HideInInspector]
    public string model = "gpt-3.5-turbo";

    [Header("发送信息 数据")]
    public List<MessagesItem> messages = new List<MessagesItem>();

    [Header("最大 Token 值")]
    [Tooltip("可以在聊天完成中生成的最大令牌数")]
    public int max_tokens = 2048;

    [Header("采样温度")]
    [Tooltip("温度 使用什么采样温度,介于 0 和 2 之间。较高的值(如 0.8)将使输出更加随机,而较低的值(如 0.2)将使其更加集中和确定")]
    [Range(0,2)]
    public float temperature = 0.5f;


    [Header("采样温度")]
    [Tooltip("使用温度采样的替代方法称为核心采样,其中模型考虑具有top_p概率质量的令牌的结果。因此,0.1 意味着只考虑包含前 10% 概率质量的迭代")]
    [Range(0, 1)]
    public float top_p = 1;

    [Header("重复度")]
    [Tooltip("介于 -2.0 和 2.0 之间的数字。正值会根据新标记到目前为止在文本中的现有频率来惩罚新标记,从而降低模型逐字重复同一行的可能性")]
    [Range(0, 2)]
    public float frequency_penalty = 1.0f;

    [Header("新主题")]
    [Tooltip("介于 -2.0 和 2.0 之间的数字。正值会根据新标记到目前为止是否出现在文本中来惩罚它们,从而增加模型讨论新主题的可能性")]
    [Range(0, 2)]
    public float presence_penalty = 1.0f;

    [Header("结束原因")]
    [Tooltip("最多 4 个序列,其中 API 将停止生成更多令牌。")]
    public string stop = "stop";

    [System.Serializable]
    public class MessagesItem
    {
    
    
        /// <summary>
        /// 演员
        /// </summary>
        public string role;
        /// <summary>
        /// 信息
        /// </summary>
        public string content;
    }


    [System.Serializable]
    public enum ModelType
    {
    
    
        //gpt-3.5-turbo
        gpt35turbo,

        //gpt-3.5-turbo-0301
        gpt35turbo0301,

        //gpt-4
        gpt4,

        //gpt-4-0314
        gpt40314,

        //gpt-4-32k
        gpt432k,

        //gpt-4-32k-0314
        gpt432k0314,

        //text-davinci-003
        textdavinci003
    }
}

Erhalten Sie die Json-Datenunterstützungsklasse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// Open AI 接收 数据
/// </summary>
[System.Serializable]
public class AcceptJson_ZH
{
    
    
    /// <summary>
    /// Open AI ID
    /// </summary>
    public string id;
    /// <summary>
    /// 支付方式
    /// </summary>
    public string @object;
    /// <summary>
    /// 建立 标识
    /// </summary>
    public int created;
    /// <summary>
    /// 使用模型
    /// </summary>
    public string model;
    /// <summary>
    /// 用法
    /// </summary>
    public Usage usage;
    /// <summary>
    /// 参数选择
    /// </summary>
    [SerializeField]
    public List<ChoicesItem> choices;


    [System.Serializable]
    public class Usage
    {
    
    
        /// <summary>
        /// 指示令牌
        /// </summary>
        public int prompt_tokens;
        /// <summary>
        /// 完成令牌
        /// </summary>
        public int completion_tokens;
        /// <summary>
        /// 总令牌
        /// </summary>
        public int total_tokens;
    }

    [System.Serializable]
    public class Message
    {
    
    
        /// <summary>
        /// 角色 一般是 user
        /// </summary>
        public string role;
        /// <summary>
        /// 回答 信息
        /// </summary>
        public string content;
    }

    [System.Serializable]
    public class ChoicesItem
    {
    
    
        /// <summary>
        /// 返回消息
        /// </summary>
        [SerializeField]
        public Message message;
        /// <summary>
        /// 完成原因 一般是 stop
        /// </summary>
        public string finish_reason;
        /// <summary>
        /// 步数
        /// </summary>
        public int index;
    }
}

Skript-Huckepack und Hierarchie

KeywordRecognition_ZH 以及 VoiceSynthesis_ZH 搭载情况

Bitte fügen Sie eine Bildbeschreibung hinzu

VoiceProcessor、VoskSpeechToText、VoskResultText 搭载情况

Bitte fügen Sie eine Bildbeschreibung hinzu

GetOpenAI_ZH 搭载情况

Bitte fügen Sie eine Bildbeschreibung hinzu

Unity 层次结构

Bitte fügen Sie eine Bildbeschreibung hinzu

Betrieb

程序包含了语音输出模块、语音输出模块、ChatGPt回答、中英文双语对话、预留了二次开发接口。
就这吧 不想写了 人麻了。
好像忘了啥。啊对 Vosk的下载链接没给你们,我就不往上翻了就直接在下面写了。
太长了,抱歉  哈哈哈。
你们要是没有积分 就直接给我发私信 给我邮箱 我直接发你们邮箱 别说谢  受不了。(。・∀・)ノ゙

Link: Offizielle Website von Vosk

Link: Vosk-Downloadadresse

Link: Download-Adresse des Vosk-Sprachmodells

Bitte fügen Sie eine Bildbeschreibung hinzu

Bitte fügen Sie eine Bildbeschreibung hinzu

Lassen Sie uns dies vorerst tun. Wenn ich Zeit habe, werde ich das große Sprachmodell aktualisieren. Ich werde eine Integration vornehmen, wenn ich später Zeit finde. Lassen Sie uns das Treffen beenden. Wenn Sie es wirklich nicht verstehen, hinterlassen Sie eine Nachricht und ich werde antworten, sobald ich sie sehe.
Der Weg ist lang und der Weg ist lang, lasst uns euch gemeinsam ermutigen.

Supongo que te gusta

Origin blog.csdn.net/weixin_43925843/article/details/130506953
Recomendado
Clasificación