@ -1,4 +1,4 @@
package stt
package ics stt
import (
import (
"encoding/binary"
"encoding/binary"
@ -6,42 +6,18 @@ import (
"fmt"
"fmt"
"io"
"io"
"log"
"log"
"net/http"
"os"
"os"
"path/filepath"
"path/filepath"
"strconv"
"strconv"
"strings"
"strings"
"time"
"mybatch/icsconf"
"batchmodule/icsconf"
encry "mybatch/icsencry"
encry "batchmodule/icsencry"
"mybatch/icserror"
"batchmodule/icserror"
httprequest "mybatch/icshttp"
"batchmodule/icshttp"
"mybatch/icslog"
"batchmodule/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 {
type Transcript struct {
Text string ` json:"text" `
Text string ` json:"text" `
StartTime int ` json:"startTime" `
StartTime int ` json:"startTime" `
@ -69,52 +45,18 @@ type TAMessage struct {
}
}
var (
var (
c fg icsconf . AppInfo
c on f icsconf . AppInfo
l * log . Logger
l * log . Logger
taUrl string
)
)
func init ( ) {
func init ( ) {
c fg = icsconf . Getconfig ( )
c on f = icsconf . Getconfig ( )
l = icslog . InitializeLogger ( )
l = icslog . InitializeLogger ( )
taUrl = conf . Urls . TAUrl
}
}
func ProcessPostRequestForDataList ( ) {
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
var reqDataForVoiceFile RequestData
if len ( parsedRes . List ) > 0 {
if len ( parsedRes . List ) > 0 {
@ -140,14 +82,14 @@ func postReqForWavFileAndDownload(parsedRes RequestData) {
method := "POST"
method := "POST"
requestBody := fmt . Sprintf ( ` { "data":"%s"} ` , encryptedRequestBody )
requestBody := fmt . Sprintf ( ` { "data":"%s"} ` , encryptedRequestBody )
response , err := httprequest . HttpRequest ( url , method , requestBody )
response , err := ics http. HttpRequest ( url , method , requestBody )
if err != nil {
if err != nil {
l . Println ( "error occured while requesting http post for datalist:" , err )
l . Println ( "error occured while requesting http post for datalist:" , err )
return
return
}
}
st := parsedRes . StartTime
st := parsedRes . StartTime
wavFilePath := c fg . Directories . WAVDirectory
wavFilePath := c on f. Directories . WAVDirectory
fileName := fmt . Sprintf ( ` %s/%s .wav` , wavFilePath , st )
fileName := fmt . Sprintf ( ` %s/%s /%s .wav` , wavFilePath , st , parsedRes . ConnId )
file , err := os . Create ( fileName )
file , err := os . Create ( fileName )
if err != nil {
if err != nil {
l . Println ( "error occured while creating file:" , err )
l . Println ( "error occured while creating file:" , err )
@ -165,13 +107,13 @@ func postReqForWavFileAndDownload(parsedRes RequestData) {
pcmResult , folderName := devideWavTo2Pcm ( fileName )
pcmResult , folderName := devideWavTo2Pcm ( fileName )
if pcmResult {
if pcmResult {
sttCallRes , err := c ontrolSTT( parsedRes , folderName )
sttCallRes , err := C ontrolSTT( parsedRes , folderName )
if err != nil {
if err != nil {
l . Println ( "runSTT() failed with the error: " , err )
l . Println ( "runSTT() failed with the error: " , err )
}
}
// stt 콜이 성공이라면 pcm 파일 지우기
// stt 콜이 성공이라면 pcm 파일 지우기
if sttCallRes {
if sttCallRes {
pcmDir := filepath . Join ( c fg . Directories . PCMDirectory , st )
pcmDir := filepath . Join ( c on f. Directories . PCMDirectory , st )
deletePcmFolder ( pcmDir )
deletePcmFolder ( pcmDir )
}
}
@ -199,7 +141,7 @@ func devideWavTo2Pcm(fileName string) (result bool, folderName string) {
fileNameWithoutWav := fileName [ : len ( fileName ) - 4 ]
fileNameWithoutWav := fileName [ : len ( fileName ) - 4 ]
lastSlashIdx := strings . LastIndex ( fileNameWithoutWav , "/" )
lastSlashIdx := strings . LastIndex ( fileNameWithoutWav , "/" )
starttime := fileNameWithoutWav [ lastSlashIdx + 1 : ] //starttime: 20250913223412
starttime := fileNameWithoutWav [ lastSlashIdx + 1 : ] //starttime: 20250913223412
pcmDir := c fg . Directories . PCMDirectory
pcmDir := c on f. Directories . PCMDirectory
starttimeDir := fmt . Sprintf ( "%s/%s" , pcmDir , starttime )
starttimeDir := fmt . Sprintf ( "%s/%s" , pcmDir , starttime )
os . MkdirAll ( starttimeDir , os . ModePerm )
os . MkdirAll ( starttimeDir , os . ModePerm )
@ -289,30 +231,28 @@ func devideWavTo2Pcm(fileName string) (result bool, folderName string) {
return true , starttime
return true , starttime
}
}
// server 연결, stt 호출, 연결 해제
func STTController ( reqDataForVoiceFile icshttp . FailedDataListReqBody , folderName string ) ( bool , * icserror . IcsError ) {
func controlSTT ( parsedRes RequestData , folderName string ) ( bool , * icserror . IcsError ) {
pcmDirectory := conf . Directories . PCMDirectory
pcmDirectory := cfg . Directories . PCMDirectory
pcmDirectory = filepath . Join ( pcmDirectory , folderName )
pcmDirectory = filepath . Join ( pcmDirectory , folderName )
// walking the file that has each left and right pcm files
// walking the file that has each left and right pcm files
filepath . Walk ( pcmDirectory , func ( path string , info os . FileInfo , err error ) error {
filepath . Walk ( pcmDirectory , func ( path string , info os . FileInfo , err error ) error {
if err != nil {
if err != nil {
l . Println ( "Error occured while walking pcm folder. error: " , err )
l . Printf ( "[ERR] sttcontroller>ControlSTT()> filepath.Walk() failed. pcmDirectory: %s" , pcmDirectory )
l . Println ( "The pcm file path: " , pcmDirectory )
return err
return err
}
}
if ! info . IsDir ( ) && filepath . Ext ( path ) == "left.pcm" {
if ! info . IsDir ( ) && filepath . Ext ( path ) == "left.pcm" {
stterr := connectSelvasServerRunSTT ( parsedRes , path , "left" )
stterr := connectSelvasServerRunSTT ( reqDataForVoiceFile , path , "left" )
if stterr != nil {
if stterr != nil {
l . Println ( " Error occured on recognizeSpeechFromPcmFile (). error: ", stterr )
l . Println ( " [ERR] sttcontroller>ControlSTT()> connectSelvasServerRunSTT (). error: ", stterr )
return err
return stt err
}
}
}
}
if ! info . IsDir ( ) && filepath . Ext ( path ) == "right.pcm" {
if ! info . IsDir ( ) && filepath . Ext ( path ) == "right.pcm" {
stterr := connectSelvasServerRunSTT ( parsedRes , path , "right" )
stterr := connectSelvasServerRunSTT ( reqDataForVoiceFile , path , "right" )
if stterr != nil {
if stterr != nil {
l . Println ( " Error occured on recognizeSpeechFromPcmFile (). error: ", stterr )
l . Println ( " [ERR] sttcontroller>ControlSTT()> connectSelvasServerRunSTT (). error: ", stterr )
return err
return stt err
}
}
}
}
return nil
return nil
@ -320,130 +260,66 @@ func controlSTT(parsedRes RequestData, folderName string) (bool, *icserror.IcsEr
return true , nil
return true , nil
}
}
func connectSelvasServerRunSTT ( parsedRes RequestData , filePath string , leftright string ) * icserror . IcsError {
func connectSelvasServerRunSTT ( reqDataForVoiceFile icshttp . FailedDataListReqBody , filePath string , leftright string ) * icserror . IcsError {
var sttRes NewSTTResult
var sttErr * icserror . IcsError
voicedata , err := os . ReadFile ( filePath )
voicedata , err := os . ReadFile ( filePath )
if err != nil {
if err != nil {
return icserror . ICSERRCONFOpenFile
return icserror . ICSERRCONFOpenFile
}
}
ip := cfg . STT . SrcIP
ip := conf . STT . SrcIP
port , _ := strconv . Atoi ( cfg . STT . Port )
port , _ := strconv . Atoi ( conf . STT . Port )
callId := parsedRes . ConnID
custId := parsedRes . Ext
connId := reqDataForVoiceFile . ConnId
recordFilePath := cfg . Directories . RecDirectory
ext := reqDataForVoiceFile . Ext
recordFilePath := conf . Directories . RecDirectory
dir := "R"
if strings . Contains ( leftright , "right" ) {
dir = "T"
}
// connecting with STT server
// connecting with STT server
s , sttErr := NewSTTS ( ip , port , callId , custId , recordFilePath )
s , sttErr := NewSTTS short ( ip , port , c onnId, recordFilePath , isRx , true )
if sttErr != nil {
if sttErr != nil {
l . Printf ( "sttcontroller>connectSelvasServerRunSTT> Failed to initialize Selvas STT connId(%s) - error: %s" , connId , sttErr . GetMessage ( ) )
return icserror . ICSERRSTTConnectFail
return icserror . ICSERRSTTConnectFail
} else if s != nil {
fmt . Println ( "STT session:" , s )
}
}
l . Print ln( "STT server is connected with: " , ip , ", port: " , port )
l . Printf ( "sttcontroller>connectSelvasServerRunSTT> Initialized Selvas STT connId(%s) - %s:%d" , connId , ip , port )
// STT 호출
// STT 호출
sttRes , sttErr = s . SendSTT ( voicedata , true , nil )
sttRes , sttErr : = s . SendSTT ( voicedata , true , nil )
if sttErr != nil {
if sttErr != nil {
l . Println ( "calling sendSTT() on sttselvas.go has failed with error: " , sttErr )
l . Println ( "[ERR] sttcontroller>connectSelvasServerRunSTT> sendSTT() failed. error: " , sttErr )
s . Close ( )
return icserror . ICSERRSTTSendFail
return icserror . ICSERRSTTSendFail
}
}
// STT server and chanel close
l . Println ( "sttcontroller>connectSelvasServerRunSTT> sttRes: " , sttRes )
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 ) {
finalSTTRes , err := s . SendSTTProcGetResult ( )
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 {
if err != nil {
l . Println ( "Failed to connect to WebSocket: %v" , err )
l . Printf ( "[ERR] sttcontroller>connectSelvasServerRunSTT> SendSTTProcGetResult() Failed. error: %v" , err )
return false , icserror . ICSERRWEBSOCKETConnectFailError
}
}
defer conn . Close ( )
resData := ResponseData {
// STT server and chanel close
Uid : parsedRes . ConnID ,
err = s . Close ( )
Ext : parsedRes . Ext ,
if err != nil {
SpeakerTag : speaker ,
l . Println ( "[ERR] sttcontroller>connectSelvasServerRunSTT> s.Close() failed. err: %v" , err )
Transcripts : [ ] Transcript {
{
Text : sttRes . Res ,
StartTime : sttRes . NStart ,
EndTime : sttRes . NEnd ,
EndPoint : true ,
} ,
} ,
}
}
jsonData , _ := json . Marshal ( resData )
// STT 호출 성공시 결과를 websocket, ta로 송신
encryptedResponseBody := encry . Encrypting ( jsonData )
if finalSTTRes != "" {
l . Printf ( "[DEBUG] sttcontroller>connectSelvasServerRunSTT> taUrl: %s" , taUrl )
responseBody := fmt . Sprintf ( ` { "data":"%s"} ` , encryptedResponseBody )
err = conn . WriteMessage ( websocket . TextMessage , [ ] byte ( responseBody ) )
_ , err := icshttp . PostProcessTA ( taUrl , "E" , connId , "" , ext , "empIdSample" , "" , "" , "0" , finalSTTRes , dir , "1" )
if err != nil {
if err != nil {
l . Println ( "failed to send msg via websocket with the err: " , err )
l . Printf ( "[ERR] sttcontroller>connectSelvasServerRunSTT> PostProcessTA() got error : %v" , 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"
err = icshttp . SendSTTResToNockChiServer ( reqDataForVoiceFile , finalSTTRes , dir )
method := "POST"
requestBody := fmt . Sprintf ( ` { "data":"%s"} ` , encryptedRequestBody )
response , err := httprequest . HttpRequest ( url , method , requestBody )
if err != nil {
if err != nil {
l . Println ( "error occured while requesting http post for datalist:" , err )
l . Printf ( "[ERR] sttcontroller>connectSelvasServerRunSTT> SendSTTResToNockChiServer() got error : %v" , err )
return false , icserror . ICSERRHTTPClientExcecution
}
}
l . Println ( "TA msg has been successfully sent. response: " , response )
}
return true, nil
return nil
}
}