加盟型网站建设,wordpress建设购物网站,网页设计与网站开发的区别,室内效果图用什么软件做最好websocker插件使用的unitywebsocker
讯飞webapi#xff0c;连接后只能请求一次#xff0c;所以每次使用时进行连接#xff0c;连接成功后进行请求#xff0c;请求完成后关闭连接。 为什么连接后只能请求一次呢#xff0c;可能是方便统计使用量。
如何通过音频数据计算出…websocker插件使用的unitywebsocker
讯飞webapi连接后只能请求一次所以每次使用时进行连接连接成功后进行请求请求完成后关闭连接。 为什么连接后只能请求一次呢可能是方便统计使用量。
如何通过音频数据计算出时间呢我这里通过 音频byte长度 / 采样率(16000) / 2 然后向上取整。
XunFeiAPIWebSocket .cs
using System;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
using UnityWebSocket;
using LitJson;
using System.Collections;[RequireComponent(typeof(AudioSource))]
public class XunFeiAPIWebSocket : MYTOOL.MonoSingletonXunFeiAPIWebSocket
{[SerializeField] string url wss://tts-api.xfyun.cn/v2/tts;[Space, SerializeField] string APPID ; //你自己的APPID[SerializeField] string APISecret ;[SerializeField] string APIKey ;WebSocket webSocket;string signature_origin ; //原始签名string signature_sha ; //使用hmac-sha256算法加密后的signaturestring signature; //最终编码后的签名string authorization_origin; //原始鉴权string authorization; //最终编码后的鉴权private readonly Queuefloat audionQue new Queuefloat(); //转后的语音队列private int audioLength; //语音长度AudioSource audioSource;private readonly QueueXunFeiData sendQue new QueueXunFeiData();//统计private int total_data_audio_length 0;private void Start(){OnStart();}private void OnDestroy(){if (webSocket ! null webSocket.ReadyState ! WebSocketState.Closed){webSocket.CloseAsync();}}void OnStart(){audioLength 0;audionQue.Clear();if (audioSource null){audioSource gameObject.GetComponentAudioSource();}webSocket new WebSocket(GetUrl(url));webSocket.OnOpen Socket_OnOpen;webSocket.OnMessage Socket_OnMessage;webSocket.OnError Socket_OnError;webSocket.OnClose Socket_OnClose;//Connect();}private void Connect(){if (webSocket.ReadyState ! WebSocketState.Open){webSocket.ConnectAsync();}}#region websocker回调private void Socket_OnOpen(object sender, OpenEventArgs e){Send();//Debug.Log(讯飞WebSocket连接成功);}private void Socket_OnMessage(object sender, MessageEventArgs e){if (e.IsText){JsonData js JsonMapper.ToObject(e.Data);if (js[message].ToString() success){if (js[data] ! null){if (js[data][audio] ! null){string data_audio js[data][audio].ToString();byte[] byte_data_audio Convert.FromBase64String(data_audio);float[] fs bytesToFloat(byte_data_audio);audioLength fs.Length;total_data_audio_length byte_data_audio.Length;foreach (float f in fs){audionQue.Enqueue(f);}if ((int)js[data][status] 2) //2为结束标志符{webSocket.CloseAsync();//关闭float audioLengthInSeconds total_data_audio_length / 16000f / 2;int audioLengthInSecondsCeiling (int)Math.Ceiling(audioLengthInSeconds);audioSource.clip AudioClip.Create(MySinusoid, 16000 * audioLengthInSecondsCeiling, 1, 16000, true, OnAudioRead); //要生成的音频名称、样本帧数(乘以60代表采样时长为1分钟)、每帧的声道数、剪辑采样频率、音频是否以流格式传输、调用该回调以生成样本数据块AudioClip cp audioSource.clip;audioSource.Play();Debug.Log($结束处理音频数据 {js[data][status]} {js[sid]} {total_data_audio_length} {audioLengthInSeconds} {audioLengthInSecondsCeiling});total_data_audio_length 0;}}}}}else if (e.IsBinary){}}private void Socket_OnClose(object sender, CloseEventArgs e){Debug.Log($讯飞WebSocket连接关闭{e.StatusCode}, {e.Reason});}private void Socket_OnError(object sender, ErrorEventArgs e){Debug.Log($错误信息 {e.Message});}#endregion/// summary/// 采样回调/// /summary/// param namedata/paramvoid OnAudioRead(float[] data) //经测试它应该是运行在子线程中的。 测试方法打印某个组件的值出现报错信息只能在主线程进行访问{for (int i 0; i data.Length; i){if (audionQue.Count 0)data[i] audionQue.Dequeue();else{if (webSocket null || webSocket.ReadyState ! WebSocketState.Open)audioLength;data[i] 0;}}}#region 组装生成鉴权private string GetUrl(string url){Uri uri new Uri(url);string date DateTime.Now.ToString(r); //官方文档要求时间必须是UTC0或GMT时区RFC1123格式(Thu, 01 Aug 2019 01:53:21 GMT)。ComposeAuthUrl(uri, date);string uriStr string.Format({0}?authorization{1}date{2}host{3}, uri, authorization, date, uri.Host); //生成最终鉴权return uriStr;}/// summary/// 组装生成鉴权/// /summaryprivate void ComposeAuthUrl(Uri uri, string date){signature_origin string.Format(host: uri.Host \ndate: date \nGET uri.AbsolutePath HTTP/1.1);signature_sha HmacSHA256(signature_origin, APISecret); //使用hmac - sha256算法结合apiSecret对signature_origin签名signature signature_sha;string auth api_key\{0}\, algorithm\{1}\, headers\{2}\, signature\{3}\;authorization_origin string.Format(auth, APIKey, hmac-sha256, host date request-line, signature); //参数介绍APIKey,加密算法名headers是参与签名的参数(该参数名是固定的host date request-line)生成的签名authorization ToBase64String(authorization_origin);}#endregion/// summary/// WebSocket Send/// /summary/// param nametext文本内容/param/// param namevcn发音人/parampublic void Send(string text, string vcn xiaoyan){if (string.IsNullOrWhiteSpace(text)){//空白不处理return;}XunFeiData data new XunFeiData(text, vcn);sendQue.Clear();sendQue.Enqueue(data);StopAudioPlay();if (webSocket.ReadyState WebSocketState.Open){Send();}else{//重新连接,连接成功后会执行Send方法Connect();}}public void StopAudioPlay(){audionQue.Clear();audioLength 0;if (AudioSourceCoroutine ! null){StopCoroutine(AudioSourceCoroutine);}if (audioSource ! null audioSource.isPlaying){audioSource.Stop();}}private void Send(){if (sendQue.Count 0){XunFeiData data sendQue.Dequeue();JsonData jsonData CreateJsonData(data.text, data.vcn);string json JsonMapper.ToJson(jsonData);webSocket.SendAsync(json);}}/// summary/// 按照官方API组装传输参数/// /summary/// returns/returnsprivate JsonData CreateJsonData(string text, string vcn){JsonData requestObj new JsonData();requestObj[common] new JsonData();JsonData commonJson new JsonData();commonJson[app_id] APPID;requestObj[common] commonJson;requestObj[business] new JsonData();JsonData bussinessJson new JsonData();bussinessJson[aue] raw; //raw未压缩的pcmbussinessJson[vcn] vcn; //发音人bussinessJson[speed] 80; //语速bussinessJson[pitch] 50; //音高bussinessJson[tte] UTF8;requestObj[business] bussinessJson;requestObj[data] new JsonData();JsonData dataJson new JsonData();dataJson[status] 2; //数据状态固定为2dataJson[text] ToBase64String(text); //文本内容需进行base64编码。base64编码前最大长度需小于8000字节约2000汉字requestObj[data] dataJson;return requestObj;}//加密算法HmacSHA256 private static string HmacSHA256(string secret, string signKey){string signRet string.Empty;using (HMACSHA256 mac new HMACSHA256(Encoding.UTF8.GetBytes(signKey))){byte[] hash mac.ComputeHash(Encoding.UTF8.GetBytes(secret));signRet Convert.ToBase64String(hash);}return signRet;}//byte[]转16进制格式stringpublic static string ToHexString(byte[] bytes){string hexString string.Empty;if (bytes ! null){StringBuilder strB new StringBuilder();foreach (byte b in bytes){strB.AppendFormat({0:x2}, b);}hexString strB.ToString();}return hexString;}///编码public static string EncodeBase64(string code_type, string code){string encode ;byte[] bytes Encoding.GetEncoding(code_type).GetBytes(code);try{encode Convert.ToBase64String(bytes);}catch{encode code;}return encode;}public static string ToBase64String(string value){if (value null || value ){return ;}byte[] bytes Encoding.UTF8.GetBytes(value);return Convert.ToBase64String(bytes);}/// summary/// byte[]数组转化为AudioClip可读取的float[]类型/// /summary/// param namebyteArray/param/// returns/returnspublic static float[] bytesToFloat(byte[] byteArray){float[] sounddata new float[byteArray.Length / 2];for (int i 0; i sounddata.Length; i){sounddata[i] bytesToFloat(byteArray[i * 2], byteArray[i * 2 1]);}return sounddata;}private static float bytesToFloat(byte firstByte, byte secondByte){// convert two bytes to one short (little endian)//小端和大端顺序要调整short s;if (BitConverter.IsLittleEndian)s (short)((secondByte 8) | firstByte);elses (short)((firstByte 8) | secondByte);// convert to range from -1 to (just below) 1return s / 32768.0F;}private class XunFeiData{public string text; //内容public string vcn; //发音人public XunFeiData(string text, string vcn){this.text text;this.vcn vcn;}}
}