Files
ai-operator/internal/ai/stt/elevenlabs_events.go
T

59 lines
1.5 KiB
Go

package stt
import (
"encoding/json"
"strings"
"time"
)
func ParseElevenLabsEvent(data []byte) (Event, error) {
var m map[string]any
if err := json.Unmarshal(data, &m); err != nil {
return Event{}, err
}
typ := strings.ToLower(toString(m["type"]))
text := firstString(m, "text", "transcript", "partial", "final")
lang := firstString(m, "language", "language_code")
ev := Event{Text: text, Language: lang, At: time.Now().UTC(), Metadata: map[string]any{}}
switch typ {
case "partial_transcript", "partial", "transcript.partial":
ev.Type = EventPartialTranscript
case "final_transcript", "final", "transcript.final":
ev.Type = EventFinalTranscript
case "committed_transcript", "committed", "transcript.committed":
ev.Type = EventCommittedTranscript
case "speech_started", "speech.start", "vad.speech_started":
ev.Type = EventSpeechStarted
case "speech_ended", "speech.end", "vad.speech_ended":
ev.Type = EventSpeechEnded
case "error":
ev.Type = EventError
ev.Error = firstString(m, "error", "message")
case "closed":
ev.Type = EventClosed
default:
if final, _ := m["is_final"].(bool); final && text != "" {
ev.Type = EventCommittedTranscript
} else if text != "" {
ev.Type = EventPartialTranscript
}
}
return ev, nil
}
func firstString(m map[string]any, keys ...string) string {
for _, k := range keys {
if s := toString(m[k]); s != "" {
return s
}
}
return ""
}
func toString(v any) string {
if s, ok := v.(string); ok {
return s
}
return ""
}