icsstt 모듈 빠져있던것 추가

main
jiyoungcheon 1 month ago
parent 095ac40fa3
commit d2bac81363

@ -0,0 +1,180 @@
package stt
import (
"math"
"sync"
"mybatch/icslog"
)
const RR_200MSEC_SIZE = 3200
type RRData struct {
wPos int
wTPos int
wtSize int
rPos int
size int // max size
audio []byte
rtAudio []byte //for GetAudio()
rtAudioLen int
m *sync.Mutex
}
func NewRRData(size int) *RRData {
if size <= 0 {
return nil
}
rr := RRData{wPos: 0, rPos: 0, size: size, rtAudioLen: 0}
rr.m = &sync.Mutex{}
rr.audio = make([]byte, size)
rr.rtAudio = make([]byte, size)
return &rr
}
func (rr *RRData) AddAudio(data []byte) int {
l := icslog.InitializeLogger()
size := len(data)
if size <= 0 || rr.audio == nil {
return -1
}
rr.m.Lock()
if rr.wPos == 0 && rr.wTPos != 0 {
rr.wPos = rr.wtSize
}
if rr.wPos+size > rr.size {
l.Printf("AddAudio> RRData write size exceeded!!! size: %d-%d", rr.size, rr.wPos+size)
rr.wPos = rr.wtSize
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "AddAudio> RRData write size exceeded. wPos reset. %d-%d-%d", rr.wPos, rr.size, rr.wPos+size)
}
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "AddAudio> wPos: %d, size: %d, total size: %d", rr.wPos, size, rr.size)
copy(rr.audio[rr.wPos:], data[:])
rr.wPos += size
if rr.size <= rr.rtAudioLen {
rr.rtAudio = append(rr.rtAudio, data...)
} else {
copy(rr.rtAudio[rr.rtAudioLen:], data)
}
rr.rtAudioLen += size
rr.m.Unlock()
return rr.wPos
}
func (rr *RRData) AddTempAudio(data []byte) int {
//1sec temp buffer
if rr.size < 40000 || rr.audio == nil {
return -1
}
size := len(data)
if size <= 0 {
return -1
}
rr.m.Lock()
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "AddTempAudio> wtPos: %d, size: %d", rr.wTPos, size)
if rr.wTPos+size > 40000 {
//rr.wTPos = 0
rr.wtSize = 40000
rr.audio = rr.audio[size:]
copy(rr.audio[rr.wTPos-size:], data[:])
} else {
rr.wtSize += size
copy(rr.audio[rr.wTPos:], data[:])
rr.wTPos += size
}
rr.m.Unlock()
return rr.wTPos
}
func (rr *RRData) ReadAudio(size int) (int, []byte) {
l := icslog.InitializeLogger()
if rr.audio == nil {
return -2, nil
}
rr.m.Lock()
if int(math.Abs(float64(rr.wPos-rr.rPos))) < 1600 || int(math.Abs(float64(rr.wPos-rr.rPos))) < size {
rr.m.Unlock()
return 0, nil
}
rData := make([]byte, size)
if rr.size < rr.rPos+size {
rr.m.Unlock()
l.Printf("ReadAudio> RRData read size exceeded!!! size: %d-%d", rr.size, rr.rPos+size)
return -1, nil
//rr.rPos = 0
}
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "ReadAudio> rPos: %d, size: %d, total size: %d", rr.rPos, size, rr.size)
copy(rData[:], rr.audio[rr.rPos:rr.rPos+size])
//fmt.Println("read audio data:", rr.rPos)
rr.rPos += size
rr.m.Unlock()
return rr.rPos, rData
}
func (rr *RRData) Clear() {
rr.m.Lock()
rr.wPos = 0
rr.rPos = 0
rr.audio = nil
rr.rtAudio = nil
rr.m.Unlock()
l := icslog.InitializeLogger()
l.Print("Cleared RRData")
}
func (rr *RRData) GetAudio() []byte {
if rr.audio == nil {
return nil
}
rr.m.Lock()
if rr.rtAudioLen <= 0 {
rr.m.Unlock()
return nil
}
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "GetAudio> audio length: %d", rr.rtAudioLen)
var rData []byte
if rr.wtSize > 0 {
rData = make([]byte, rr.wtSize+rr.rtAudioLen)
copy(rData, rr.audio[:rr.wtSize])
copy(rData[rr.wtSize:], rr.rtAudio)
} else {
rData = make([]byte, rr.rtAudioLen)
copy(rData, rr.rtAudio)
}
rr.m.Unlock()
return rData
}
func (rr *RRData) Close() {
rr.audio = nil
rr.rtAudio = nil
//rr = new(RRData)
}

@ -0,0 +1,48 @@
package stt
import (
"cloud.google.com/go/speech/apiv1"
"cloud.google.com/go/speech/apiv1/speechpb"
"context"
"log"
"os"
)
func RecognizeSpeech(language, filepath string) error {
ctx := context.Background()
client, err := speech.NewClient(ctx)
if err != nil {
return err
}
defer client.Close()
audioData, err := os.ReadFile(filepath)
if err != nil {
return err
}
req := &speechpb.RecognizeRequest{
Config: &speechpb.RecognitionConfig{
Encoding: speechpb.RecognitionConfig_LINEAR16,
SampleRateHertz: 16000,
LanguageCode: language,
},
Audio: &speechpb.RecognitionAudio{
AudioSource: &speechpb.RecognitionAudio_Content{
Content: audioData,
},
},
}
resp, err := client.Recognize(ctx, req)
if err != nil {
return err
}
for _, result := range resp.Results {
for _, alt := range result.Alternatives {
log.Printf("Transcript: %s\n", alt.Transcript)
}
}
return nil
}

@ -0,0 +1,45 @@
package stt
import (
"fmt"
"mybatch/icsconf"
"mybatch/icserror"
"os"
"strconv"
"testing"
)
var config icsconf.AppInfo
func init() {
config = icsconf.Getconfig()
}
func TestXXX(t *testing.T) {
data, _ := os.ReadFile("/home/prac/svc/icsbc/voice/pcm/20250913223412/20250913223412-left.pcm")
connectSttServer()
sttResTest(data)
}
func connectSttServer(voicedata []byte) (bool, *icserror.IcsError) {
var s *STTSelvas
var sttErr *icserror.IcsError
ip := config.STT.SrcIP
port, _ := strconv.Atoi(cfg.STT.Port)
callId := "00ef1234567899001"
custid := "3002"
RecordFilePath := "/home/prac/svc/icsbc/sttres"
// func NewSTTS(sid int, IP string, port int, callID string, custID string, filePath string)
s, sttErr = NewSTTS(ip, port, callId, custid, RecordFilePath)
if sttErr != nil {
return false, icserror.ICSERRSTTConnectFail
} else if s != nil {
fmt.Println("STT session:", s)
}
fmt.Println("stt server is connected with: ", ip, ", port: ", port)
return true, nil
}
func sttResTest(voicedata []byte) (bool, *icserror.IcsError) {
}

@ -0,0 +1,449 @@
package stt
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"mybatch/icsconf"
encry "mybatch/icsencry"
"mybatch/icserror"
httprequest "mybatch/icshttp"
"mybatch/icslog"
"github.com/gorilla/websocket"
)
type RequestData struct {
StartTime string `json:"starttime"`
Ext string `json:"ext"`
ConnID string `json:"connid"`
}
type FileListResponse struct {
TotalCnt string `json:"totalCnt"`
ReturnCode string `json:"returnCode"`
ReturnMsg string `json:"returnMsg"`
List []FileInfo `json:"list"`
}
type FileInfo struct {
No int `json:"no"`
ConnID string `json:"connid"`
Ext string `json:"ext"`
StartTime string `json:"starttime"`
}
type Transcript struct {
Text string `json:"text"`
StartTime int `json:"startTime"`
EndTime int `json:"endTime"`
EndPoint bool `json:"endPoint"`
}
type ResponseData struct {
Uid string `json:"uid"`
Ext string `json:"ext"`
SpeakerTag string `json:"speakerTag"`
Transcripts []Transcript `json:"transcripts"`
}
type TAMessage struct {
Cmd string `json:"cmd"` // STT 이벤트 상태 구분값 S:시작, E:종료, T:Text, P:Partial
ConnID string `json:"connid"` //Cti 생성콜 key
Tel string `json:"tel"` //고객 전화번호
Ext string `json:"ext"` //상담사 내선번호
CallStartTime string `json:"callStartTime"` //콜 시작시간 unixtime
IgGbn string `json:"igGbn"` //통화유형 0:알수없음, 1:인바운드, 2:아웃바운드
DateTime string `json:"datetime"` //STT 시작시간
Stt string `json:"stt"` //STT 결과
Dir string `json:"dir"` //STT 화자구분 R:고객, T:상담사
}
var (
cfg icsconf.AppInfo
l *log.Logger
)
func init() {
cfg = icsconf.Getconfig()
l = icslog.InitializeLogger()
}
func ProcessPostRequestForDataList() {
var starttime uint64
currentDate := time.Now().Format("20060102")
currentDateUint64, _ := strconv.ParseUint(currentDate, 10, 64)
starttime = currentDateUint64 - 1
starttimeStr := strconv.FormatUint(starttime, 10)
data := RequestData{
StartTime: starttimeStr,
Ext: "",
ConnID: "",
}
jsonData, _ := json.Marshal(data)
encryptedRequestBody := encry.Encrypting(jsonData)
url := "https://192.168.0.69:8080/sttRest.do"
method := "POST"
requestBody := fmt.Sprintf(`{"data":"%s"}`, encryptedRequestBody)
response, err := httprequest.HttpRequest(url, method, requestBody)
if err != nil {
l.Println("error occured while requesting http post for datalist:", err)
return
}
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println("응답 on ProcessPostRequestForDataList: ", string(body))
var parsedRes FileListResponse
if err := json.Unmarshal([]byte(body), &parsedRes); err != nil {
l.Println("Error parsing JSON:", err)
return
}
var reqDataForVoiceFile RequestData
if len(parsedRes.List) > 0 {
for _, item := range parsedRes.List {
reqDataForVoiceFile = RequestData{
StartTime: item.StartTime,
Ext: item.Ext,
ConnID: item.ConnID,
}
// Requesting For wav file and download it at local
postReqForWavFileAndDownload(reqDataForVoiceFile)
}
} else {
l.Println("No items in the datalist.")
}
}
func postReqForWavFileAndDownload(parsedRes RequestData) {
jsonData, _ := json.Marshal(parsedRes)
encryptedRequestBody := encry.Encrypting(jsonData)
url := "https://192.168.0.69:8080/sttRest.do"
method := "POST"
requestBody := fmt.Sprintf(`{"data":"%s"}`, encryptedRequestBody)
response, err := httprequest.HttpRequest(url, method, requestBody)
if err != nil {
l.Println("error occured while requesting http post for datalist:", err)
return
}
st := parsedRes.StartTime
wavFilePath := cfg.Directories.WAVDirectory
fileName := fmt.Sprintf(`%s/%s.wav`, wavFilePath, st)
file, err := os.Create(fileName)
if err != nil {
l.Println("error occured while creating file:", err)
return
}
defer file.Close()
_, err = io.Copy(file, response.Body)
if err != nil {
l.Println("error occured while writing to file:", err)
return
}
// 잘 쪼개졌다면 각 left, right을 stt 돌리기
pcmResult, folderName := devideWavTo2Pcm(fileName)
if pcmResult {
sttCallRes, err := controlSTT(parsedRes, folderName)
if err != nil {
l.Println("runSTT() failed with the error: ", err)
}
// stt 콜이 성공이라면 pcm 파일 지우기
if sttCallRes {
pcmDir := filepath.Join(cfg.Directories.PCMDirectory, st)
deletePcmFolder(pcmDir)
}
}
}
func deletePcmFolder(foldername string) (bool, *icserror.IcsError) {
fmt.Println("foldername in deletePcmFolder func: ", foldername)
if _, err := os.Stat(foldername); os.IsNotExist(err) {
l.Println("pcm folder does not exist with the dir: ", foldername) //error here
l.Println("error: ", err)
return false, icserror.ICSERRFileOpen
}
err := os.RemoveAll(foldername)
if err != nil {
l.Panicln("error occured while deleting folder: ", foldername)
return false, icserror.ICSERRWriteFile
}
l.Printf(`folder: %s has been successfully deleted`, foldername)
return true, nil
}
func devideWavTo2Pcm(fileName string) (result bool, folderName string) {
// fileName: /home/prac/svc/icsbc/voice/wav/20250913223412.wav
fileNameWithoutWav := fileName[:len(fileName)-4]
lastSlashIdx := strings.LastIndex(fileNameWithoutWav, "/")
starttime := fileNameWithoutWav[lastSlashIdx+1:] //starttime: 20250913223412
pcmDir := cfg.Directories.PCMDirectory
starttimeDir := fmt.Sprintf("%s/%s", pcmDir, starttime)
os.MkdirAll(starttimeDir, os.ModePerm)
leftOutputFile := fmt.Sprintf(`%s/%s-left.pcm`, starttimeDir, starttime)
rightOutputFile := fmt.Sprintf(`%s/%s-right.pcm`, starttimeDir, starttime)
fmt.Println("inFile reading wav path: ", fileName)
inFile, err := os.Open(fileName)
if err != nil {
l.Println("failed to open input file: %v", err)
return false, ""
}
defer inFile.Close()
leftFile, err := os.Create(leftOutputFile)
if err != nil {
l.Println("failed to create left channel file: %v", err)
return false, ""
}
defer leftFile.Close()
rightFile, err := os.Create(rightOutputFile)
if err != nil {
l.Println("failed to create right channel file: %v", err)
return false, ""
}
defer rightFile.Close()
// Skip WAV header (44 bytes)
wavHeader := make([]byte, 44)
if _, err := inFile.Read(wavHeader); err != nil {
l.Println("failed to read WAV header: %v", err)
return false, ""
}
// Check if it's a valid WAV file
if string(wavHeader[:4]) != "RIFF" || string(wavHeader[8:12]) != "WAVE" {
l.Println("invalid WAV file format")
return false, ""
}
// Check if WAV file is stereo
numChannels := binary.LittleEndian.Uint16(wavHeader[22:24])
if numChannels != 2 {
l.Println("unsupported channel count: this function only supports stereo (2 channels)")
return false, ""
}
buf := make([]byte, 4) // 2 bytes per sample * 2 channels
for {
n, err := inFile.Read(buf)
if err == io.EOF {
break
}
if err != nil {
l.Println("failed to read from input file: %v", err)
return false, ""
}
if n < 4 {
l.Printf("unexpected sample size read: %d\n", n)
// Break or handle the case based on your needs
for i := n; i < 4; i++ {
buf[i] = 0
}
break
}
leftSample := buf[:2]
rightSample := buf[2:]
if err := binary.Write(leftFile, binary.LittleEndian, leftSample); err != nil {
l.Println("failed to write to left channel file: %v", err)
return false, ""
}
if err := binary.Write(rightFile, binary.LittleEndian, rightSample); err != nil {
l.Println("failed to write to right channel file: %v", err)
return false, ""
}
}
l.Println("WAV file split successfully")
return true, starttime
}
// server 연결, stt 호출, 연결 해제
func controlSTT(parsedRes RequestData, folderName string) (bool, *icserror.IcsError) {
pcmDirectory := cfg.Directories.PCMDirectory
pcmDirectory = filepath.Join(pcmDirectory, folderName)
// walking the file that has each left and right pcm files
filepath.Walk(pcmDirectory, func(path string, info os.FileInfo, err error) error {
if err != nil {
l.Println("Error occured while walking pcm folder. error: ", err)
l.Println("The pcm file path: ", pcmDirectory)
return err
}
if !info.IsDir() && filepath.Ext(path) == "left.pcm" {
stterr := connectSelvasServerRunSTT(parsedRes, path, "left")
if stterr != nil {
l.Println("Error occured on recognizeSpeechFromPcmFile(). error: ", stterr)
return err
}
}
if !info.IsDir() && filepath.Ext(path) == "right.pcm" {
stterr := connectSelvasServerRunSTT(parsedRes, path, "right")
if stterr != nil {
l.Println("Error occured on recognizeSpeechFromPcmFile(). error: ", stterr)
return err
}
}
return nil
})
return true, nil
}
func connectSelvasServerRunSTT(parsedRes RequestData, filePath string, leftright string) *icserror.IcsError {
var sttRes NewSTTResult
var sttErr *icserror.IcsError
voicedata, err := os.ReadFile(filePath)
if err != nil {
return icserror.ICSERRCONFOpenFile
}
ip := cfg.STT.SrcIP
port, _ := strconv.Atoi(cfg.STT.Port)
callId := parsedRes.ConnID
custId := parsedRes.Ext
recordFilePath := cfg.Directories.RecDirectory
// connecting with STT server
s, sttErr := NewSTTS(ip, port, callId, custId, recordFilePath)
if sttErr != nil {
return icserror.ICSERRSTTConnectFail
} else if s != nil {
fmt.Println("STT session:", s)
}
l.Println("STT server is connected with: ", ip, ", port: ", port)
// STT 호출
sttRes, sttErr = s.SendSTT(voicedata, true, nil)
if sttErr != nil {
l.Println("calling sendSTT() on sttselvas.go has failed with error: ", sttErr)
return icserror.ICSERRSTTSendFail
}
// STT server and chanel close
s.CloseChanelAndServer()
// STT 호출 성공시 결과를 websocket, ta rest로 송신
if sttRes.Res != "" {
wssres, wsserr := webSocketSend(parsedRes, sttRes, leftright)
httpres, httperr := taRestSend(parsedRes, sttRes, s.GetReqTime(), leftright)
if wssres && httpres {
l.Println("stt results have successfully sent through both wss and http(ta)")
}
if wsserr != nil {
l.Println("sending stt result through websocket has failed with the error: ", wsserr)
}
if httperr != nil {
l.Println("sending stt result through http for ta has failed with the error: ", httperr)
}
}
return nil
}
func webSocketSend(parsedRes RequestData, sttRes NewSTTResult, leftright string) (bool, *icserror.IcsError) {
speaker := "X" // T: 상담사
if leftright == "left" {
speaker = "R" //R: 고객
}
url := "ws://192.168.0.69:8090/wss"
headers := http.Header{
"Origin": {"https://192.168.0.69"},
}
conn, _, err := websocket.DefaultDialer.Dial(url, headers)
if err != nil {
l.Println("Failed to connect to WebSocket: %v", err)
return false, icserror.ICSERRWEBSOCKETConnectFailError
}
defer conn.Close()
resData := ResponseData{
Uid: parsedRes.ConnID,
Ext: parsedRes.Ext,
SpeakerTag: speaker,
Transcripts: []Transcript{
{
Text: sttRes.Res,
StartTime: sttRes.NStart,
EndTime: sttRes.NEnd,
EndPoint: true,
},
},
}
jsonData, _ := json.Marshal(resData)
encryptedResponseBody := encry.Encrypting(jsonData)
responseBody := fmt.Sprintf(`{"data":"%s"}`, encryptedResponseBody)
err = conn.WriteMessage(websocket.TextMessage, []byte(responseBody))
if err != nil {
l.Println("failed to send msg via websocket with the err: ", err)
return false, icserror.ICSERRWEBSOCKETWriteError
} else {
l.Println("Sent the msg via websocket. message body: ", responseBody)
return true, nil
}
}
func taRestSend(parsedRes RequestData, sttRes NewSTTResult, reqTime time.Time, leftright string) (bool, *icserror.IcsError) {
dir := "T" // T: 상담사
if leftright == "left" {
dir = "R" //R: 고객
}
resData := TAMessage{
Cmd: "T",
ConnID: parsedRes.ConnID,
Tel: "", // 정보없음
Ext: parsedRes.Ext,
CallStartTime: parsedRes.StartTime,
IgGbn: "1", // 인바운드
DateTime: reqTime.Format("2006-01-02 15:04:05"),
Stt: sttRes.Res,
Dir: dir,
}
jsonData, _ := json.Marshal(resData)
encryptedRequestBody := encry.Encrypting(jsonData)
url := "https://192.168.0.69:8080/taRest.do"
method := "POST"
requestBody := fmt.Sprintf(`{"data":"%s"}`, encryptedRequestBody)
response, err := httprequest.HttpRequest(url, method, requestBody)
if err != nil {
l.Println("error occured while requesting http post for datalist:", err)
return false, icserror.ICSERRHTTPClientExcecution
}
l.Println("TA msg has been successfully sent. response: ", response)
return true, nil
}

@ -0,0 +1,727 @@
//go:build !test
// +build !test
// for STT SELVAS STT
package stt
/*
#cgo LDFLAGS: -lstdc++ -ldl ./extlib/selvasstt/SDK/LIB/c_linux/x64/libASRLIB.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 <Lvcsr_Api.h>
char* getResultData(LVCSR_DATA_RESULT* pDataResult, long long nCount) {
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("pResult : %s\n", midResult->pResult);
printf("flag : %d\n", midResult->bEngineDetectionFlag);
printf("count: %ld\n\n", midResult->nCount);
}
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);
}
long getSTTSockID(LVCSR_SOCK_HEAD sockhead) {
return sockhead.uSock;
}
*/
import "C"
import (
"fmt"
"mybatch/icserror"
"mybatch/icslog"
"runtime/debug"
"strings"
"sync"
"time"
"unsafe"
// "git.icomsys.co.kr/icomsys/voicegateway/voiceagent/icsconf"
"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
NO_USED_EPD = 0 // epd used
//USED_EPD = 1 // epd used
USED_SCORE = 0 // used off
)
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
sreserved string
trid string
errCode string
errFunName string
errMsg string
result string
reqTime time.Time
rspTime time.Time
svcReqTime time.Time
svcRspTime time.Time
sttcount int
sttStatus int
//icsstat.StatInfos
language string
}
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
}
type STTSResult struct {
result string
error *icserror.IcsError
}
type NewSTTResult struct {
Res string
NStart int
NEnd int
}
func (s STTSelvas) GetTrID() string {
return s.trid
}
// connect SELVAS STT Server
func NewSTTS(IP string, port int, callID string, custID string, filePath string) (*STTSelvas, *icserror.IcsError) {
//func NewSTTS(sid int, IP string, port int, callID string, custID string, filePath string, sreserved string, statOK bool) (*STTSelvas, *icserror.IcsError) {
l := icslog.InitializeLogger()
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", icserror.ICSERRSTTFailInit.GetError().Error(), string(debug.Stack()))
default:
l.Print(icserror.ICSERRSTTFailInit.GetError().Error())
}
}
derr = icserror.ICSERRSTTFailInit
}()
if len(IP) <= 0 || port <= 0 {
derr = icserror.ICSERRInvalidParam
return nil, derr
}
stts := STTSelvas{authCode: "LGUPlusManager", uDataSize: 1600, uEndOfSpeech: 0, IsClose: false, SpeechStatus: 0, reqTime: time.Now(), svcReqTime: time.Time{}, svcRspTime: time.Time{}, callID: callID, custID: custID, 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 = false
stts.rrData = NewRRData(960000) //60sec
csIP := C.CString(IP)
defer C.free(unsafe.Pointer(csIP))
csPort := C.long(port)
csConTimeout := C.long(CONNECT_TIMEOUT)
csReadTimeout := C.long(READ_CONNECT_TIMEOUT)
// 셀바스 API는 현재 통합통계가 있어야 동작을함
trID := uuid.New().String()
trID = strings.ReplaceAll(trID, "-", "a")
stts.trid = trID
/*
if stts.sttStatus == STTMemo {
return &stts, nil
}
*/
//svcReqTime := time.Now()
l.Printf("STT ASR_SVC_OPEN Start")
rc := C.ASR_SVC_OPEN(csIP, csPort, csConTimeout, csReadTimeout, &stts.STTInfo.LVCSR_SOCK_HEAD) // add LVCSR_SOCK_HEAD
if int(rc) == -1 {
////////////////테스트코드/////////////////////
rc = C.ASR_SVC_GET_ERROR(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("[%d] ASR_SVC_GET_ERROR Fail.. %d", int(stts.sttID), rc)
// return "", derr
} else {
l.Printf("[%d] LVCSR_ERROR_RESULT - [%d]%s", int(stts.sttID), stts.STTInfo.LVCSR_ERROR_RESULT.nErrorCode, C.GoString(&stts.STTInfo.LVCSR_ERROR_RESULT.pErrorMsg[0]))
}
l.Printf("STT ASR_SVC_OPEN Fail - rc:%d", rc)
derr = icserror.ICSERRSTTConnectTimeout
return nil, derr
} else if int(rc) == -2 {
l.Printf("STT ASR_SVC_OPEN Fail - rc:%d", rc)
////////////////테스트코드/////////////////////
rc = C.ASR_SVC_GET_ERROR(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("[%d] ASR_SVC_GET_ERROR Fail.. %d", int(stts.sttID), rc)
// return "", derr
} else {
l.Printf("[%d] LVCSR_ERROR_RESULT - [%d]%s ", int(stts.sttID), stts.STTInfo.LVCSR_ERROR_RESULT.nErrorCode, C.GoString(&stts.STTInfo.LVCSR_ERROR_RESULT.pErrorMsg[0]))
}
///////////////////////////////////////////////
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
// 통합통계
now := time.Now()
tloTime := fmt.Sprintf("%d%02d%02d%02d%02d%02d", now.Year(), int(now.Month()), now.Day(), now.Hour(), now.Minute(), now.Minute())
csTrId := C.CString(trID)
defer C.free(unsafe.Pointer(csTrId))
csCallId := C.CString(callID)
defer C.free(unsafe.Pointer(csCallId))
csTloTime := C.CString(tloTime)
defer C.free(unsafe.Pointer(csTloTime))
csCustID := C.CString(custID)
defer C.free(unsafe.Pointer(csCustID))
C.setSid(&stts.STTInfo.LVCSR_DATA_LOGINFO, csCustID, C.int(len(custID)))
C.setCallId(&stts.STTInfo.LVCSR_DATA_LOGINFO, csCallId, C.int(len(callID)))
C.setTrId(&stts.STTInfo.LVCSR_DATA_LOGINFO, csTrId, C.int(len(trID)))
C.setItemStartMessage(&stts.STTInfo.LVCSR_DATA_LOGINFO, csTloTime, C.int(len(tloTime)))
l.Printf("[%d] SET ASR_SVC_SET_LOGINFO > trID:%s, callID:%s, tloTime:%+v, custID:%s", int(stts.sttID), trID, callID, tloTime, custID)
//svcReqTime = time.Now()
rs := C.ASR_SVC_SET_LOGINFO(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_DATA_LOGINFO) // 통합통계 설정
//ljhwan
//rs = 0
if int(rs) < 0 {
l.Printf("[%d] STT ASR_SVC_SET_LOGINFO Fail Result rs:%d, LVCSR_DATA_LOGINFO: %+v", int(stts.sttID), rs, stts.STTInfo.LVCSR_DATA_LOGINFO)
////////////////테스트코드/////////////////////
rc = C.ASR_SVC_GET_ERROR(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("[%d] ASR_SVC_GET_ERROR Fail..", int(stts.sttID))
// return "", derr
} else {
l.Printf("[%d] LVCSR_ERROR_RESULT - [%d]%s", 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 ASR_SVC_CLOS Start", int(stts.sttID))
rc = C.ASR_SVC_CLOS(&stts.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("[%d] STT ASR_SVC_CLOS Fail Result rs:%d", int(stts.sttID), rs)
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
// Channel Connect
//svcReqTime = time.Now()
l.Printf("[%d] STT ASR_SVC_RECG_OPEN Start", int(stts.sttID))
rc = C.ASR_SVC_RECG_OPEN(&stts.STTInfo.LVCSR_SOCK_HEAD) // add LVCSR_SOCK_HEAD
//ljhwan
//rc = 0
if int(rc) < 0 {
l.Printf("[%d] STT ASR_SVC_RECG_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 ASR_SVC_CLOS Start", int(stts.sttID))
rc = C.ASR_SVC_CLOS(&stts.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("[%d]STT ASR_SVC_CLOS Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v", int(stts.sttID), rs, stts.STTInfo.LVCSR_SOCK_HEAD)
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
derr = icserror.ICSERRSTTFailInit
return nil, derr
}
// 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.bEpdUsed = NO_USED_EPD
// } else {
// stts.STTInfo.LVCSR_DATA_INFO.bEpdUsed = USED_EPD
// }
stts.STTInfo.LVCSR_DATA_INFO.bScoreUsed = USED_SCORE
//svcReqTime = time.Now()
rc = C.ASR_SVC_RECG_SET_LIST(&stts.STTInfo.LVCSR_SOCK_HEAD, &stts.STTInfo.LVCSR_DATA_INFO)
//ljhwan
//rc = 0
if int(rc) < 0 {
l.Printf("[%d]STT ASR_SVC_RECG_SET_LIST Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v, stts.STTInfo.LVCSR_DATA_INFO: %+v", int(stts.sttID), rs, stts.STTInfo.LVCSR_SOCK_HEAD, stts.STTInfo.LVCSR_DATA_INFO)
// Channel Connection Close
//svcReqTime = time.Now()
l.Printf("[%d]STT ASR_SVC_RECG_CLOS Start", int(stts.sttID))
rc = C.ASR_SVC_RECG_CLOS(&stts.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("[%d]STT ASR_SVC_RECG_CLOS Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v", int(stts.sttID), rs, stts.STTInfo.LVCSR_SOCK_HEAD)
derr = icserror.ICSERRTTSNotInit
}
// Server Close
l.Printf("[%d]STT ASR_SVC_CLOS Start", int(stts.sttID))
//svcReqTime = time.Now()
rc = C.ASR_SVC_CLOS(&stts.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("[%d]STT ASR_SVC_CLOS Fail Result rs:%d, LVCSR_SOCK_HEAD: %+v", 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'", int(stts.sttID), callID, trID)
// fmt.Println("STT: Selvas STT New Connection")
return &stts, derr
}
func (s *STTSelvas) Close(save bool) (string, string, *icserror.IcsError) {
if s == nil {
return "", "", icserror.ICSERRSTTNotInit
}
l := icslog.InitializeLogger()
// conf := icsconf.GetIcsConfig()
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", icserror.ICSERRSTTFailInit.GetError().Error(), string(debug.Stack()))
default:
l.Print(icserror.ICSERRSTTFailInit.GetError().Error())
}
derr = icserror.ICSERRSTTFailInit
return
}
// derr = icserror.ICSERRSTTFailInit
}()
//l.Printf(icslog.LOG_LEVEL_WARN, s.sessionID, "[%d]STT CLOSE : %s", int(s.sttID), string(debug.Stack()))
l.Printf("Close STT[%d]. Send Audio Packet Num: %d", int(s.sttID), s.txNum)
/*
if s.handle < 0 || s.ch < 0 {
fmt.Println("selvas stt", s.ch)
return icserror.ICSERRSTTNotInit
}
*/
s.M.Lock()
s.IsClose = true
s.M.Unlock()
var localPath, URL string
if *s.RecordStart {
if save {
// aud := s.rrData.GetAudio()
// audLen := len(aud)
// 여기 수정해야함
// path, ymd, serr := icsutil.Save(aud, s.RecordFilePath, conf.AppInfo.VoiceConfig.Path, true)
// //path, ymd := Save(s.rrData.GetAudio(), s.RecordFilePath, conf.VoiceConfig.Path, true)
// if serr == nil {
// if len(path) == 0 {
// l.Printf(icslog.LOG_LEVEL_WARN, s.sessionID, "[%d]Failed to save STT voice : %s", int(s.sttID), s.RecordFilePath)
// } else {
// localPath = path
// URL = fmt.Sprintf("%s%s/%s.wav", conf.AppInfo.VoiceConfig.HTTPPath, ymd, s.RecordFilePath)
// s.RecordFilePath = ""
// l.Printf(icslog.LOG_LEVEL_INFO, s.sessionID, "[%d]Saved STT voice(%d). path: %s, URL: %s", int(s.sttID), audLen, localPath, URL)
// }
// } else {
// l.Printf(icslog.LOG_LEVEL_WARN, s.sessionID, "[%d]Failed to save STT voice(%d) : %s, %s - %s", int(s.sttID), audLen, s.RecordFilePath, conf.AppInfo.VoiceConfig.Path, serr.GetMessage())
// }
}
}
*s.RecordStart = false
// l.Printf(icslog.LOG_LEVEL_DEBUG2, s.sessionID, "[%d]STT ASR_SVC_RECG_CLOS. sock header: %+v", int(s.sttID), s.STTInfo.LVCSR_SOCK_HEAD.uSock)
//l.Printf(icslog.LOG_LEVEL_INFO, s.sessionID, "[%d] s.STTInfo.LVCSR_RECOG_RESULT Start - s.STTInfo.LVCSR_RECOG_RESULT:%+v", int(s.sttID), s.STTInfo.LVCSR_RECOG_RESULT)
rc := C.ASR_SVC_RECG_PROC_FREE(&s.STTInfo.LVCSR_RECOG_RESULT)
if int(rc) < 0 {
l.Printf("Failed to free STT result[%d]. rc: %d", int(s.sttID), rc)
if strings.Compare(s.errCode, "54000013") != 0 {
s.errCode, s.errMsg, s.errFunName = "54000010", "Fail", "ASR_SVC_RECG_PROC_FREE"
}
derr = icserror.ICSERRSTTFreeError
// s.SendStasticInfo(s.callID, s.custID, s.trid, "STT", "ASR_SVC_RECG_PROC_FREE", "54000001", "Fail", "", "", s.reqTime, time.Now(), s.sreserved, svcReqTime, time.Now())
}
// Channel Connection Close
l.Printf("Close STT channel[%d]", int(s.sttID))
rc = C.ASR_SVC_RECG_CLOS(&s.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Printf("Failed to close STT channel[%d], rc: %d", 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", "ASR_SVC_RECG_CLOS"
}
derr = icserror.ICSERRTTSNotInit
// s.SendStasticInfo(s.callID, s.custID, s.trid, "STT", "ASR_SVC_RECG_CLOS", "54000001", "Fail", "", "", s.reqTime, time.Now(), s.sreserved, svcReqTime, time.Now())
}
// Server Close
l.Printf("Close STT SVC[%d]", int(s.sttID))
rc = C.ASR_SVC_CLOS(&s.STTInfo.LVCSR_SOCK_HEAD)
//ljhwan
//rc = 0
if int(rc) < 0 {
l.Printf("Failed to close STT SVC[%d], rc: %d", int(s.sttID), rc)
derr = icserror.ICSERRTTSNotInit
if strings.Compare(s.errCode, "54000013") != 0 {
s.errCode, s.errMsg, s.errFunName = "54000012", "Fail", "ASR_SVC_CLOS"
}
// s.SendStasticInfo(s.callID, s.custID, s.trid, "STT", "ASR_SVC_CLOS", "54000001", "Fail", "", "", s.reqTime, time.Now(), s.sreserved, s.svcReqTime, time.Now())
// return derr
}
l.Printf("Closed STT[%d] sock header: %+v", int(s.sttID), s.STTInfo.LVCSR_SOCK_HEAD.uSock)
s.rrData.Clear()
l.Printf("Selvas STT Close - %d. %s", s.voiceBufCur, string(debug.Stack()))
return localPath, URL, 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, inout bool)
func (s *STTSelvas) SendSTT(voicedata []byte, final bool, cbFunc AsyncCBFunc) (NewSTTResult, *icserror.IcsError) {
l := icslog.InitializeLogger()
var res NewSTTResult
var derr *icserror.IcsError = nil
var result string
// var sendCount int
if s == nil {
derr = icserror.ICSERRTTSNotInit
l.Println("STTSelvas struct is not initialized")
return res, derr
}
// // setting the language
// cLanguage := C.CString(language)
// defer C.free(unsafe.Pointer(cLanguage))
// rc := C.ASR_SVC_SET_PARAM(&s.sttInfo.LVCSR_SOCK_HEAD, C.LVCSR_PARAM_TYPE_LANGUAGE, cLanguage)
// if rc != 0 {
// return "", icserror.ICSERRSTTLanguageSetting
// }
defer func() {
if err := recover(); err != nil {
switch v := err.(type) {
case error:
icserror.ICSERRSTTSendFail.SetError(v)
l.Printf("PANIC! %s\n%s", icserror.ICSERRSTTSendFail.GetError().Error(), string(debug.Stack()))
default:
l.Print(icserror.ICSERRSTTSendFail.GetError().Error())
}
}
derr = icserror.ICSERRSTTSendFail
}()
s.uEndOfSpeech = 1
//recording audio
if *s.RecordStart {
s.rrData.AddAudio(voicedata)
} else {
s.rrData.AddTempAudio(voicedata)
}
csUDataSize := C.long(s.uDataSize)
csUEndSpeech := C.long(s.uEndOfSpeech)
csBuff := (*C.char)(unsafe.Pointer(&voicedata))
//csBuff := (*C.char)(unsafe.Pointer(&buff1[0]))
rc := C.ASR_SVC_RECG_DATA(&s.STTInfo.LVCSR_SOCK_HEAD,
csBuff,
csUDataSize,
csUEndSpeech,
&s.STTInfo.LVCSR_EPD_INFO)
if int(rc) < 0 {
l.Printf("[%d] ASR_SVC_RECG_DATA ERROR %d", int(s.sttID), rc)
////////////////테스트코드/////////////////////
rc = C.ASR_SVC_GET_ERROR(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_ERROR_RESULT)
if int(rc) < 0 {
l.Printf("[%d] ASR_SVC_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", "ASR_SVC_RECG_DATA"
if cbFunc != nil {
cbFunc("", 99, true)
}
derr = icserror.ICSERRSTTSendFail
return res, derr
}
s.txNum++
rc = C.ASR_SVC_RECG_STR_PROC(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_RESULT)
s.svcRspTime = time.Now()
if int(rc) < 0 {
l.Printf("[%d]!!!! ASR_SVC_RECG_STR_PROC Fail - rc:%d, s.STTInfo.LVCSR_RECOG_RESULT:%+v", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_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 res, icserror.ICSERRSTTContinue // 묵음으로 처리
}
result = C.GoString(s.STTInfo.LVCSR_RECOG_RESULT.pResult)
l.Printf("STT ID[%d] result: %s, result: %p, pointer: %p", int(s.sttID), result, &result, s.STTInfo.LVCSR_RECOG_RESULT.pResult)
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)
}
// jiyounc
// return "", icserror.ICSERRSTTContinue
res = NewSTTResult{
Res: results,
NStart: int(s.STTInfo.LVCSR_DATA_RESULT.nStart),
NEnd: int(s.STTInfo.LVCSR_DATA_RESULT.nEnd),
}
return res, nil
}
// result return
func NewSTTSResult(result string, err *icserror.IcsError) *STTSResult {
return &STTSResult{result, err}
}
// 말을 하지 않았을때 결과 조회
func (s *STTSelvas) GetSTTResultToStopSTT() (string, *icserror.IcsError) {
l := icslog.InitializeLogger()
if s == nil {
return "", icserror.ICSERRSTTNotInit
}
l.Printf("[%d] LVCSR_RECOG_RESULT: %+v, LVCSR_RECOG_RESULT:%+v", int(s.sttID), &s.STTInfo.LVCSR_RECOG_RESULT, s.STTInfo.LVCSR_RECOG_RESULT)
rc := C.ASR_SVC_RECG_STR_PROC(&s.STTInfo.LVCSR_SOCK_HEAD, &s.STTInfo.LVCSR_RECOG_RESULT)
if int(rc) < 0 {
l.Printf("[%d] ASR_SVC_RECG_STR_PROC Fail - rc:%d, s.STTInfo.LVCSR_RECOG_RESULT:%+v", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_RESULT)
s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "ASR_SVC_RECG_STR_PROC"
// 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) {
l := icslog.InitializeLogger()
var derr *icserror.IcsError = nil
if s == nil {
return "", icserror.ICSERRSTTNotInit
}
// buff1 := make([]byte, 0)
s.uEndOfSpeech = 1
uDataSize := 0
csUDataSize := C.long(uDataSize)
csUEndSpeech := C.long(s.uEndOfSpeech)
// csBuff := nil
l.Printf("[%d] LVCSR_RECOG_RESULT: %+v, LVCSR_RECOG_RESULT:%+v", int(s.sttID), &s.STTInfo.LVCSR_RECOG_RESULT, s.STTInfo.LVCSR_RECOG_RESULT)
// svcReqTime := time.Now()
rc := C.ASR_SVC_RECG_DATA(&s.STTInfo.LVCSR_SOCK_HEAD,
nil,
csUDataSize,
csUEndSpeech,
&s.STTInfo.LVCSR_EPD_INFO)
if int(rc) < 0 {
l.Printf("[%d] ASR_SVC_RECG_STR_PROC Fail - rc:%d, s.STTInfo.LVCSR_RECOG_RESULT:%+v", int(s.sttID), rc, s.STTInfo.LVCSR_RECOG_RESULT)
derr = icserror.ICSERRSTTSendFail
s.errCode, s.errMsg, s.errFunName = "54000009", "Fail", "ASR_SVC_RECG_STR_PROC"
// s.SendStasticInfo(s.callID, s.custID, s.trid, "STT", "ASR_SVC_RECG_DATA", "54000001", "Fail", "", "", s.reqTime, time.Now(), s.sreserved, svcReqTime, time.Now())
return "", derr
}
s.GetSTTResultToStopSTT()
// l.Print(icslog.LOG_LEVEL_INFO, s.sessionID, "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
// }
return "", nil
}
func (s STTSelvas) GetAudio() []byte {
return s.rrData.GetAudio()
}
func (s STTSelvas) GetReqTime() time.Time {
return s.reqTime
}
func (s *STTSelvas) CloseChanelAndServer() (bool, *icserror.IcsError) {
// 서버 결과에 사용된 메모리 초기화
rc := C.ASR_SVC_RECG_PROC_FREE(&s.STTInfo.LVCSR_RECOG_RESULT)
if int(rc) < 0 {
l.Println("Error occured while executing ASR_SVC_RECG_PROC_FREE()")
return false, icserror.ICSERRSTTConnectCloseFail
}
// 채널 해제
rc = C.ASR_SVC_RECG_CLOS(&s.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Println("Error occured while executing ASR_SVC_RECG_CLOS()")
return false, icserror.ICSERRSTTConnectCloseFail
}
// stt 서버 종료
rc = C.ASR_SVC_CLOS(&s.STTInfo.LVCSR_SOCK_HEAD)
if int(rc) < 0 {
l.Println("Error occured while executing ASR_SVC_CLOS()")
return false, icserror.ICSERRSTTConnectCloseFail
}
s.rrData.Clear()
return true, nil
}
Loading…
Cancel
Save