forked from go/golangs_learn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
8.8 KiB
268 lines
8.8 KiB
package aliyun
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
|
|
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
|
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
ALIYUN_CLOUND_REGION_CHA = 1 //中国
|
|
ALIYUN_CLOUND_REGION_INT = 2 //海外
|
|
)
|
|
|
|
//阿里云语音识别引擎
|
|
type AliyunClound struct {
|
|
AccessKeyId string
|
|
AccessKeySecret string
|
|
AppKey string
|
|
Region int
|
|
}
|
|
|
|
|
|
//阿里云录音文件识别结果集
|
|
type AliyunAudioRecognitionResult struct {
|
|
Text string //文本结果
|
|
TranslateText string //翻译文本结果
|
|
ChannelId int64 //音轨ID
|
|
BeginTime int64 //该句的起始时间偏移,单位为毫秒
|
|
EndTime int64 //该句的结束时间偏移,单位为毫秒
|
|
SilenceDuration int64 //本句与上一句之间的静音时长,单位为秒
|
|
SpeechRate int64 //本句的平均语速,单位为每分钟字数
|
|
EmotionValue int64 //情绪能量值1-10,值越高情绪越强烈
|
|
}
|
|
|
|
//阿里云识别词语数据集
|
|
type AliyunAudioWord struct {
|
|
Word string
|
|
ChannelId int64
|
|
BeginTime int64
|
|
EndTime int64
|
|
}
|
|
|
|
|
|
// 定义常量
|
|
const REGION_ID_REGION_INT string = "ap-southeast-1"
|
|
const ENDPOINT_NAME_REGION_INT string = "ap-southeast-1"
|
|
const PRODUCT_REGION_INT string = "nls-filetrans"
|
|
const DOMAIN_REGION_INT string = "filetrans.ap-southeast-1.aliyuncs.com"
|
|
const API_VERSION_REGION_INT string = "2019-08-23"
|
|
|
|
const REGION_ID_REGION_CHA string = "cn-shanghai"
|
|
const ENDPOINT_NAME_REGION_CHA string = "cn-shanghai"
|
|
const PRODUCT_REGION_CHA string = "nls-filetrans"
|
|
const DOMAIN_REGION_CHA string = "filetrans.cn-shanghai.aliyuncs.com"
|
|
const API_VERSION_REGION_CHA string = "2018-08-17"
|
|
|
|
|
|
const POST_REQUEST_ACTION string = "SubmitTask"
|
|
const GET_REQUEST_ACTION string = "GetTaskResult"
|
|
// 请求参数key
|
|
const KEY_APP_KEY string = "appkey"
|
|
const KEY_FILE_LINK string = "file_link"
|
|
const KEY_VERSION string = "version"
|
|
const KEY_ENABLE_WORDS string = "enable_words"
|
|
|
|
//是否打开ITN,中文数字将转为阿拉伯数字输出,默认值为false
|
|
const KEY_ENABLE_INVERSE_TEXT_NORMAL = "enable_inverse_text_normalization"
|
|
//是否启⽤语义断句,取值:true/false,默认值false
|
|
const KEY_ENABLE_SEMANTIC_SENTENCE_DETECTION = "enable_semantic_sentence_detection"
|
|
//是否启用时间戳校准功能,取值:true/false,默认值false
|
|
const KEY_ENABLE_TIMESTAMP_ALIGNMENT = "enable_timestamp_alignment"
|
|
|
|
// 响应参数key
|
|
const KEY_TASK string = "Task"
|
|
const KEY_TASK_ID string = "TaskId"
|
|
const KEY_STATUS_TEXT string = "StatusText"
|
|
const KEY_RESULT string = "Result"
|
|
// 状态值
|
|
const STATUS_SUCCESS string = "SUCCESS"
|
|
const STATUS_RUNNING string = "RUNNING"
|
|
const STATUS_QUEUEING string = "QUEUEING"
|
|
|
|
|
|
//发起录音文件识别
|
|
//接口文档 https://help.aliyun.com/document_detail/90727.html?spm=a2c4g.11186623.6.581.691af6ebYsUkd1
|
|
func (c AliyunClound) NewAudioFile(fileLink string) (string , *sdk.Client , error) {
|
|
regionId, domain, apiVersion, product := c.GetApiVariable()
|
|
|
|
client, err := sdk.NewClientWithAccessKey(regionId, c.AccessKeyId, c.AccessKeySecret)
|
|
if err != nil {
|
|
return "" , client , err
|
|
}
|
|
client.SetConnectTimeout(time.Second * 20)
|
|
|
|
postRequest := requests.NewCommonRequest()
|
|
postRequest.Domain = domain
|
|
postRequest.Version = apiVersion
|
|
postRequest.Product = product
|
|
postRequest.ApiName = POST_REQUEST_ACTION
|
|
postRequest.Method = "POST"
|
|
|
|
|
|
mapTask := make(map[string]string)
|
|
mapTask[KEY_APP_KEY] = c.AppKey
|
|
mapTask[KEY_FILE_LINK] = fileLink
|
|
// 新接入请使用4.0版本,已接入(默认2.0)如需维持现状,请注释掉该参数设置
|
|
mapTask[KEY_VERSION] = "4.0"
|
|
// 设置是否输出词信息,默认为false,开启时需要设置version为4.0
|
|
mapTask[KEY_ENABLE_WORDS] = "true"
|
|
|
|
//统一后处理
|
|
mapTask[KEY_ENABLE_INVERSE_TEXT_NORMAL] = "true"
|
|
mapTask[KEY_ENABLE_SEMANTIC_SENTENCE_DETECTION] = "true"
|
|
mapTask[KEY_ENABLE_TIMESTAMP_ALIGNMENT] = "true"
|
|
|
|
// to json
|
|
task, err := json.Marshal(mapTask)
|
|
if err != nil {
|
|
return "" , client , errors.New("to json error .")
|
|
}
|
|
postRequest.FormParams[KEY_TASK] = string(task)
|
|
// 发起请求
|
|
postResponse, err := client.ProcessCommonRequest(postRequest)
|
|
if err != nil {
|
|
return "" , client , err
|
|
}
|
|
postResponseContent := postResponse.GetHttpContentString()
|
|
//校验请求
|
|
if (postResponse.GetHttpStatus() != 200) {
|
|
return "" , client , errors.New("录音文件识别请求失败 , Http错误码 : " + strconv.Itoa(postResponse.GetHttpStatus()))
|
|
}
|
|
//解析数据
|
|
var postMapResult map[string]interface{}
|
|
err = json.Unmarshal([]byte(postResponseContent), &postMapResult)
|
|
if err != nil {
|
|
return "" , client , errors.New("to map struct error .")
|
|
}
|
|
|
|
var taskId = ""
|
|
var statusText = ""
|
|
statusText = postMapResult[KEY_STATUS_TEXT].(string)
|
|
|
|
//检验结果
|
|
if statusText == STATUS_SUCCESS {
|
|
taskId = postMapResult[KEY_TASK_ID].(string)
|
|
return taskId , client , nil
|
|
}
|
|
|
|
return "" , client , errors.New("录音文件识别失败 , (" + c.GetErrorStatusTextMessage(statusText) + ")")
|
|
}
|
|
|
|
|
|
//获取录音文件识别结果
|
|
//接口文档 https://help.aliyun.com/document_detail/90727.html?spm=a2c4g.11186623.6.581.691af6ebYsUkd1
|
|
func (c AliyunClound) GetAudioFileResult(taskId string , client *sdk.Client , logOutput func(text string) , callback func(result []byte)) (err error) {
|
|
_, domain, apiVersion, product := c.GetApiVariable()
|
|
|
|
getRequest := requests.NewCommonRequest()
|
|
getRequest.Domain = domain
|
|
getRequest.Version = apiVersion
|
|
getRequest.Product = product
|
|
getRequest.ApiName = GET_REQUEST_ACTION
|
|
getRequest.Method = "GET"
|
|
getRequest.QueryParams[KEY_TASK_ID] = taskId
|
|
statusText := ""
|
|
|
|
|
|
var (
|
|
trys = 0
|
|
getResponse *responses.CommonResponse
|
|
getResponseContent string
|
|
)
|
|
|
|
//遍历获取识别结果
|
|
for trys < 10 {
|
|
|
|
if trys != 0 {
|
|
logOutput("尝试重新查询识别结果,第" + strconv.Itoa(trys) + "次")
|
|
}
|
|
|
|
getResponse, err = client.ProcessCommonRequest(getRequest)
|
|
if err != nil {
|
|
logOutput("查询识别结果失败:" + err.Error())
|
|
trys++
|
|
time.Sleep(time.Second * time.Duration(trys))
|
|
continue
|
|
}
|
|
|
|
getResponseContent = getResponse.GetHttpContentString()
|
|
if (getResponse.GetHttpStatus() != 200) {
|
|
logOutput("查询识别结果失败,Http错误码:" + strconv.Itoa(getResponse.GetHttpStatus()))
|
|
trys++
|
|
time.Sleep(time.Second * time.Duration(trys))
|
|
continue
|
|
}
|
|
|
|
var getMapResult map[string]interface{}
|
|
err = json.Unmarshal([]byte(getResponseContent), &getMapResult)
|
|
if err != nil {
|
|
trys++
|
|
logOutput("查询识别结果失败,解析结果失败:" + err.Error())
|
|
continue
|
|
}
|
|
|
|
//校验遍历条件
|
|
statusText = getMapResult[KEY_STATUS_TEXT].(string)
|
|
if statusText == STATUS_RUNNING || statusText == STATUS_QUEUEING {
|
|
time.Sleep(3 * time.Second)
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
if statusText == STATUS_SUCCESS && getResponse != nil {
|
|
//调用回调函数
|
|
callback(getResponse.GetHttpContentBytes())
|
|
} else {
|
|
err = errors.New("录音文件识别失败 , (" + c.GetErrorStatusTextMessage(statusText) + ")")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
|
|
|
|
//获取API常量
|
|
func (c AliyunClound) GetApiVariable () (regionId string , domain string , apiVersion string , product string) {
|
|
if c.Region == 0 || c.Region == ALIYUN_CLOUND_REGION_CHA {
|
|
regionId = REGION_ID_REGION_CHA
|
|
domain = DOMAIN_REGION_CHA
|
|
apiVersion = API_VERSION_REGION_CHA
|
|
product = PRODUCT_REGION_CHA
|
|
} else if c.Region == ALIYUN_CLOUND_REGION_INT {
|
|
regionId = REGION_ID_REGION_INT
|
|
domain = DOMAIN_REGION_INT
|
|
apiVersion = API_VERSION_REGION_INT
|
|
product = PRODUCT_REGION_INT
|
|
}
|
|
return
|
|
}
|
|
|
|
//获取错误信息
|
|
func (c AliyunClound) GetErrorStatusTextMessage (statusText string) string {
|
|
var code map[string]string = map[string]string{
|
|
"REQUEST_APPKEY_UNREGISTERED":"阿里云智能语音项目未创建/无访问权限。请检查语音引擎Appkey是否填写错误;如果是海外地区,在软件创建语音引擎时,服务区域需要选择“海外”",
|
|
"USER_BIZDURATION_QUOTA_EXCEED":"单日2小时识别免费额度超出限制",
|
|
"FILE_DOWNLOAD_FAILED":"文件访问失败,请检查OSS存储空间访问权限。请将OSS存储空间设置为“公共读”",
|
|
"FILE_TOO_LARGE":"音频文件超出512MB",
|
|
"FILE_PARSE_FAILED":"音频文件解析失败,请检查音频文件是否有损坏",
|
|
"UNSUPPORTED_SAMPLE_RATE":"采样率不匹配",
|
|
"FILE_TRANS_TASK_EXPIRED":"音频文件识别任务过期,请重试",
|
|
"REQUEST_INVALID_FILE_URL_VALUE":"音频文件访问失败,请检查OSS存储空间访问权限",
|
|
"FILE_404_NOT_FOUND":"音频文件访问失败,请检查OSS存储空间访问权限",
|
|
"FILE_403_FORBIDDEN":"音频文件访问失败,请检查OSS存储空间访问权限",
|
|
"FILE_SERVER_ERROR":"音频文件访问失败,请检查请求的文件所在的服务是否可用",
|
|
"INTERNAL_ERROR":"识别内部通用错误,请稍候重试",
|
|
}
|
|
|
|
if _, ok := code[statusText]; ok {
|
|
return code[statusText]
|
|
} else {
|
|
return statusText
|
|
}
|
|
}
|