package aliyun import ( "github.com/buger/jsonparser" "regexp" "strings" "unicode" "unicode/utf8" "videosrt/app/tool" ) type AliyunAudioRecognitionResultBlock struct { AliyunAudioRecognitionResult Blocks []int BlockEmptyTag bool BlockEmptyHandle bool } //阿里云录音录音文件识别 - 智能分段处理 func AliyunAudioResultWordHandle(result [] byte , callback func (vresult *AliyunAudioRecognitionResult)) { var audioResult = make(map[int64][] *AliyunAudioRecognitionResultBlock) var wordResult = make(map[int64][]*AliyunAudioWord) var err error //获取录音识别数据集 _, err = jsonparser.ArrayEach(result, func(value []byte, dataType jsonparser.ValueType, offset int, err error) { text , _ := jsonparser.GetString(value, "Text") channelId , _ := jsonparser.GetInt(value, "ChannelId") beginTime , _ := jsonparser.GetInt(value, "BeginTime") endTime , _ := jsonparser.GetInt(value, "EndTime") silenceDuration , _ := jsonparser.GetInt(value, "SilenceDuration") speechRate , _ := jsonparser.GetInt(value, "SpeechRate") emotionValue , _ := jsonparser.GetInt(value, "EmotionValue") vresult := &AliyunAudioRecognitionResultBlock {} vresult.Text = text vresult.ChannelId = channelId vresult.BeginTime = beginTime vresult.EndTime = endTime vresult.SilenceDuration = silenceDuration vresult.SpeechRate = speechRate vresult.EmotionValue = emotionValue _ , isPresent := audioResult[channelId] if isPresent { //追加 audioResult[channelId] = append(audioResult[channelId] , vresult) } else { //初始 audioResult[channelId] = []*AliyunAudioRecognitionResultBlock{} audioResult[channelId] = append(audioResult[channelId] , vresult) } } , "Result", "Sentences") if err != nil { panic(err) } //获取词语数据集 _, err = jsonparser.ArrayEach(result , func(value []byte, dataType jsonparser.ValueType, offset int, err error) { word , _ := jsonparser.GetString(value, "Word") channelId , _ := jsonparser.GetInt(value, "ChannelId") beginTime , _ := jsonparser.GetInt(value, "BeginTime") endTime , _ := jsonparser.GetInt(value, "EndTime") vresult := &AliyunAudioWord{ Word:word, ChannelId:channelId, BeginTime:beginTime, EndTime:endTime, } _, isPresent := wordResult[channelId] if isPresent { //追加 wordResult[channelId] = append(wordResult[channelId] , vresult) } else { //初始 wordResult[channelId] = []*AliyunAudioWord{} wordResult[channelId] = append(wordResult[channelId] , vresult) } } , "Result" , "Words") if err != nil { panic(err) } var symbol = []string{"?","。",",","!",";","、","?",".",",","!"} //数据集处理 for _ , value := range audioResult { for _ , data := range value { // filter data.Text = FilterText(data.Text) data.Blocks = GetTextBlock(data.Text) data.Text = ReplaceStrs(data.Text , symbol , "") if len(data.Blocks) == 0 { data.BlockEmptyTag = true } } } //遍历输出 for _,value := range wordResult { var block string = "" var blockRune int = 0 var lastBlock int = 0 var beginTime int64 = 0 var blockBool = false var ischinese = IsChineseWords(value) //校验中文 var chineseNumberWordIndexs []int var chineseNumberDiffLength int = 0 for i , word := range value { if blockBool || i == 0 { beginTime = word.BeginTime blockBool = false } if ischinese && block == "" { chineseNumberWordIndexs = []int{} chineseNumberDiffLength = 0 } if ischinese { block += word.Word if tool.CheckChineseNumber(word.Word) && FindSliceIntCount(chineseNumberWordIndexs , i) == 0 { cl := tool.ChineseNumberToLowercaseLength(word.Word) - utf8.RuneCountInString(word.Word) if cl > 0 { chineseNumberDiffLength += cl chineseNumberWordIndexs = append(chineseNumberWordIndexs , i) } else { //例外 if i != 0 { newWord := value[i-1].Word + word.Word cl := tool.ChineseNumberToLowercaseLength(newWord) - utf8.RuneCountInString(newWord) if cl > 0 { chineseNumberDiffLength += cl chineseNumberWordIndexs = append(chineseNumberWordIndexs , i) } } } } } else { block += CompleSpace(word.Word) //补全空格 } blockRune = utf8.RuneCountInString(block) //fmt.Println("chineseNumberDiffLength : " , chineseNumberWordIndexs , chineseNumberDiffLength , word.Word) for channel , p := range audioResult { if word.ChannelId != channel { continue } for windex , w := range p { if (word.BeginTime >= w.BeginTime && word.EndTime <= w.EndTime) || ((word.BeginTime < w.EndTime && word.EndTime > w.EndTime) && (FindSliceIntCount(w.Blocks , -1) != len(w.Blocks))) { flag := false early := false if !w.BlockEmptyTag { for t , B := range w.Blocks{ //fmt.Println("blockRune : " , blockRune , B , word.Word) if ((blockRune >= B) || (blockRune + chineseNumberDiffLength >= B)) && B != -1 { flag = true //fmt.Println(w.Blocks) //fmt.Println(B , lastBlock , (B - lastBlock) , word.Word) //fmt.Println(w.Text) //fmt.Println( block ) //fmt.Println("\n") var thisText = "" //容错机制 if t == (len(w.Blocks) - 1) { thisText = SubString(w.Text , lastBlock , 10000) } else { //下个词提前结束 if i < len(value)-1 && value[i+1].BeginTime >= w.EndTime{ thisText = SubString(w.Text , lastBlock , 10000) early = true } else { thisText = SubString(w.Text , lastBlock , (B - lastBlock)) } } lastBlock = B if early == true { //全部设置为-1 for vt,vb := range w.Blocks{ if vb != -1 { w.Blocks[vt] = -1; } } } else { w.Blocks[t] = -1 } vresult := &AliyunAudioRecognitionResult{ Text:thisText, ChannelId:channel, BeginTime:beginTime, EndTime:word.EndTime, SilenceDuration:w.SilenceDuration, SpeechRate:w.SpeechRate, EmotionValue:w.EmotionValue, } callback(vresult) //回调传参 blockBool = true break } } //fmt.Println("word.Word : " , word.Word) //fmt.Println(block) if FindSliceIntCount(w.Blocks , -1) == len(w.Blocks) { //全部截取完成 block = "" lastBlock = 0 } //容错机制 if FindSliceIntCount(w.Blocks , -1) == (len(w.Blocks)-1) && flag == false { var thisText = SubString(w.Text , lastBlock , 10000) w.Blocks[len(w.Blocks) - 1] = -1 //vresult vresult := &AliyunAudioRecognitionResult{ Text:thisText, ChannelId:channel, BeginTime:beginTime, EndTime:w.EndTime, SilenceDuration:w.SilenceDuration, SpeechRate:w.SpeechRate, EmotionValue:w.EmotionValue, } //fmt.Println( thisText ) //fmt.Println( block ) //fmt.Println( word.Word , beginTime, w.EndTime , flag , word.EndTime ) callback(vresult) //回调传参 //覆盖下一段落的时间戳 if windex < (len(p)-1) { beginTime = p[windex+1].BeginTime } else { beginTime = w.EndTime } //清除参数 block = "" lastBlock = 0 } } else { //清除参数 block = "" lastBlock = 0 blockBool = true if w.BlockEmptyHandle == false { vresult := &AliyunAudioRecognitionResult{ Text:w.Text, ChannelId:w.ChannelId, BeginTime:w.BeginTime, EndTime:w.EndTime, SilenceDuration:w.SilenceDuration, SpeechRate:w.SpeechRate, EmotionValue:w.EmotionValue, } callback(vresult) //回调传参 w.BlockEmptyHandle = true } } } } } } } } func FindSliceIntCount(slice []int , target int) int { c := 0 for _ , v := range slice { if target == v { c++ } } return c } //批量替换多个关键词文本 func ReplaceStrs(strs string , olds []string , s string) string { for _ , word := range olds { strs = strings.Replace(strs , word , s , -1) } return strs } func StringIndex(strs string , word rune) int { strsRune := []rune(strs) for i,v := range strsRune { if v == word { return i } } return -1 } //补全右边空格 func CompleSpace(s string) string { s = strings.TrimLeft(s , " "); s = strings.TrimRight(s , " "); return s + " "; } func IsChineseWords(words []*AliyunAudioWord) bool { for _,v := range words { if (IsChineseChar(v.Word)){ return true } } return false } func IsChineseChar(str string) bool { for _, r := range str { if unicode.Is(unicode.Scripts["Han"], r) || (regexp.MustCompile("[\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b]").MatchString(string(r))) { return true } } return false } func IndexRunes(strs string , olds []rune) int { min := -1 for i , word := range olds { index := StringIndex(strs , word) //println( "ts : " , index) if i == 0 { min = index } else { if min == -1 { min = index } else { if index < min && index != -1 { min = index } } } } return min } func GetTextBlock(strs string) ([]int) { var symbol_zhcn = []rune{'?','。',',','!',';','、','?','.',',','!'} //var symbol_en = []rune{'?','.',',','!'} strsRune := []rune(strs) blocks := []int{} for { index := IndexRunes(strs , symbol_zhcn) if index == -1 { break } strs = string(strsRune[0:index]) + string(strsRune[(index + 1):]) strsRune = []rune(strs) blocks = append(blocks , index) } return blocks } func SubString(str string , begin int ,length int) (substr string) { // 将字符串的转换成[]rune rs := []rune(str) lth := len(rs) // 简单的越界判断 if begin < 0 { begin = 0 } if begin >= lth { begin = lth } if length < 0 { length = 0 } end := begin + length if end > lth { end = lth } // 返回子串 return string(rs[begin:end]) } //过滤文本 func FilterText(text string) string { //去除换行符 re, _ := regexp.Compile("[\n|\r|\r\n]+") text = re.ReplaceAllString(text, "") return text }