using System; using System.Collections; using System.IO; using System.Security.Cryptography; using System.Text; using UnityEngine; public class MicrophoneInputHuman : MonoBehaviour { public static MicrophoneInputHuman instance; public AudioSource audioSource; public int lengthSec = 60; private int frequency = 16000; private string savePath; private void Awake() { instance = this; savePath = Application.persistentDataPath + "/audios/micro.wav"; audioSource = GetComponent(); if (!Directory.Exists(Path.GetDirectoryName(savePath))) { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); } if (!File.Exists(savePath)) { File.Create(savePath); } } /// /// 开始录制 /// public void OnStartClick() { Debug.Log("OnStartClick"); if (!Application.HasUserAuthorization(UserAuthorization.Microphone)) { Debug.LogError("无录音权限,获取中,请重新说话"); MyDebugger.Log("无录音权限,获取中,请重新说话"); StartCoroutine(RequestMicrophoneAuth()); return; } StartRecord(); } /// /// 停止录制 /// public void OnStopClick(Action callback) { Debug.Log("OnStopClick"); int length = StopRecord(); if (length > 0) { byte[] file = WavUtility.FromAudioClip(audioSource.clip, savePath, true); IFlytekManager.instance.AudioToText(file, str => { callback(str); }); } else { MyDebugger.Log("没录音数据"); } } /// /// 播放录音 /// private void PlayAudio() { //读取本地文件播放 ReadAudioFile(savePath); } public IEnumerator RequestMicrophoneAuth() { yield return Application.RequestUserAuthorization(UserAuthorization.Microphone); } public void StartRecord() { if (Microphone.devices.Length > 0) { Debug.Log("开始录音"); audioSource.Stop(); audioSource.loop = false; audioSource.mute = true; audioSource.clip = Microphone.Start(null, false, lengthSec, frequency); MyDebugger.Log("录音中"); } else { Debug.Log("无麦克风"); MyDebugger.Log("无麦克风"); } } public int StopRecord() { int length = Microphone.GetPosition(null); Microphone.End(null); return length; } public bool SaveAudioFile(string filePath, int length) { if (Microphone.IsRecording(null)) return false; byte[] data = GetClipData(audioSource, length); if (data == null) { return false; } File.WriteAllBytes(filePath, data); string infoLog = "total length:" + data.Length + " time:" + audioSource.time + " path:" + filePath; Debug.Log(infoLog); return true; } public void ReadAudioFile(string filePath) { byte[] bytes = File.ReadAllBytes(filePath); float[] samples = byte2float(bytes); var clip = audioSource.clip; audioSource.Stop(); audioSource.clip = AudioClip.Create(clip.name, samples.Length, clip.channels, clip.frequency, false); audioSource.clip.SetData(samples, 0); audioSource.mute = false; audioSource.Play(); } byte[] GetClipData(AudioSource source, int length) { if (length < 10) { Debug.Log("录音文件太短"); return null; } float[] samples = new float[length]; source.clip.GetData(samples, 0); byte[] outData = float2byte(samples); return outData; } byte[] float2byte(float[] floats) { byte[] outData = new byte[floats.Length * 2]; int reScaleFactor = 32767; for (int i = 0; i < floats.Length; i++) { short tempShort = (short)(floats[i] * reScaleFactor); byte[] tempData = BitConverter.GetBytes(tempShort); outData[i * 2] = tempData[0]; outData[i * 2 + 1] = tempData[1]; } return outData; } float[] byte2float(byte[] bytes) { float reScaleFactor = 32768.0f; float[] data = new float[bytes.Length / 2]; for (int i = 0; i < bytes.Length; i += 2) { short s; if (BitConverter.IsLittleEndian) //小端和大端顺序要调整 s = (short)((bytes[i + 1] << 8) | bytes[i]); else s = (short)((bytes[i] << 8) | bytes[i + 1]); // convert to range from -1 to (just below) 1 data[i / 2] = s / reScaleFactor; } return data; } //private IEnumerator CallAudioToString(string fileName,long fileSize) //{ // string ts = GetTimeStampSecond().ToString(); // var a = new { duration = 200, fileName = fileName, fileSize = fileSize, signa = GetSigna(ts), ts = ts, appId = APPID }; // UnityWebRequest request = UnityWebRequest.Post("https://raasr.xfyun.cn/v2/api/upload", JsonConvert.SerializeObject(a)); // request.uploadHandler.contentType = "application/json"; // yield return request.SendWebRequest(); // if(!request.isNetworkError && !request.isHttpError) // { // Debug.Log(request.downloadHandler.text); // audioText.text = request.downloadHandler.text; // } // else // { // audioText.text = request.downloadHandler.error; // } //} //private string GetSigna(string ts) //{ // string md5str = MD5(APPID + ts); // string hmacStr= HMACSHA1Text(md5str, SecretKey); // return hmacStr; //} /// /// 获取时间戳-单位秒 /// /// private int GetTimeStampSecond() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt32(ts.TotalSeconds); } /// /// 字符串MD5加密 /// /// 要加密的字符串 /// 密文 private string MD5(string Text) { byte[] buffer = Encoding.UTF8.GetBytes(Text); System.Security.Cryptography.MD5CryptoServiceProvider check; check = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] somme = check.ComputeHash(buffer); string ret = ""; foreach (byte a in somme) { if (a < 16) ret += "0" + a.ToString("X"); else ret += a.ToString("X"); } return ret.ToLower(); } private string HMACSHA1Text(string text, string key) { //HMACSHA1加密 HMACSHA1 hmacsha1 = new HMACSHA1(); hmacsha1.Key = Encoding.UTF8.GetBytes(key); byte[] dataBuffer = Encoding.UTF8.GetBytes(text); byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); return Convert.ToBase64String(hashBytes); } }