You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1009 lines
33 KiB
Go

// go:build !test
//go:build !test
// +build !test
// for STT SELVAS STT
package icsstt
/*
#cgo LDFLAGS: -lstdc++ -ldl ./extlib/selvasstt/SDK/LIB/c_linux/x64/libSTTLIB.a ./extlib/selvasstt/SDK/OpenSSL/Linux/Linux_x64/libssl.a ./extlib/selvasstt/SDK/OpenSSL/Linux/Linux_x64/libcrypto.a
#cgo CFLAGS: -I ../extlib/selvasstt/SDK/INCLUDE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <STT_Api.h>
char* getResultData(LVCSR_DATA_RESULT* pDataResult, int nCount) {
char* skip1 = "<eps>";
char* space = " ";
int len = 0;
int i;
for (i = 0; i < nCount; i++) {
int maxLength = 50 + strlen(pDataResult[i].pTokenStr);
char* strResult = malloc(sizeof(char) * maxLength);
sprintf(strResult, "%u|%u|%s\n", pDataResult[i].nStart, pDataResult[i].nEnd, pDataResult[i].pTokenStr);
len += strlen(strResult) + 1;
printf("%ld|%ld\n", pDataResult[i].nStart, pDataResult[i].nEnd);
free(strResult);
}
char* result = malloc(sizeof(char) * (len + 50));
strcpy(result, "");
for (i = 0; i < nCount; i++) {
int maxLength = 50 + strlen(pDataResult[i].pTokenStr);
char* strResult = malloc(sizeof(char) * maxLength);
sprintf(strResult, "%u|%u|%s\n", pDataResult[i].nStart, pDataResult[i].nEnd, pDataResult[i].pTokenStr);
if (strcmp(pDataResult[i].pTokenStr,skip1) == 0) {
} else {
strcat(result, space);
strcat(result, strResult);
}
free(strResult);
}
return result;
}
// char* getResultStrData(LVCSR_DATA_RESULT* pResultStr) {
// char* skip1 = "<eps>";
// char* space = " ";
// int len = 0;
// long long i;
// for (i = 0; i < nCount; i++) {
// len += strlen(pDataResult[i].pTokenStr) + 1;
// printf("start: %ld, end: %ld\n", pDataResult[i].nStart, pDataResult[i].nEnd);
// }
// char* result = malloc(sizeof(char) * len);
// strcpy(result, "");
// for (i = 0; i < nCount; i++) {
// if (strcmp(pDataResult[i].pTokenStr,skip1) == 0) {
// } else {
// strcat(result, space);
// strcat(result, pDataResult[i].pTokenStr);
// }
// }
// return result;
// }
void freeResult(char* result){
if(result == NULL) {
return;
}
free(result);
}
int getMidResultEPD(LVCSR_RECOG_MID_RESULT *midResult){
return midResult->bEngineDetectionFlag;
}
void printMidResult(LVCSR_RECOG_MID_RESULT *midResult){
printf("result len : %ld\n", midResult->nResultLen);
printf("pResultStr : %s\n", midResult->pResultStr);
printf("flag : %d\n", midResult->bEngineDetectionFlag);
printf("count: %ld\n\n", midResult->nDataCnt);
}
void setSid(LVCSR_DATA_LOGINFO *logInfo, char* sid, int size) {
// memset(logInfo.tloItemSID, 0, 51);
// memcpy(logInfo.tloItemSID, sid, size);
sprintf(logInfo->tloItemSID, "%s", sid);
// printf("logInfo.tloItemSID-%s\n ", logInfo.tloItemSID);
}
void setCallId(LVCSR_DATA_LOGINFO *logInfo, char* callId, int size) {
// memset(logInfo.tloItemCallID, 0, 61);
// memcpy(logInfo.tloItemCallID, callId, size);
sprintf(logInfo->tloItemCallID, "%s", callId);
// printf("logInfo.tloItemCallID-%s\n ", logInfo.tloItemSID);
}
void setTrId(LVCSR_DATA_LOGINFO *logInfo, char* trId, int size) {
// memset(logInfo.tloItemTransactionID, 0, 101);
// memcpy(logInfo.tloItemTransactionID, trId, size);
sprintf(logInfo->tloItemTransactionID, "%s", trId);
// printf("logInfo.tloItemTransactionID-%s\n ", logInfo.tloItemTransactionID);
}
void setItemStartMessage(LVCSR_DATA_LOGINFO *logInfo, char* tloTime, int size) {
// memset(logInfo.tloItemStartMessage, 0, 101);
// memcpy(logInfo.tloItemStartMessage, trId, size);
sprintf(logInfo->tloItemStartMessage, "%s", tloTime);
// printf("logInfo.tloItemStartMessage-%s\n ", logInfo.tloItemStartMessage);
}
void setConnId(LVCSR_DATA_CALLINFO *callInfo, char* sid, int size) {
callInfo->pConnIdStr = (char*)malloc(size + 1);
memset(callInfo->pConnIdStr, 0, size + 1);
callInfo->nConnIdLen = size;
sprintf(callInfo->pConnIdStr, "%s", sid);
// printf("logInfo.tloItemSID-%s\n ", logInfo.tloItemSID);
}
void setCallDateTime(LVCSR_DATA_CALLINFO *callInfo, unsigned long callDatetime) {
// memset(logInfo.tloItemCallID, 0, 61);
// memcpy(logInfo.tloItemCallID, callId, size);
LVCSR_DATE_TIMESTAMP pCallDateTime = { 0 };
unsigned long sBaseTimeMillis = time(NULL);
SelvySTT_GET_TIMESTAMP(sBaseTimeMillis, &pCallDateTime);
callInfo->pCallDateTime = pCallDateTime;
//sprintf(logInfo->tloItemCallID, "%s", callId);
// printf("logInfo.tloItemCallID-%s\n ", logInfo.tloItemSID);
}
void freeConnId(LVCSR_DATA_CALLINFO *callInfo) {
if (callInfo->pConnIdStr){
free(callInfo->pConnIdStr);
callInfo->pConnIdStr = NULL;
callInfo->nConnIdLen = 0;
}
}
long getSTTSockID(LVCSR_SOCK_HEAD sockhead) {
return sockhead.nSock;
}
*/
import "C"
import (
"fmt"
"log"
"runtime/debug"
"strings"
"sync"
"time"
"unsafe"
// "git.icomsys.co.kr/icomsys/voicecapture/voiceagent/icsconf"
// "git.icomsys.co.kr/icomsys/voicecapture/voiceagent/icserror"
// "git.icomsys.co.kr/icomsys/voicecapture/voiceagent/icslog"
"batchmodule/icsconf"
"batchmodule/icserror"
"batchmodule/icslog"
"github.com/google/uuid"
)
const (
CONNECT_TIMEOUT = 3
READ_CONNECT_TIMEOUT = 5
READ_CONNECT_TIMEOUT_LONGVOICE = 10
// model Info
MODEL_ID = 0
KWD_ID = -1
CODEC_TYPE = 0 // 8k
LANGUAGE = 1 // utf-8
USED_EPD = 1 // epd used
ENGINE_EPD_USED_ON = 2
NO_USED_EPD = 0 // epd used
//USED_EPD = 1 // epd used
USED_SCORE = 0 // used off
USED_ASYNC_MID_RESULT_OFF = 0 // mid result
USED_ASYNC_MID_RESULT_ON = 1 // mid result
DIRECTION_USED_UNK = 0 // Unknown
DIRECTION_USED_INB = 1 // Inbound
DIRECTION_USED_OB = 2 // Outbound
SEG_USED_MONO = 0 // Rx/Tx
SEG_USED_RX = 1 // Receiver
SEG_USED_TX = 2 // Transmitter
SEG_USED_BOT = 3
)
type AsyncCBFunc func(sttResult string, epd int, inout bool)
type STTSelvas struct {
sessionID int
//handle int
authCode string
//ch int
sttID C.long
text string
voiceBuf []byte
voiceBufCur int64
silencenum int
validnum int64 //rms counter
uDataSize int
uEndOfSpeech int
STTInfo STTInfo
IsClose bool
SpeechStatus int
RecordFilePath string
RecordStart *bool
rrData *RRData
M *sync.Mutex
txNum int //number of sending stt audio packet
callID string
custID string
callExt string
sreserved string
trid string
errCode string
errMsg string
errFunName string
result string
reqTime time.Time
rspTime time.Time
svcReqTime time.Time
svcRspTime time.Time
sttIdx int
sttStatus int
//icsstat.StatInfos
}
type STTInfo struct {
LVCSR_SOCK_HEAD C.LVCSR_SOCK_HEAD
LVCSR_EPD_INFO C.LVCSR_EPD_INFO
LVCSR_DATA_AUTHENTICATION C.LVCSR_DATA_AUTHENTICATION
LVCSR_RECOG_RESULT C.LVCSR_RECOG_RESULT
LVCSR_DATA_RESULT C.LVCSR_DATA_RESULT
LVCSR_RECOG_MID_RESULT C.LVCSR_RECOG_MID_RESULT
LVCSR_DATA_INFO C.LVCSR_DATA_INFO
LVCSR_DATA_LOGINFO C.LVCSR_DATA_LOGINFO
LVCSR_ERROR_RESULT C.LVCSR_ERROR_RESULT
LVCSR_DATA_CALLINFO C.LVCSR_DATA_CALLINFO
}
type STTSResult struct {
result string
error *icserror.IcsError
}
var (
conf icsconf.AppInfo
l *log.Logger
)
func init() {
conf = icsconf.Getconfig()
l = icslog.InitializeLogger()
}
func (s STTSelvas) GetTrID() string {
return s.trid
}
// connect SELVAS STT Server
func NewSTTSshort(IP string, port int, connId string, filePath string, isRx bool, isInbound bool) (*STTSelvas, *icserror.IcsError) {
//func NewSTTS(sid int, IP string, port int, callID string, custID string, filePath string, sreserved string, statOK bool) (*STTSelvas, *icserror.IcsError) {
var derr *icserror.IcsError = nil
l.Println("NewSTTSshort() has started!")
defer func() {
if err := recover(); err != nil {
switch v := err.(type) {
case error:
icserror.ICSERRSTTFailInit.SetError(v)
l.Printf("PANIC! %s\n%s\n", icserror.ICSERRSTTFailInit.GetError().Error(), string(debug.Stack()))
default:
l.Println(icserror.ICSERRSTTFailInit.GetError().Error())
}
}
derr = icserror.ICSERRSTTFailInit
}()
if len(IP) <= 0 || port <= 0 {
derr = icserror.ICSERRInvalidParam
return nil, derr
}
// STT 실패 재처리 모듈이라 callId, custId 없어서 connId 넣음.
stts := STTSelvas{authCode: "LGUPlusManager", uDataSize: 1600, uEndOfSpeech: 0, IsClose: false, SpeechStatus: 0, reqTime: time.Now(), svcReqTime: time.Time{}, svcRspTime: time.Time{}, callID: connId, custID: connId, result: "", errCode: "", errMsg: "", errFunName: ""}
//stts := STTSelvas{handle: -1, authCode: "LGUPlusManager", uDataSize: 1600, uEndOfSpeech: 0, IsClose: false}
stts.M = &sync.Mutex{}
stts.txNum = 0
//recording
stts.RecordFilePath = filePath
stts.RecordStart = new(bool)
*stts.RecordStart = true
stts.rrData = NewRRData(960000) //60sec
csIP := C.CString(IP)
defer C.free(unsafe.Pointer(csIP))
csPort := C.int(port)
csConTimeout := C.int(CONNECT_TIMEOUT)
csReadTimeout := C.int(READ_CONNECT_TIMEOUT)
trID := uuid.New().String()
trID = strings.ReplaceAll(trID, "-", "a")
stts.trid = trID
/*
if stts.sttStatus == STTMemo {
return &stts, nil
}
*/
//svcReqTime := time.Now()
l.Println("STT SelvySTT_INIT Start")
rc := C.SelvySTT_INIT(csIP, csPort, csConTimeout, csReadTimeout, &stts.STTInfo.LVCSR_SOCK_HEAD) // add LVCSR_SOCK_HEAD
if int(rc) == -1 {
////////////////테스트코드/////////////////////
rc = C.SelvySTT_GET_ERROR(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("[%d] SelvySTT_GET_ERROR Fail.. %d\n", int(stts.sttID), rc)
// return "", derr
} else {
l.Printf("[%d] LVCSR_ERROR_RESULT - [%d]%s\n", int(stts.sttID), stts.STTInfo.LVCSR_ERROR_RESULT.nErrorCode, C.GoString(&stts.STTInfo.LVCSR_ERROR_RESULT.pErrorMsg[0]))
}
l.Printf("STT SelvySTT_INIT Fail - rc:%d\n", rc)
derr = icserror.ICSERRSTTConnectTimeout
return nil, derr
} else if int(rc) == -2 {
l.Printf("STT SelvySTT_INIT Fail - rc:%d\n", rc)
////////////////테스트코드/////////////////////
rc = C.SelvySTT_GET_ERROR(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("[%d] SelvySTT_GET_ERROR Fail.. %d\n", int(stts.sttID), rc)
// return "", derr
} else {
l.Printf("[%d] LVCSR_ERROR_RESULT - [%d]%s \n", int(stts.sttID), stts.STTInfo.LVCSR_ERROR_RESULT.nErrorCode, C.GoString(&stts.STTInfo.LVCSR_ERROR_RESULT.pErrorMsg[0]))
}
///////////////////////////////////////////////
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
// callID = strings.ReplaceAll(callID, "-", "")
// if len(callID) > 12 {
// callID = callID[:12]
// }
// l.Printf("callID: %s\n", callID)
// if len(callID) == 0 {
// callID = trID
// }
now := time.Now()
tloTime := fmt.Sprintf("%d%02d%02d%02d%02d%02d\n", now.Year(), int(now.Month()), now.Day(), now.Hour(), now.Minute(), now.Minute())
csTrId := C.CString(trID)
defer C.free(unsafe.Pointer(csTrId))
csConnId := C.CString(connId)
defer C.free(unsafe.Pointer(csConnId))
csTloTime := C.CString(tloTime)
defer C.free(unsafe.Pointer(csTloTime))
// csCustID := C.CString(custID)
csCustID := C.CString(connId)
defer C.free(unsafe.Pointer(csCustID))
// connid 없어서 callid로 connid 만들었던 코드. 해당파일에서는 connId 넣어줌
// C.setConnId(&stts.STTInfo.LVCSR_DATA_CALLINFO, csCallId, C.int(len(callID)))
C.setConnId(&stts.STTInfo.LVCSR_DATA_CALLINFO, csConnId, C.int(len(connId)))
C.setCallDateTime(&stts.STTInfo.LVCSR_DATA_CALLINFO, C.ulong(time.Now().UnixNano()))
if isInbound {
stts.STTInfo.LVCSR_DATA_CALLINFO.nCallDirection = DIRECTION_USED_INB
} else {
stts.STTInfo.LVCSR_DATA_CALLINFO.nCallDirection = DIRECTION_USED_OB
}
if isRx {
stts.STTInfo.LVCSR_DATA_CALLINFO.nSpeakerSegmentation = SEG_USED_RX
} else {
stts.STTInfo.LVCSR_DATA_CALLINFO.nSpeakerSegmentation = SEG_USED_TX
}
l.Printf("[%d] SET SelvySTT_SET_CALLINFO > connID:%s, direction:%d, speakerSeg:%d\n", int(stts.sttID), C.GoString(stts.STTInfo.LVCSR_DATA_CALLINFO.pConnIdStr), stts.STTInfo.LVCSR_DATA_CALLINFO.nCallDirection, stts.STTInfo.LVCSR_DATA_CALLINFO.nSpeakerSegmentation)
// 콜인포 설정
rs := C.SelvySTT_SET_CALLINFO(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_DATA_CALLINFO)
// rs := C.SelvySTT_SET_LOGINFO(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_DATA_LOGINFO)
//ljhwan
//rs = 0
if int(rs) < 0 {
l.Printf("[%d] STT SelvySTT_SET_LOGINFO Fail Result rs:%d, LVCSR_DATA_LOGINFO: %+v\n", int(stts.sttID), rs, stts.STTInfo.LVCSR_DATA_LOGINFO)
////////////////테스트코드/////////////////////
rc = C.SelvySTT_GET_ERROR(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("[%d] SelvySTT_GET_ERROR Fail..", int(stts.sttID))
// return "", derr
} else {
l.Printf("[%d] LVCSR_ERROR_RESULT - [%d]%s\n", int(stts.sttID), stts.STTInfo.LVCSR_ERROR_RESULT.nErrorCode, C.GoString(&stts.STTInfo.LVCSR_ERROR_RESULT.pErrorMsg[0]))
}
///////////////////////////////////////////////
// Server Close
//svcReqTime = time.Now()
l.Printf("[%d] STT SelvySTT_EXIT Start\n", int(stts.sttID))
rc = C.SelvySTT_EXIT(&stts.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("[%d] STT SelvySTT_EXIT Fail Result rs:%d\n", int(stts.sttID), rs)
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
C.freeConnId(&stts.STTInfo.LVCSR_DATA_CALLINFO)
//svcReqTime = time.Now()
// Set Model List
stts.STTInfo.LVCSR_DATA_INFO.nModelID = MODEL_ID
stts.STTInfo.LVCSR_DATA_INFO.nKwdID = KWD_ID
stts.STTInfo.LVCSR_DATA_INFO.nCodecType = CODEC_TYPE
stts.STTInfo.LVCSR_DATA_INFO.nCharSet = LANGUAGE
// if stts.sttStatus == STTMemo {
// stts.STTInfo.LVCSR_DATA_INFO.nEpdUsed = NO_USED_EPD
// } else {
stts.STTInfo.LVCSR_DATA_INFO.nEpdUsed = ENGINE_EPD_USED_ON
stts.STTInfo.LVCSR_DATA_INFO.bAsyncMidRstUsed = USED_ASYNC_MID_RESULT_ON
// }
stts.STTInfo.LVCSR_DATA_INFO.bScoreUsed = USED_SCORE
// Channel Connect
//svcReqTime = time.Now()
l.Printf("[%d] STT SelvySTT_OPEN Start\n", int(stts.sttID))
rc = C.SelvySTT_OPEN(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_DATA_INFO) // add LVCSR_SOCK_HEAD
//ljhwan
//rc = 0
if int(rc) < 0 {
l.Printf("[%d] STT SelvySTT_OPEN Fail, LVCSR_SOCK_HEAD: %+v\r\n", int(stts.sttID), stts.STTInfo.LVCSR_SOCK_HEAD)
// Server Close
//svcReqTime = time.Now()
l.Printf("[%d] STT SelvySTT_EXIT Start", int(stts.sttID))
rc = C.SelvySTT_EXIT(&stts.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("[%d]STT SelvySTT_EXIT Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v\n", int(stts.sttID), rs, stts.STTInfo.LVCSR_SOCK_HEAD)
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
// rc = C.SelvySTT_SET_INFO(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_DATA_INFO)
// //ljhwan
// //rc = 0
// if int(rc) < 0 {
// l.Printf("[%d]STT SelvySTT_SET_INFO Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v, stts.STTInfo.LVCSR_DATA_INFO: %+v\n", int(stts.sttID), rs, stts.STTInfo.LVCSR_SOCK_HEAD, stts.STTInfo.LVCSR_DATA_INFO)
// // Channel Connection Close
// //svcReqTime = time.Now()
// l.Printf("[%d]STT SelvySTT_CLOS Start\n", int(stts.sttID))
// rc = C.SelvySTT_CLOS(&stts.STTInfo.LVCSR_SOCK_HEAD)
// if int(rc) < 0 {
// l.Printf("[%d]STT SelvySTT_CLOS Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v\n", int(stts.sttID), rs, stts.STTInfo.LVCSR_SOCK_HEAD)
// derr = icserror.ICSERRTTSNotInit
// }
// // Server Close
// l.Printf("[%d]STT SelvySTT_EXIT Start\n", int(stts.sttID))
// //svcReqTime = time.Now()
// rc = C.SelvySTT_EXIT(&stts.STTInfo.LVCSR_SOCK_HEAD)
// if int(rc) < 0 {
// l.Printf("[%d]STT SelvySTT_EXIT Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v\n", int(stts.sttID), rs, stts.STTInfo.LVCSR_SOCK_HEAD)
// derr = icserror.ICSERRSTTFailInit
// return nil, derr
// }
// derr = icserror.ICSERRSTTFailInit
// return nil, derr
// }
//l.Printf("[%d]Selvas STT New Connection > callID:'%s',trID:'%s'\n", int(stts.sttID), callID, trID)
l.Printf("[%d]Selvas STT New Connection > connId:'%s',trID:'%s'\n", int(stts.sttID), connId, trID)
return &stts, derr
}
func (s *STTSelvas) Close() *icserror.IcsError {
if s == nil {
return icserror.ICSERRSTTNotInit
}
var derr *icserror.IcsError = nil
defer func() {
if err := recover(); err != nil {
switch v := err.(type) {
case error:
icserror.ICSERRSTTFailInit.SetError(v)
l.Printf("PANIC! %s\n%s\n", icserror.ICSERRSTTFailInit.GetError().Error(), string(debug.Stack()))
default:
l.Print(icserror.ICSERRSTTFailInit.GetError().Error())
}
derr = icserror.ICSERRSTTFailInit
return
}
// derr = icserror.ICSERRSTTFailInit
}()
l.Printf("Close STT[%d]. Send Audio Packet Num: %d\n", int(s.sttID), s.txNum)
s.M.Lock()
s.IsClose = true
s.M.Unlock()
*s.RecordStart = false
rc := C.SelvySTT_CLS_RES(&s.STTInfo.LVCSR_RECOG_RESULT)
if int(rc) < 0 {
l.Printf("Failed to free STT result[%d]. rc: %d\n", int(s.sttID), rc)
if strings.Compare(s.errCode, "54000013") != 0 {
s.errCode, s.errMsg, s.errFunName = "54000010", "Fail", "SelvySTT_CLS_RES"
}
derr = icserror.ICSERRSTTFreeError
}
// Channel Connection Close
l.Printf("Close STT channel[%d]\n", int(s.sttID))
rc = C.SelvySTT_CLOS(&s.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("Failed to close STT channel[%d], rc: %d\n", int(s.sttID), rc)
if s.result == "$NO_RESULT$" {
s.errCode, s.errMsg, s.errFunName = "20000003", "Success", ""
} else if strings.Compare(s.errCode, "54000013") != 0 {
s.errCode, s.errMsg, s.errFunName = "54000011", "Fail", "SelvySTT_CLOS"
}
derr = icserror.ICSERRTTSNotInit
}
// Server Close
l.Printf("Close STT SVC[%d]\n", int(s.sttID))
rc = C.SelvySTT_EXIT(&s.STTInfo.LVCSR_SOCK_HEAD)
//ljhwan
//rc = 0
if int(rc) < 0 {
l.Printf("Failed to close STT SVC[%d], rc: %d\n", int(s.sttID), rc)
derr = icserror.ICSERRTTSNotInit
if strings.Compare(s.errCode, "54000013") != 0 {
s.errCode, s.errMsg, s.errFunName = "54000012", "Fail", "SelvySTT_EXIT"
}
}
l.Printf("Closed STT[%d] sock header: %+v\n", int(s.sttID), s.STTInfo.LVCSR_SOCK_HEAD.nSock)
s.rrData.Clear()
return derr
}
func (s *STTSelvas) GetSTTStatus() bool {
if s == nil {
// fmt.Println("get status: stt handle nil")
return false
}
s.M.Lock()
b := s.IsClose
s.M.Unlock()
return b
}
// type AsyncCBFunc func(sttResult string, epd int)
func (s *STTSelvas) SendSTT(voicedata []byte, final bool, cbFunc AsyncCBFunc) (string, *icserror.IcsError) {
if s == nil {
return "", icserror.ICSERRTTSNotInit
}
var result string
var sendCount int
var derr *icserror.IcsError = nil
var resultsWithTime string
defer func() {
if err := recover(); err != nil {
switch v := err.(type) {
case error:
icserror.ICSERRSTTSendFail.SetError(v)
l.Printf("sttselvas.go>SendSTT()> PANIC! %s\n%s\n", icserror.ICSERRSTTSendFail.GetError().Error(), string(debug.Stack()))
default:
l.Print(icserror.ICSERRSTTSendFail.GetError().Error())
}
}
derr = icserror.ICSERRSTTSendFail
}()
// if s.sttStatus != STTMemo {
// Set EPD value
if !final {
s.uEndOfSpeech = 0
} else {
s.uEndOfSpeech = 1
}
// file split
// sendCount = len(voicedata) / 320
sendCount = len(voicedata) / 1600
// l.Printf("SendSTT voice size: %d, sendCount: %d \n", len(voicedata), sendCount)
//start := time.Now()
// send voice(voicedata)
for j := 0; j < sendCount; j++ {
// buff1 := voicedata[320*j : 320*(j+1)]
buff1 := voicedata[1600*j : 1600*(j+1)]
//recording audio
if *s.RecordStart {
s.rrData.AddAudio(buff1)
} else {
s.rrData.AddTempAudio(buff1)
}
csUDataSize := C.int(s.uDataSize)
// if !final && j < sendCount-1 {
// s.uEndOfSpeech = 0
// } else {
// s.uEndOfSpeech = 1
// }
csUEndSpeech := C.int(s.uEndOfSpeech)
csBuff := (*C.char)(unsafe.Pointer(&buff1[0]))
// l.Printf("SelvySTT_SEND_DATA : %d, size: %d EndofSpeech : %d\n", j, csUDataSize, s.uEndOfSpeech)
rc := C.SelvySTT_SEND_DATA(&s.STTInfo.LVCSR_SOCK_HEAD,
csBuff,
csUDataSize,
csUEndSpeech,
&s.STTInfo.LVCSR_EPD_INFO)
if int(rc) < 0 {
l.Printf("sttselvas.go>SendSTT()> [%d] SelvySTT_SEND_DATA ERROR %d\n", int(s.sttID), rc)
////////////////테스트코드/////////////////////
rc = C.SelvySTT_GET_ERROR(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("sttselvas.go>SendSTT()> [%d] SelvySTT_GET_ERROR Fail.. %d\n", int(s.sttID), rc)
// return "", derr
} else {
l.Printf("sttselvas.go>SendSTT()> [%d] LVCSR_ERROR_RESULT - [%d]%s\n", int(s.sttID), s.STTInfo.LVCSR_ERROR_RESULT.nErrorCode, C.GoString(&s.STTInfo.LVCSR_ERROR_RESULT.pErrorMsg[0]))
}
///////////////////////////////////////////////
s.errCode, s.errMsg, s.errFunName = "54000013", "Fail", "SelvySTT_SEND_DATA"
if cbFunc != nil {
cbFunc("", 99, true)
break
}
derr = icserror.ICSERRSTTSendFail
return "", derr
}
s.txNum++
if s.STTInfo.LVCSR_EPD_INFO == 1 {
//l.Printf("STT ID[%d] LVCSR_EPD_INFO: %d", int(s.sttID), s.STTInfo.LVCSR_EPD_INFO)
if s.SpeechStatus == 0 {
l.Printf("sttselvas.go>SendSTT()> STT ID[%d] LVCSR_EPD_INFO: %d\n", int(s.sttID), s.STTInfo.LVCSR_EPD_INFO)
s.SpeechStatus = 1
if cbFunc != nil {
cbFunc(result, int(s.STTInfo.LVCSR_EPD_INFO), true)
}
}
} else if s.STTInfo.LVCSR_EPD_INFO > 1 {
l.Printf("sttselvas.go>SendSTT()> LVCSR_EPD_INFO == %d\n", s.STTInfo.LVCSR_EPD_INFO)
s.svcReqTime = time.Now()
break
}
}
if s.STTInfo.LVCSR_EPD_INFO == 2 || s.STTInfo.LVCSR_EPD_INFO == 5 {
// l.Printf("[%d]!!!! LVCSR_EPD_INFO: %d, LVCSR_SOCK_HEAD: %+v", int(s.sttID), s.STTInfo.LVCSR_EPD_INFO, s.STTInfo.LVCSR_SOCK_HEAD)
l.Printf("sttselvas.go>SendSTT()> STT ID[%d] LVCSR_EPD_INFO: %d, STT Completed!\n", int(s.sttID), s.STTInfo.LVCSR_EPD_INFO)
rc := C.SelvySTT_GET_MIDRES(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_MID_RESULT)
s.svcRspTime = time.Now()
if int(rc) < 0 {
l.Printf("sttselvas.go>SendSTT()> [%d]SelvySTT_GET_MIDRES Failed!!! - rc:%d, s.STTInfo.LVCSR_RECOG_MID_RESULT:%+v\n", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_MID_RESULT)
// s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "ASR_SVC_RECG_STR_PROC"
s.result = "$NO_RESULT$"
derr = icserror.ICSERRSTTSendFail
if cbFunc != nil {
cbFunc("", 2, true)
}
return "", icserror.ICSERRSTTContinue // 묵음으로 처리
}
s.sttIdx++
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
result = C.GoString(s.STTInfo.LVCSR_RECOG_MID_RESULT.pResultStr)
resultTocken := C.GoString(s.STTInfo.LVCSR_RECOG_MID_RESULT.pDataResult.pTokenStr)
nStartTime := C.int(s.STTInfo.LVCSR_RECOG_MID_RESULT.pDataResult.nStart)
nEnd := C.int(s.STTInfo.LVCSR_RECOG_MID_RESULT.pDataResult.nEnd)
l.Printf("sttselvas.go>SendSTT()> STT ID[%d] result: %s, result: %p, pointer: %p\n", int(s.sttID), result, &result, s.STTInfo.LVCSR_RECOG_RESULT.pResultStr)
l.Printf("sttselvas.go>SendSTT()> STT ID[%d] result: %s, %d, %d\n", int(s.sttID), resultTocken, nStartTime, nEnd)
// l.Printf("STT ID[%d] result: %s, result: %p, pointer: %p\n", int(s.sttID), result, &result, s.STTInfo.LVCSR_RECOG_RESULT.pResultStr)
results := ""
if s.STTInfo.LVCSR_RECOG_MID_RESULT.nResultLen == 0 { // 길이 0일때 값 nil로 나옴
result = ""
}
//result = "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST"
s.result = result
results = result
if result == "$NO_RESULT$" {
results = ""
}
resultsWithTime = fmt.Sprintf("%d|%d|%s\n", nStartTime, nEnd, results)
if cbFunc != nil {
cbFunc(results, int(s.STTInfo.LVCSR_EPD_INFO), true)
}
//l.Printf("[%d] result Free OK", int(s.sttID))
wg.Done()
}()
wg.Wait()
// 중간결과 구조체 메모리 해제
rc = C.SelvySTT_CLS_MIDRES(&s.STTInfo.LVCSR_RECOG_MID_RESULT)
if int(rc) < 0 {
l.Println("sttselvas.go>SendSTT()> SelvySTT_CLS_MIDRES Failed!!! MID RES pResultStr: ", s.STTInfo.LVCSR_RECOG_MID_RESULT.pResultStr)
}
return resultsWithTime, icserror.ICSERRSTTContinue
}
// } else {
// s.uEndOfSpeech = 1
// //recording audio
// if *s.RecordStart {
// s.rrData.AddAudio(voicedata)
// } else {
// s.rrData.AddTempAudio(voicedata)
// }
// csUDataSize := C.int(s.uDataSize)
// csUEndSpeech := C.int(s.uEndOfSpeech)
// csBuff := (*C.char)(unsafe.Pointer(&voicedata))
// //csBuff := (*C.char)(unsafe.Pointer(&buff1[0]))
// rc := C.SelvySTT_SEND_DATA(&s.STTInfo.LVCSR_SOCK_HEAD,
// csBuff,
// csUDataSize,
// csUEndSpeech,
// &s.STTInfo.LVCSR_EPD_INFO)
// if int(rc) < 0 {
// l.Printf("[%d] SelvySTT_SEND_DATA ERROR %d", int(s.sttID), rc)
// ////////////////테스트코드/////////////////////
// rc = C.SelvySTT_GET_ERROR(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_ERROR_RESULT)
// if int(rc) < 0 {
// l.Printf("[%d] SelvySTT_GET_ERROR Fail.. %d", int(s.sttID), rc)
// // return "", derr
// } else {
// l.Printf("[%d] LVCSR_ERROR_RESULT - [%d]%s", int(s.sttID), s.STTInfo.LVCSR_ERROR_RESULT.nErrorCode, C.GoString(&s.STTInfo.LVCSR_ERROR_RESULT.pErrorMsg[0]))
// }
// ///////////////////////////////////////////////
// s.errCode, s.errMsg, s.errFunName = "54000013", "Fail", "SelvySTT_SEND_DATA"
// if cbFunc != nil {
// cbFunc("", 99, true)
// }
// derr = icserror.ICSERRSTTSendFail
// return "", derr
// }
// s.txNum++
// rc = C.SelvySTT_GET_MIDRES(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_MID_RESULT)
// s.svcRspTime = time.Now()
// if int(rc) < 0 {
// l.Printf("[%d]!!!! SelvySTT_GET_MIDRES Fail - rc:%d, s.STTInfo.LVCSR_RECOG_MID_RESULT:%+v", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_MID_RESULT)
// // s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "ASR_SVC_RECG_STR_PROC"
// s.result = "$NO_RESULT$"
// derr = icserror.ICSERRSTTSendFail
// if cbFunc != nil {
// cbFunc("", 2, true)
// }
// return "", icserror.ICSERRSTTContinue // 묵음으로 처리
// }
// result = C.GoString(s.STTInfo.LVCSR_RECOG_RESULT.pResultStr)
// l.Printf("STT ID[%d] result: %s, result: %p, pointer: %p", int(s.sttID), result, &result, s.STTInfo.LVCSR_RECOG_RESULT.pResultStr)
// results := ""
// if s.STTInfo.LVCSR_RECOG_RESULT.nResultLen == 0 { // 길이 0일때 값 nil로 나옴
// result = ""
// }
// //result = "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST"
// s.result = result
// results = result
// if result == "$NO_RESULT$" {
// results = ""
// }
// if cbFunc != nil {
// cbFunc(results, int(s.STTInfo.LVCSR_EPD_INFO), true)
// }
// //l.Printf("[%d] result Free OK", int(s.sttID))
// return results, icserror.ICSERRSTTOK
// }
return "", icserror.ICSERRSTTContinue
}
// result return
func NewSTTSResult(result string, err *icserror.IcsError) *STTSResult {
return &STTSResult{result, err}
}
// 말을 하지 않았을때 결과 조회
func (s *STTSelvas) GetSTTResultToStopSTT() (string, *icserror.IcsError) {
l := icslog.GetIcsLog()
if s == nil {
return "", icserror.ICSERRSTTNotInit
}
//rc := C.SelvySTT_GET_MIDRES(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_MID_RESULT)
rc := C.SelvySTT_GET_RES(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_RESULT)
l.Printf("GetSTTResultToStopSTT rc:%d, [%d] EPDINFO[%d] LVCSR_RECOG_RESULT: %+v, LVCSR_RECOG_RESULT:%+v\n", int(rc), int(s.sttID), s.STTInfo.LVCSR_EPD_INFO, &s.STTInfo.LVCSR_RECOG_RESULT, s.STTInfo.LVCSR_RECOG_RESULT)
if int(rc) < 0 {
l.Printf("[%d] SelvySTT_GET_MIDRES Fail - rc:%d, s.STTInfo.LVCSR_RECOG_MID_RESULT:%+v\n", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_MID_RESULT)
s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "SelvySTT_GET_MIDRES"
// s.SendStasticInfo(s.callID, s.custID, s.trid, "STT", "ASR_SVC_RECG_STR_PROC", "54000001", "Fail", "", "", s.reqTime, time.Now(), s.sreserved, svcReqTime, time.Now())
return "", icserror.ICSERRSTTSendFail
}
return "", icserror.ICSERRSTTContinue
}
// epd 1 이후 end 전송 => 결과조회
func (s *STTSelvas) SendSTTProcGetResult() (string, *icserror.IcsError) {
var derr *icserror.IcsError = nil
if s == nil {
return "", icserror.ICSERRSTTNotInit
}
//buff1 := make([]byte, 1)
s.uEndOfSpeech = 1
uDataSize := 0
csUDataSize := C.int(uDataSize)
csUEndSpeech := C.int(s.uEndOfSpeech)
//csBuff := (*C.char)(unsafe.Pointer(&buff1[0]))
// csBuff := nil
// svcReqTime := time.Now()
rc := C.SelvySTT_SEND_DATA(&s.STTInfo.LVCSR_SOCK_HEAD,
nil,
csUDataSize,
csUEndSpeech,
&s.STTInfo.LVCSR_EPD_INFO)
if int(rc) < 0 {
l.Printf("[ERR] sttselvas>SendSTTProcGetResult()> [%d] SelvySTT_SEND_DATA Failed - rc:%d, s.STTInfo.LVCSR_RECOG_RESULT:%+v\n", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_RESULT)
derr = icserror.ICSERRSTTSendFail
s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "SelvySTT_SEND_DATA"
// s.SendStasticInfo(s.callID, s.custID, s.trid, "STT", "SelvySTT_SEND_DATA", "54000001", "Fail", "", "", s.reqTime, time.Now(), s.sreserved, svcReqTime, time.Now())
return "", derr
}
l.Printf("[LOG] sttselvas>SendSTTProcGetResult()> rc:%d, [%d] EPDINFO[%d] LVCSR_RECOG_RESULT: %+v, LVCSR_RECOG_RESULT:%+v\n",
int(rc), int(s.sttID), s.STTInfo.LVCSR_EPD_INFO, &s.STTInfo.LVCSR_RECOG_RESULT, s.STTInfo.LVCSR_RECOG_RESULT)
if s.STTInfo.LVCSR_EPD_INFO == 2 {
// l.Printf("[%d]!!!! LVCSR_EPD_INFO: %d, LVCSR_SOCK_HEAD: %+v", int(s.sttID), s.STTInfo.LVCSR_EPD_INFO, s.STTInfo.LVCSR_SOCK_HEAD)
l.Printf("[LOG] sttselvas>SendSTTProcGetResult()> STT ID[%d] LVCSR_EPD_INFO: %d, STT Completed!\n", int(s.sttID), s.STTInfo.LVCSR_EPD_INFO)
rc := C.SelvySTT_GET_MIDRES(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_MID_RESULT)
s.svcRspTime = time.Now()
if int(rc) < 0 {
l.Printf("[ERR] sttselvas>SendSTTProcGetResult()> [%d] SelvySTT_GET_MIDRES Failed - rc:%d, s.STTInfo.LVCSR_RECOG_MID_RESULT:%+v\n", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_MID_RESULT)
// s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "ASR_SVC_RECG_STR_PROC"
s.result = "$NO_RESULT$"
// derr = icserror.ICSERRSTTSendFail
return "", icserror.ICSERRSTTContinue // 묵음으로 처리
}
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
result := C.GoString(s.STTInfo.LVCSR_RECOG_MID_RESULT.pResultStr)
l.Printf("[LOG] sttselvas>SendSTTProcGetResult()> STT ID[%d] result: %s, result: %p, pointer: %p\n", int(s.sttID), result, &result, s.STTInfo.LVCSR_RECOG_RESULT.pResultStr)
results := ""
if s.STTInfo.LVCSR_RECOG_MID_RESULT.nResultLen == 0 { // 길이 0일때 값 nil로 나옴
result = ""
}
//result = "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST"
s.result = result
results = result
if result == "$NO_RESULT$" {
results = ""
}
l.Printf("[LOG] sttselvas>SendSTTProcGetResult()> results: %s", results)
//l.Printf("[%d] result Free OK", int(s.sttID))
wg.Done()
}()
wg.Wait()
}
// 중간결과 구조체 메모리 해제
rc = C.SelvySTT_CLS_MIDRES(&s.STTInfo.LVCSR_RECOG_MID_RESULT)
if int(rc) < 0 {
l.Println("[ERR] sttselvas>SendSTTProcGetResult()> SelvySTT_CLS_MIDRES Failed. LVCSR_RECOG_MID_RESULT.pResultStr: ", s.STTInfo.LVCSR_RECOG_MID_RESULT.pResultStr)
}
// 최종 결과 호출
rc = C.SelvySTT_GET_RES(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_RESULT)
if int(rc) < 0 {
l.Printf("[ERR] sttselvas>SendSTTProcGetResult()> [%d] SelvySTT_GET_RES Fail - rc:%d, s.STTInfo.SelvySTT_GET_RES:%+v\n", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_RESULT)
derr = icserror.ICSERRSTTSendFail
s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "SelvySTT_GET_RES"
return "", derr
}
dataCnt := int(s.STTInfo.LVCSR_RECOG_RESULT.nDataCnt)
resultLen := int(s.STTInfo.LVCSR_RECOG_RESULT.nResultLen)
pResultStr := C.GoString(s.STTInfo.LVCSR_RECOG_RESULT.pResultStr)
l.Printf("dataCnt: %d", dataCnt)
l.Printf("resultLen: %d", resultLen)
if pResultStr != "" {
strresult := C.getResultData(s.STTInfo.LVCSR_RECOG_RESULT.pDataResult, C.int(dataCnt))
l.Printf("[LOG] sttselvas>SendSTTProcGetResult()> SelvySTT_GET_RES 인식 결과: %s", C.GoString(strresult))
defer C.free(unsafe.Pointer(strresult))
if resultLen > 0 {
l.Printf("[LOG] sttselvas>SendSTTProcGetResult()> SelvySTT_GET_RES 인식 결과: 연속어 [ %s ], 첫음 [ %d ] 끝음 [ %d ] 스코어 [ %f ]",
pResultStr, s.STTInfo.LVCSR_RECOG_RESULT.pDataResult.nStart, s.STTInfo.LVCSR_RECOG_RESULT.pDataResult.nEnd, s.STTInfo.LVCSR_RECOG_RESULT.fConfidScore)
} else {
return "", icserror.ICSERRSTTFail
}
// if dataCnt > 0 {
// for i := 0; i < dataCnt; i++ {
// l.Printf(icslog.LOG_LEVEL_INFO, -1, "음성인식 결과 : 인식어 [ %s ], 시작시간 [ %d ] 종료시간 [ %d ]", s.STTInfo.LVCSR_RECOG_RESULT.pDataResult[i].pTokenStr, s.STTInfo.LVCSR_RECOG_RESULT.pDataResult[i].nStart, s.STTInfo.LVCSR_RECOG_RESULT.pDataResult[i].nEnd)
// }
// }
//s.GetSTTResultToStopSTT()
// fmt.Print("Request Recg Result")
// rc = C.ASR_SVC_RECG_PROC(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_RESULT)
// if int(rc) < 0 {
// derr = icserror.ICSERRSTTFail
// return "", derr
// }
returnstr := C.GoString(strresult)
return returnstr, nil
}
return "", nil
}
func long(dataCnt int) {
panic("unimplemented")
}
// func getResultMessage(result *C.LVCSR_RECOG_RESULT, size int) []string {
// messages := make([]string, size)
// for i := 0; i < size; i++ {
// cMsg := C.GoString(result.pDataResult)
// }
// return s.rrData.GetAudio()
// }
func (s STTSelvas) GetAudio() []byte {
return s.rrData.GetAudio()
}
func (s STTSelvas) GetReqTime() time.Time {
return s.reqTime
}