分享

桌面精灵制作记录

 新用户79878317 2023-01-09 发布于河南

前言

2014年时,想做一个会跳舞的,当在敲代码的时候驱动跳舞激励程序员、可以聊天的、可以语音聊 的桌面精灵

上个最后效果图 没gif

接入聊天AI

市面上的人工智能回答很多产品。比较流行的好用的有:

1.微软小娜和微软小冰,似乎是微软小娜比较好,微软小冰还处于比较基础的日常聊天,但回复内容多样,会有词语接龙、数绵羊、读心术、颜值测试和一些天气交通的日常功能等功能,而且调侃功能丰富,当年被微信封杀,却在微博刚上线的时候引发一波热潮。而相对的win10自带的微软小娜功能丰富。

2.小黄鸡。SimSimi是一款来自韩国的聊天机器人应用,以吉祥物“小鸡鸡”自居。SimSimi机器人的界面非常可爱,深受女生欢迎,最近网络上还刮起了一阵和SimSimi机器人对话的旋风。也尝试过接入,但其原本是用python写的,用Json进行应答传输,接入比较麻烦。

也尝试过小黄鸡
小黄鸡的消息上传需要编写xml或Json  对于xml或Json的处理   对于小黄鸡调用API的学习

3.图灵机器人。功能比较完善的一个自动回复机器人,是国人出品的,这次接入了这个。
图灵机器人官网:http://www./

效果图

图灵机器人接入关键代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Windows.Forms;
  8. using System.Net;
  9. using System.IO;
  10. using Newtonsoft.Json;
  11. using UnityEditor;
  12. using UnityEngine;
  13. namespace 聊天机器人
  14. {
  15.     public partial class Form1 : MonoBehaviour
  16.     {
  17.         SpeechVoiceSpeakFlags SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
  18.         SpVoice Voice = new SpVoice();
  19.         public string usay;
  20.         public string jijisay = '';
  21.         HttpWebResponse Response = null;
  22.         public string ConnectTuLing(string p_strMessage)
  23.         {
  24.             string result = null;
  25.             try  {
  26.                 String APIKEY = 'c32ccaa805b6441be76bc18074f12e51';
  27.                 String _strMessage = p_strMessage;
  28.                 String INFO = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(_strMessage));
  29.                 String getURL = 'http://www./openapi/api?key=' + APIKEY + '&info=' + INFO;
  30.                 HttpWebRequest MyRequest = (HttpWebRequest)HttpWebRequest.Create(getURL);
  31.                 HttpWebResponse MyResponse = (HttpWebResponse)MyRequest.GetResponse();
  32.                 Response = MyResponse;
  33.                 using (Stream MyStream = MyResponse.GetResponseStream())
  34.                 {
  35.                     long ProgMaximum = MyResponse.ContentLength;
  36.                     long totalDownloadedByte = 0;
  37.                     byte[] by = new byte[1024];
  38.                     int osize = MyStream.Read(by, 0, by.Length);
  39.                     Encoding encoding = Encoding.UTF8;
  40.                     while (osize > 0)                    {
  41.                         totalDownloadedByte = osize + totalDownloadedByte;
  42.                         result += encoding.GetString(by, 0, osize);
  43.                         long ProgValue = totalDownloadedByte;
  44.                         osize = MyStream.Read(by, 0, by.Length);                    }                }
  45.                 JsonReader reader = new JsonTextReader(new StringReader(result));
  46.                 while (reader.Read())                {
  47.                     if (reader.Path == 'text')                    {
  48.                         result = reader.Value.ToString();
  49.                         Debug.Log(reader.Value);
  50.                         jijisay = reader.Value.ToString();                    }                }            }
  51.             catch (Exception)            {                throw;            }
  52.             return result;        }
  53.         private void btn_send_Click()        {
  54.             string returnMess = ConnectTuLing(usay);
  55.             try             {
  56.                 SpeechVoiceSpeakFlags SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
  57.                 SpVoice Voice = new SpVoice();
  58.                 if (chkSaveToWavFile.Checked)                {
  59.                     SaveFileDialog sfd = new SaveFileDialog();
  60.                     sfd.Filter = 'All files (*.*)|*.*|wav files (*.wav)|*.wav';
  61.                     sfd.Title = 'Save to a wave file';
  62.                     sfd.FilterIndex = 2;
  63.                     sfd.RestoreDirectory = true;
  64.                     if (sfd.ShowDialog()== DialogResult.OK)                     {
  65.                         SpeechStreamFileMode SpFileMode = SpeechStreamFileMode.SSFMCreateForWrite;
  66.                         SpFileStream SpFileStream = new SpFileStream();
  67.                         SpFileStream.Open(sfd.FileName, SpFileMode, false);
  68.                         Voice.AudioOutputStream = SpFileStream;
  69.                         Voice.Speak(txtSpeakText.Text, SpFlags);
  70.                         Voice.WaitUntilDone(5);
  71.                         SpFileStream.Close();                    }                }
  72.                 else                {                    Voice.Speak(txtSpeakText.Text, SpFlags);                }            }            
  73. catch(Exception error) { MessageBox.Show('Speak error''SimpleTTS', MessageBoxButtons.OK, MessageBoxIcon.Error);    }    }
  74.               void OnGUI(){            if (GUI.Button (new Rect (1001008050), '点击'))
  75.                 btn_send_Click ();
  76.             usay = GUI.TextArea (new Rect (05035050), usay);
  77.             GUI.TextField (new Rect (020035050), jijisay);        }
  78.     }
  79. }

4.也试过很多ACG的自动回复机器人。像伪春菜,白丝魔理沙。但仔细玩就会发现这些与上面的不同,他们没有强大的数据库,也没有自然语言分析和模糊分析处理,只是对应内容进行回复,只有学习功能,需要玩家自己调教,显得非常的不智能。

语音与文字相互转换

想可以和AI聊天,AI可以说话

1.微软Speech.DLL 下的 TTS 和 STT引擎

Text-to-speech一般分为两个步骤:
1) 文本处理。
这一步做的事情是把文本转化成音素序列,并标出每个音素的起止时间、频率变化等信息。
作为一个预处理步骤,它的重要性经常被忽视,但是它涉及到很多值得研究的问题,比如拼写相同但读音不同的词的区分、缩写的处理、停顿位置的确定,等等。
2) 语音合成。
狭义上这一步专指根据音素序列(以及标注好的起止时间、频率变化等信息)生成语音,广义上它也可以包括文本处理的步骤。
这一步主要有三类方法:
a) 拼接法,即从事先录制的大量语音中,选择所需的基本单位拼接而成。这样的单位可以是音节、音素等等;为了追求合成语音的连贯性,也常常用使用双音子(从一个音素的中央到下一个音素的中央)作为单位。拼接法合成的语音质量较高,但它需要录制大量语音以保证覆盖率。
b) 参数法,即根据统计模型来产生每时每刻的语音参数(包括基频、共振峰频率等),然后把这些参数转化为波形。参数法也需要事先录制语音进行训练,但它并不需要100%的覆盖率。参数法合成出的语音质量比拼接法差一些。
c) 声道模拟法。参数法利用的参数是语音信号的性质,它并不关注语音的产生过程。与此相反,声道模拟法则是建立声道的物理模型,通过这个物理模型产生波形。这种方法的理论看起来很优美,但由于语音的产生过程实在是太复杂,所以实用价值并不高。

测试代码

  1. using UnityEngine;
  2. using System.Collections;
  3. using SpeechLib;
  4. public class WinSpeech : MonoBehaviour {    
  5.     SpeechVoiceSpeakFlags SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
  6.     SpVoice Voice = new SpVoice();
  7.     void OnGUI(){
  8.         if(GUI.Button(new Rect(200,5,80,50),'Speech'))        {
  9.             Voice.Speak('你好', SpFlags);
  10.         }
  11.     }
  12. }

2.飞讯SDK

3.Kinect
(含Kinect的语音识别功能) 之后转换成信息(错误率可能很高)
再转给小黄鸡...
识别语音之后3D模型要做的事情
[Kinect speech的使用]
Kinect v2 SDK包
额外下载 == Microsoft speech SDK + MSKinectLangPack_enUS.msi.

窗口制作

1.unity shader
使用传统的CustomChromakey方法 + 窗口化和置顶(DLL)
相当于抠色的功能的,取像素点颜色,判断颜色是否在阀值内,进行除去

  1. Shader 'Custom/ChromakeyTransparent' {
  2. Properties {
  3. _MainTex ('Base (RGB)', 2D) = 'white' {}
  4. _TransparentColourKey ('Transparent Colour Key', Color) = (0,0,0,1)
  5. _TransparencyTolerance ('Transparency Tolerance', Float) = 0.01
  6. }
  7. SubShader {
  8. Pass {
  9. Tags { 'RenderType' = 'Opaque' }
  10. LOD 200
  11. CGPROGRAM
  12. #pragma vertex vert
  13. #pragma fragment frag
  14. #include 'UnityCG.cginc'
  15. struct a2v
  16. {
  17. float4 pos : POSITION;
  18. float2 uv : TEXCOORD0;
  19. };
  20. struct v2f
  21. {
  22. float4 pos : SV_POSITION;
  23. float2 uv : TEXCOORD0;
  24. };
  25. v2f vert(a2v input)
  26. {
  27. v2f output;
  28. output.pos = mul (UNITY_MATRIX_MVP, input.pos);
  29. output.uv = input.uv;
  30. return output;
  31. }
  32. sampler2D _MainTex;
  33. float3 _TransparentColourKey;
  34. float _TransparencyTolerance;
  35. float4 frag(v2f input) : SV_Target
  36. {
  37. // What is the colour that *would* be rendered here?
  38. float4 colour = tex2D(_MainTex, input.uv);
  39. // Calculate the different in each component from the chosen transparency colour
  40. float deltaR = abs(colour.r - _TransparentColourKey.r);
  41. float deltaG = abs(colour.g - _TransparentColourKey.g);
  42. float deltaB = abs(colour.b - _TransparentColourKey.b);
  43. // If colour is within tolerance, write a transparent pixel
  44. if (deltaR < _TransparencyTolerance && deltaG < _TransparencyTolerance && deltaB < _TransparencyTolerance)
  45. {
  46. return float4(0.0f, 0.0f, 0.0f, 0.0f);
  47. }
  48. // Otherwise, return the regular colour
  49. return colour;
  50. }
  51. ENDCG
  52. }
  53. }
  54. }

2.vs窗口设置

3.代码设置

UpdateLayeredWindow可以设置使得窗口透明 UpdateLayeredWindow_百度百科

关键代码:

  1. Win32.BLENDFUNCTION blendFunc = new Win32.BLENDFUNCTION();
  2. blendFunc.AlphaFormat = Win32.AC_SRC_ALPHA;
  3. Win32.UpdateLayeredWindow(..blendFunc..);

 跳舞鼓励功能 

我希望每当我敲打键盘的时候 桌面精灵能根据我敲键盘速度 模型会进行跳舞。

1.代码控制动画

  1. public Image PowerFilled;
  2.     void Start () {        Slow ();    }
  3.     void OnGUI() {
  4.         Event e = Event.current;
  5.         if (e.isKey) {
  6.             if(Time.timeScale < 1)
  7.                 Time.timeScale = Time.timeScale + 0.05F;
  8.             GUI.Box (new Rect (5508050),e.keyCode.ToString ());
  9.         }
  10.         GUI.Box (new Rect (558050), Time.timeScale.ToString ());        
  11.     }
  12.     void Slow (){
  13.         if(Time.timeScale > 0.05)
  14.         {
  15.         Time.timeScale = Time.timeScale - 0.02F;
  16.             PowerFilled.fillAmount = (float)(Time.timeScale/1F);
  17.         Invoke ('Slow'0.1F);
  18.         }
  19.     } 


当我离开键盘,跳舞速度便慢慢地下降下来~但我发现 当我切换到别的应用程序之后 桌面精灵程序便不会继续监听我的键盘输入,失去了桌面精灵的意义。所以写了个Hook

2.HOOK使用:全局键盘钩子

如是我便使用了全局键盘钩子HOOK.
但这个只能在unity里使用 而不能发布exe
因为我写的这个功能 360告诉我是病毒 。。严重警告然后删了
我写之前都没意识到这件事。。
我是打算写一个桌面精灵而已
然后只要我不断打代码 她就会开始跳舞 当我afk的时候她就慢慢停下来
我觉得很好玩。。实现起来的过程很难 花了我很多时间去写。。
终于写了出来。。结果被360删了。。。
之后我意识到,我这个程序,因为是桌面精灵 所以一直处于后台运行状态
不单后台运行 它还监听了我的键盘输入
细思极恐。。
这就是盗窃密码的病毒啊
后台运行,任务栏不显示,进程的名字改了,还监听键盘。。我都做到了,虽然她是个桌面精灵。。。。。。
实际上这是我的毕设

so,以后可能会有程序猿说发个游戏或者应用给你们测试一下,其实他可能给你发了一个键盘监听程序。
键盘监听在unity里始终不太好用。因为种种原因
种种原因就不解释了 太长。因为系统防御还算是有的。

---------end---------

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多