476 lines
20 KiB
C#
476 lines
20 KiB
C#
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();
|
||
/// <summary>
|
||
/// 回调地址
|
||
/// </summary>
|
||
/// <param name="voiceUrl">语音地址</param>
|
||
/// <param name="returnUrl">返回地址</param>
|
||
/// <param name="voice_code">编码</param>
|
||
/// <remarks>
|
||
/// 1、当returnUrl为空,则不做另外的回调操作
|
||
/// 2、当此调录音已经被翻译过,则此处直接返回翻译内容,并且在此接口直接回调 returnUrl
|
||
/// 3、如果是新的录音,则返回参数成功,后续返回的时候调用回调
|
||
/// 4、多个请求了相同的录音,将被记录到多条需要回调的地址,等到数据被返回,都会一一去重后调用回调地址
|
||
///
|
||
/// </remarks>
|
||
/// <returns></returns>
|
||
[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<Voice_Config> 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
|
||
/// <summary>
|
||
/// http下载voice文件,用于翻译
|
||
/// </summary>
|
||
/// <param name="url"></param>
|
||
/// <param name="filename"></param>
|
||
/// <returns></returns>
|
||
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());
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 阿里云语音识别回调接口
|
||
/// </summary>
|
||
/// <param name="info"></param>
|
||
/// <returns></returns>
|
||
[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" };
|
||
}
|
||
/// <summary>
|
||
/// 调用各大请求
|
||
/// </summary>
|
||
private async Task CallBackClientRequest(string file_md5, AliyunApiResult aliyunApiResult)
|
||
{
|
||
try
|
||
{
|
||
List<Voice_Receive> 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());
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
}
|