using Aliyun.Acs.Core; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Profile; using CRM.Core.BLL.Voice; using CRM.Core.DTO.Api; using CRM.Core.Model.Entity; using CRM.Core.Model.Enum; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Runtime.Remoting; using System.Text; using System.Threading.Tasks; using System.Web.Http; using WX.CRM.Common; namespace Core.VoiceApi.Controllers { public class VoiceController : ApiController { ValidationErrors errors = new ValidationErrors(); public Voice_BL voicebl = new Voice_BL(); /// /// 回调地址 /// /// 语音地址 /// 返回地址 /// 编码 /// /// 1、当returnUrl为空,则不做另外的回调操作 /// 2、当此调录音已经被翻译过,则此处直接返回翻译内容,并且在此接口直接回调 returnUrl /// 3、如果是新的录音,则返回参数成功,后续返回的时候调用回调 /// 4、多个请求了相同的录音,将被记录到多条需要回调的地址,等到数据被返回,都会一一去重后调用回调地址 /// /// /// [Route("Voice/Push")] [HttpGet] public ApiResult Push(string voiceUrl = null, string returnUrl = null, string voice_code = "VoiceAnalysis") { if (string.IsNullOrEmpty(voiceUrl)) { return new ApiResult() { result = false, retcode = (int)EnumInterfaceErrcode.参数错误, retmsg = "参数错误" }; } voiceUrl = voiceUrl.Trim(); string urlmd5 = Utility.EncryptMD5(voiceUrl); Voice_Aliyun_Return record = voicebl.GetRecord(urlmd5);//第一步 是否能找到成功的解析值 int id = 0; if (record == null)//如果是一个完全新的数据,则需要进行,插入一条 { bool result = voicebl.InsertReceive(new Voice_Receive { file_link = voiceUrl, file_md5 = urlmd5, isAready = 0, retrun_link = returnUrl }, ref errors, ref id);//插入接收表 if (result) { //执行调用阿里云接口。 Task task1 = new Task(() => PushVoiceToAliyun(urlmd5, voiceUrl, voice_code));//异步调用任务 task1.Start(); LogHelper.Info("我先走拉main:"+ voiceUrl); } else { return new ApiResult() { result = false, retcode = (int)EnumInterfaceErrcode.调用成功但有错误, retmsg = "Voice_Receive入库出现错误!" }; } } else { bool result = voicebl.InsertReceive(new Voice_Receive { file_link = voiceUrl, file_md5 = urlmd5, isAready = 1, retrun_link = returnUrl }, ref errors, ref id);//插入接收表 voicebl.InsertLog(new Voice_ReceiveHis() { ctime = DateTime.Now, file_link = voiceUrl, file_md5 = urlmd5, id = id, isAready = 1, retrun_link = returnUrl, transtime = DateTime.Now });//插入日志 //CallBackClientRequest(urlmd5, new AliyunApiResult()//调用callback //{ // BizDuration = record.BizDuration, // StatusCode = record.StatusCode, // StatusText = record.StatusText, // voicetext = record.voicetext //}); return new ApiResult() { result = true, retcode = (int)EnumInterfaceErrcode.调用成功且有数据, retmsg = "SUCCESS", retData = new AliyunApiResult() { BizDuration = record.BizDuration, StatusCode = record.StatusCode, StatusText = record.StatusText, voicetext = record.voicetext } };//返回成功数据 } return new ApiResult() { result = true, retcode = (int)EnumInterfaceErrcode.调用成功, retmsg = "请求已受理" }; } #region 阿里云语音识别接口调用 // 地域ID,固定值。 public const string REGIONID = "cn-shanghai"; public const string PRODUCT = "nls-filetrans"; public const string DOMAIN = "filetrans.cn-shanghai.aliyuncs.com"; public const string API_VERSION = "2018-08-17"; public const string POST_REQUEST_ACTION = "SubmitTask"; public const string GET_REQUEST_ACTION = "GetTaskResult"; // 请求参数 public const string KEY_APP_KEY = "appkey"; public const string KEY_FILE_LINK = "file_link"; public const string KEY_VERSION = "version"; public const string KEY_ENABLE_WORDS = "enable_words"; // 响应参数 public const string KEY_TASK = "Task"; public const string KEY_TASK_ID = "TaskId"; public const string KEY_STATUS_TEXT = "StatusText"; // 状态值 public const string STATUS_SUCCESS = "SUCCESS"; public const string STATUS_RUNNING = "RUNNING"; public const string STATUS_QUEUEING = "QUEUEING"; public const string STATUS_CODE = "StatusCode"; //public static string accessKeyId = Utility.GetSettingByKey("Aliyun_accessKeyId"); //public static string accessKeySecret = Utility.GetSettingByKey("Aliyun_accessKeySecret"); //public static string appKey = Utility.GetSettingByKey("Aliyun_appKey"); public static string folder = Utility.GetSettingByKey("Aliyun_downloadPath"); public static string Aliyun_interface_Url = Utility.GetSettingByKey("Aliyun_interface_Url"); public static string callback_url = Utility.GetSettingByKey("Aliyun_callback_url"); private void PushVoiceToAliyun(string urlmd5, string voiceUrl, string voice_code) { if (!voicebl.IsNeedAddNewRequest(urlmd5)) return; LogHelper.Info("执行下载2:"+ voiceUrl); //string fileLink = voiceUrl; List configlit = voicebl.GetConfigList(); var voiceconfig = configlit.FirstOrDefault(m => m.voice_code == voice_code); if (voiceconfig == null) { voiceconfig = configlit.FirstOrDefault(m => m.voice_code == "VoiceAnalysis");//找不到用默认的 if (voiceconfig == null)//找不配置数据 { return; } } string filename = ""; if (!HttpDownloadFile(voiceUrl, ref filename)) { return;//下载失败 } string new_voiceUrl = Aliyun_interface_Url + filename; /** * 创建阿里云鉴权对象 */ IClientProfile profile = DefaultProfile.GetProfile( REGIONID, voiceconfig.accessKeyId, voiceconfig.accessKeySecret ); DefaultAcsClient client = new DefaultAcsClient(profile); Voice_Aliyun_Request record = new Voice_Aliyun_Request() { ctime = DateTime.Now, file_link = voiceUrl, file_md5 = urlmd5, StatusCode = 0, filename = filename }; try { /** * 创建录音文件识别请求,设置请求参数。 */ CommonRequest request = new CommonRequest(); request.Domain = DOMAIN; request.Version = API_VERSION; request.Action = POST_REQUEST_ACTION; request.Product = PRODUCT; request.Method = MethodType.POST; // 设置task,以JSON字符串形式设置到请求Body中。 JObject obj = new JObject(); obj[KEY_APP_KEY] = voiceconfig.Appkey; obj[KEY_FILE_LINK] = new_voiceUrl; // 新接入请使用4.0版本,已接入(默认2.0)如需维持现状,请注释掉该参数设置。 obj[KEY_VERSION] = "4.0"; // 设置是否输出词信息,默认为false。开启时需要设置version为4.0。 obj[KEY_ENABLE_WORDS] = false; obj["enable_callback"] = true;//开启回调 obj["callback_url"] = callback_url;//调用中心点的回调接口 obj["enable_sample_rate_adaptive"] = true; obj["enable_disfluency"] = true; string task = obj.ToString(); request.AddBodyParameters(KEY_TASK, task); /** * 提交录音文件识别请求,处理服务端返回的响应。 */ CommonResponse response = client.GetCommonResponse(request); System.Console.WriteLine(response.Data); record.HttpStatus = response.HttpStatus;//===========请求状态赋值 if (response.HttpStatus != 200) { System.Console.WriteLine("录音文件识别请求失败: " + response.HttpStatus); return; } // 获取录音文件识别请求任务ID,以供识别结果查询使用。 string taskId = ""; JObject jsonObj = JObject.Parse(response.Data); string statusText = jsonObj[KEY_STATUS_TEXT].ToString(); record.HttpStatusTxt = statusText;//===========请求状态描述赋值 record.StatusCode = Convert.ToInt32(jsonObj[STATUS_CODE]);//======获取状态码 if (statusText.Equals(STATUS_SUCCESS)) { //System.Console.WriteLine("录音文件识别请求成功响应!"); //LogHelper.Info("录音文件识别请求成功响应!"); taskId = jsonObj[KEY_TASK_ID].ToString(); record.TaskId = taskId;//===========任务ID赋值 } else { //System.Console.WriteLine("录音文件识别请求失败!"); LogHelper.Info("录音文件识别请求失败!json:"+ response.Data); return; } } catch (Aliyun.Acs.Core.Exceptions.ServerException ex) { //System.Console.WriteLine(ex.ToString()); LogHelper.Error(ex.ToString()); } catch (ClientException ex) { //System.Console.WriteLine(ex.ToString()); LogHelper.Error(ex.ToString()); } finally { voicebl.RequestInsert(record, ref errors);//=======最后入库record数据 LogHelper.Info("执行完毕:"+ voiceUrl); } } #endregion /// /// http下载voice文件,用于翻译 /// /// /// /// private static bool HttpDownloadFile(string url, ref string filename) { bool result = true; try { int xieganlenth = url.LastIndexOf("."); if (xieganlenth < 0) { return false; } string exit = Path.GetExtension(url); //LogHelper.Error("exit:" + exit); if (exit.Length > 5) { exit = exit.Substring(0, exit.IndexOf("&")); } Random rd = new Random(10000); int i = rd.Next(); filename = DateTime.Now.ToString("yyyyMMddHHmmssffff") + i + exit;//时间加上随机数 string path = Path.Combine(folder, filename);//地址 //LogHelper.Error(path); //LogHelper.Error(url); // 设置参数 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; //发送请求并获取相应回应数据 HttpWebResponse response = request.GetResponse() as HttpWebResponse; //直到request.GetResponse()程序才开始向目标网页发送Post请求 Stream responseStream = response.GetResponseStream(); //创建本地文件写入流 Stream stream = new FileStream(path, FileMode.Create); byte[] bArr = new byte[1024]; int size = responseStream.Read(bArr, 0, (int)bArr.Length); while (size > 0) { stream.Write(bArr, 0, size); size = responseStream.Read(bArr, 0, (int)bArr.Length); } stream.Close(); responseStream.Close(); result = true; } catch (Exception e) { LogHelper.Error(e.ToString()); result = false; } return result; } private static void RomveFile(string filename) { try { if (string.IsNullOrEmpty(filename)) return; string path = Path.Combine(folder, filename);//地址 if (File.Exists(path)) { File.Delete(path);//删除文件 } } catch (Exception e) { LogHelper.Error(e.ToString()); } } /// /// 阿里云语音识别回调接口 /// /// /// [Route("Voice/callback")] [HttpPost] public ApiResult callback([FromBody] dynamic info) { try { int[] succedcodes = { 21050003, 21050000 };//21050000 SUCCESS 成功 ,21050003//识别结果查询接口调用成功,但是没有识别到语音 string json = Newtonsoft.Json.JsonConvert.SerializeObject(info); //LogHelper.Info(json); int StatusCode = info.StatusCode;//状态码 string taskid = info.TaskId;//任务ID Voice_Aliyun_Request request = voicebl.GetRequest(taskid); if (request == null) { LogHelper.Info("can't find task:" + json); return new ApiResult() { result = true, retcode = (int)EnumInterfaceErrcode.调用成功, retmsg = "SUCCESS" }; } if (succedcodes.Contains(StatusCode))//在成功的范畴中 { long requesttime = info.RequestTime; long SolveTime = info.SolveTime; DateTime requestTimeT = DateTimeTool.GetTimeFromLinuxTimeDiscern(requesttime); DateTime solveTimeT = DateTimeTool.GetTimeFromLinuxTimeDiscern(SolveTime); string voicetext = ""; if (info.Result != null && info.Result.Sentences != null) { foreach (var item in info.Result.Sentences) { voicetext += item.Text; } } Voice_Aliyun_Return ren = new Voice_Aliyun_Return() { file_md5 = request.file_md5, BizDuration = info.BizDuration, ctime = DateTime.Now, file_link = request.file_link, RequestTime = requestTimeT, Sentences = Newtonsoft.Json.JsonConvert.SerializeObject(info.Result.Sentences),//解析后返回的内容 voicetext = voicetext,//讲内容提取出来文本来 SolveTime = solveTimeT, StatusCode = info.StatusCode, StatusText = info.StatusText, TaskId = info.TaskId }; voicebl.RetrunSuccedInsert(ren); AliyunApiResult aliyunApiResult = new AliyunApiResult() { BizDuration = info.BizDuration, StatusCode = StatusCode, StatusText = info.StatusText, voicetext = voicetext }; CallBackClientRequest(request.file_md5, aliyunApiResult);//回调给各个客户端 } else { long SolveTime = info.SolveTime; DateTime solveTimeT = DateTimeTool.GetTimeFromLinuxTimeDiscern(SolveTime); Voice_Aliyun_Return_Erro ren = new Voice_Aliyun_Return_Erro() { file_md5 = request.file_md5, BizDuration = info.BizDuration, ctime = DateTime.Now, file_link = request.file_link, RequestTime = request.ctime, SolveTime = solveTimeT, StatusCode = info.StatusCode, StatusText = info.StatusText, TaskId = info.TaskId }; voicebl.RetrunErroInsert(ren);//插入失败信息 AliyunApiResult aliyunApiResult = new AliyunApiResult() { BizDuration = info.BizDuration, StatusCode = StatusCode, StatusText = info.StatusText, voicetext = "" }; CallBackClientRequest(request.file_md5, aliyunApiResult);//回调给各个客户端 //Voice_Aliyun_Return_Erro } voicebl.ReturnRequest(request); RomveFile(request.filename); } catch (Exception e) { LogHelper.Error("callback_erro:" + e.ToString()); } return new ApiResult() { result = true, retcode = (int)EnumInterfaceErrcode.调用成功, retmsg = "SUCCESS" }; } /// /// 调用各大请求 /// private async Task CallBackClientRequest(string file_md5, AliyunApiResult aliyunApiResult) { try { List list = voicebl.GetReceive(file_md5); foreach (Voice_Receive item in list) { if (!string.IsNullOrEmpty(item.retrun_link)) { AliyunApiResult model = new AliyunApiResult() { id = item.id, voicetext = aliyunApiResult.voicetext, StatusText = aliyunApiResult.StatusText, BizDuration = aliyunApiResult.BizDuration, StatusCode = aliyunApiResult.StatusCode }; string errmsg = ""; try { string retmsg = Utility.PostAjaxData(item.retrun_link, Newtonsoft.Json.JsonConvert.SerializeObject(model), Encoding.UTF8);//返回信息 } catch (Exception e) { errmsg = e.Message; } voicebl.InsertLog(new Voice_ReceiveHis() { ctime = item.ctime, file_link = item.file_link, file_md5 = item.file_md5, id = item.id, isAready = item.isAready, retrun_link = item.retrun_link, transtime = DateTime.Now, return_status = string.IsNullOrEmpty(errmsg) ? "SUCCESS" : errmsg }); } } } catch (Exception e) { LogHelper.Error("CallBackClientRequest:" + e.ToString()); } } } }