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());
}
}
}
}