第一步在管理端配置请求地址
wss://ise-api.xfyun.cn
第二步接口鉴权,生成url
由于在小程序端生成的url总是失败,就把url的生成放在了服务端。
@RequestMapping(value = "/getAuthUrl", method = RequestMethod.GET)
public @ResponseBody
Message getAuthUrl() throws Exception {
String hostUrl="wss://ise-api.xfyun.cn/v2/open-ise",
host="ise-api.xfyun.cn",
//在控制台-我的应用-语音评测(流式版)获取
appid= "************",
//在控制台-我的应用-语音评测(流式版)获取
apiSecret= "**************",//在控制台-我的应用-语音评测(流式版)获取
apiKey= "*************",
uri="/v2/open-ise";
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
StringBuilder builder = new StringBuilder("host: ").append(host).append("\n").//
append("date: ").append(date).append("\n").//
append("GET ").append(uri).append(" HTTP/1.1");
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");
mac.init(spec);
byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
String sha = Base64.getEncoder().encodeToString(hexDigits);
String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
StringBuffer httpUrl = new StringBuffer();
httpUrl.append(hostUrl).append("?")
.append("authorization=").append(Base64.getEncoder().encodeToString(authorization.getBytes(charset)))
.append("&date=").append(URLEncoder.encode(date,"UTF-8"))
.append("&host=").append(host);
return MessageUtil.createSuccessMessage(httpUrl.toString());
}
第三步 上传MP3文件
生成MP3文件
this.recorderManager = wx.getRecorderManager();
const options = {
duration: duration,
sampleRate: 16000,
numberOfChannels: 1,
encodeBitRate: 48000,
format: 'mp3',
};
this.recorderManager.start(options);
this.recorderManager.onStop(res => {
if (this.playAndRecordStatus == 'record') {
//生成的临时mp3文件
this.tempFile = res.tempFilePath;
//可以直接调用上传MP3的问题
new Promise(r=>{
this.$emit("record-finished",{text:this.segmentItem.eng,pcmFile:this.tempFile})
})
this.playRecord();
this.$apply();
}
});
创建socket并上传MP3文件
//上传MP3文件,pcmFile mp3文件的路径,text测评的文本
checkAudio(pcmFile, text) {
//把文本中的中文替换掉,如果有中文就会报错
text = text.replaceAll(/[\u4E00-\u9FA5]/g, '');
//获取服务端生成的url
Check.getAuthUrl(wssUrl => {
console.log(wssUrl);
//创建socket
this.socketTask = wx.connectSocket({
url: wssUrl,
complete: e => {
console.log(e);
}
});
this.socketTask.onError(e => {
console.log('==onError=');
console.log(e);
// this.readFile(pcmFile,0,1280,text)
});
this.socketTask.onOpen(e => {
//socket 打开后开始上传文件
const fs = wx.getFileSystemManager();
fs.getFileInfo({
filePath: pcmFile,
complete: e => {
this.readFileTime(fs, pcmFile, 0, 1280, text, e.size);
}
});
});
//处理socket返回的结果
this.socketTask.onMessage(e => {
var reslut = JSON.parse(e.data);
//code!=0 测评出现错误
if(reslut.code !=0){
console.log(reslut);
this.socketTask.close()
return;
}
if(reslut&&reslut.data&&reslut.data.status == '2'){
//测评完成,返回结果
this.socketTask.close()
const base64 = new Base64();
var d = base64.decode(reslut.data.data);
//处理返回的XML
this.loadXML(d);
}
});
});
}
readFileTime(fs, filePath, startIndex, length, text, lastTotal){
//设置定时器,每40毫秒上传一次
var intervalId = setInterval(()=>{
this.readFile(
fs,
filePath,
startIndex,
length,
text,
lastTotal
);
if(lastTotal<=length){
clearInterval(intervalId)
return;
}
startIndex = startIndex + length;
lastTotal = lastTotal - length;
},40)
}
读取文件并上传
readFile(fs, filePath, startIndex, length, text, lastTotal) {
var isLast = false;
if (length >= lastTotal) {
length = lastTotal;
isLast = true;
}
fs.readFile({
filePath: filePath,
position: startIndex,
length: length,
complete: e => {
},
success: e => {
var baseData = wx.arrayBufferToBase64(e.data);
if (!isLast) {
if (startIndex == 0) {
this.send(baseData, text, this.FRAME.STATUS_FIRST_FRAME);
} else {
if((lastTotal - length)==0){
this.send(baseData, text, this.FRAME.STATUS_LAST_FRAME);
return;
}else{
this.send(baseData, text, this.FRAME.STATUS_CONTINUE_FRAME);
}
}
} else {
this.send(baseData, text, this.FRAME.STATUS_LAST_FRAME);
}
}
});
// var data = fs.readFileSync(filePath,startIndex,length)
}
上传数据
// 上传数据
send(data, text, status) {
var frame = '';
switch (status) {
case this.FRAME.STATUS_FIRST_FRAME:
// 第一次数据发送:
frame = {
common: { app_id: this.config.appid },
business: {
// 服务类型指定 ise(开放评测)
sub: 'ise',
// 中文:cn_vip 英文:en_vip
ent: 'en_vip',
// 题型:句子朗读
category: 'read_sentence',
// 待评测文本编码 utf-8
text: '\uFEFF'+text,
check_type:"easy",
// 待评测文本编码 utf-8 gbk
tte: 'utf-8',
rstcd: 'utf8',
// 跳过ttp直接使用ssb中的文本进行评测(使用时结合cmd参数查看),默认值true
ttp_skip: true,
cmd: 'ssb',
aue: 'lame',
auf: 'audio/L16;rate=16000'
},
data: { status: 0 }
};
this.socketTask.send({
data: JSON.stringify(frame),
complete: e => {
}
});
// 后续数据发送
frame = {
common: { app_id: this.config.appid },
business: { aus: 1, cmd: 'auw', aue: 'lame' },
data: { status: 1, data: data }
};
break;
case this.FRAME.STATUS_CONTINUE_FRAME:
frame = {
common: { app_id: this.config.appid },
business: { aus: 2, cmd: 'auw', aue: 'lame' },
data: { status: 1, data: data }
};
break;
case this.FRAME.STATUS_LAST_FRAME:
frame = {
common: { app_id: this.config.appid },
business: { aus: 4, cmd: 'auw', aue: 'lame' },
data: { status: 2, data: data }
};
break;
}
//上传数据
this.socketTask.send({
data: JSON.stringify(frame),
complete: e => {
console.log(e);
}
});
}
解析xml
loadXML(xml) {
//把xml转成json
var x2js = new X2JS();
var json = x2js.xml2js(xml);
var chapter = json.xml_result.read_sentence.rec_paper.read_chapter;
var sentences = chapter.sentence;
var ttsScore = {};
ttsScore.totalScore = this.toIntScore(chapter._total_score)
var words = [];
if(sentences._total_score){
words = words.concat(this.getWordList(sentences))
}else{
for (var i = 0; i < sentences.length; i++) {
words = words.concat(this.getWordList(sentences[i]))
}
}
ttsScore.wordList = words;
//当前播放的文本拆成一个个的单词
var wordItemArr = this.currentPlaySegment.wordItemArr
var j = 0
//对比返回的单词,和原文本的单词,给原文本的单词设置评分
for(var i = 0 ; i < wordItemArr.length; i++){
var wordItem = wordItemArr[i]
if(j>=words.length){
break;
}
var wordScore = words[j]
var text = wordItem.text.toLowerCase().replaceAll(/[^a-zA-Z0-9_-]/g, '');
var word = wordScore.word.toLowerCase().replaceAll(/[^a-zA-Z0-9_-]/g, '');
if(text== word){
j++
}else{
continue
}
if(wordScore.score>95){
wordItemArr[i].score = 1;
}else if(wordScore.score>85){
wordItemArr[i].score = 2;
}else{
wordItemArr[i].score = 3;
}
}
this.currentPlaySegment.totalScore = ttsScore.totalScore
//给原文本的句子设置评分
for(var i = 0 ; i< this.segmentItems.length ; i++){
if(this.segmentItems[i].start == this.currentPlaySegment.start){
this.segmentItems[i].totalScore = ttsScore.totalScore
this.segmentItems[i].wordItemArr=wordItemArr
break;
}
}
this.$broadcast("show-score",this.currentPlaySegment)
this.$apply()
}
//给测评的结果乘20编程百分制
toIntScore(score){
return parseInt(parseFloat(score)*20)
}
网友评论