feat: generate transcript and event-driven particle processing
This generates the transcript and shows the caption experience on the client side for media particles. It also simplifies other side effects that we must perform such as updating the `last_child_created_at` field for stream and container particles.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package speech
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
dgapi "github.com/deepgram/deepgram-go-sdk/v3/pkg/api/listen/v1/rest"
|
||||
interfaces "github.com/deepgram/deepgram-go-sdk/v3/pkg/client/interfaces"
|
||||
client "github.com/deepgram/deepgram-go-sdk/v3/pkg/client/listen"
|
||||
)
|
||||
|
||||
type TranscriptWord struct {
|
||||
Word string
|
||||
Start float64
|
||||
End float64
|
||||
}
|
||||
|
||||
type TranscriptSentence struct {
|
||||
Text string
|
||||
Start float64
|
||||
End float64
|
||||
}
|
||||
|
||||
type TranscriptParagraph struct {
|
||||
Sentences []TranscriptSentence
|
||||
Start float64
|
||||
End float64
|
||||
}
|
||||
|
||||
type TranscriptResult struct {
|
||||
Transcript string
|
||||
Words []TranscriptWord
|
||||
Paragraphs []TranscriptParagraph
|
||||
}
|
||||
|
||||
type SpeechService interface {
|
||||
Transcribe(ctx context.Context, mediaUrl string) (*TranscriptResult, error)
|
||||
}
|
||||
|
||||
type speechServiceImpl struct {
|
||||
deepgramClient *dgapi.Client
|
||||
}
|
||||
|
||||
func NewSpeechService(ctx context.Context) SpeechService {
|
||||
return &speechServiceImpl{
|
||||
deepgramClient: dgapi.New(client.NewRESTWithDefaults()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *speechServiceImpl) Transcribe(ctx context.Context, mediaUrl string) (*TranscriptResult, error) {
|
||||
options := &interfaces.PreRecordedTranscriptionOptions{
|
||||
Model: "nova-3",
|
||||
SmartFormat: true,
|
||||
Paragraphs: true,
|
||||
}
|
||||
|
||||
response, err := s.deepgramClient.FromURL(ctx, mediaUrl, options)
|
||||
if err != nil {
|
||||
slog.Error("failed to transcribe prerecorded media", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
alt := response.Results.Channels[0].Alternatives[0]
|
||||
|
||||
words := make([]TranscriptWord, len(alt.Words))
|
||||
for i, w := range alt.Words {
|
||||
words[i] = TranscriptWord{
|
||||
Word: w.PunctuatedWord,
|
||||
Start: w.Start,
|
||||
End: w.End,
|
||||
}
|
||||
}
|
||||
|
||||
var paragraphs []TranscriptParagraph
|
||||
if alt.Paragraphs != nil {
|
||||
paragraphs = make([]TranscriptParagraph, len(alt.Paragraphs.Paragraphs))
|
||||
for i, p := range alt.Paragraphs.Paragraphs {
|
||||
sentences := make([]TranscriptSentence, len(p.Sentences))
|
||||
for j, s := range p.Sentences {
|
||||
sentences[j] = TranscriptSentence{
|
||||
Text: s.Text,
|
||||
Start: s.Start,
|
||||
End: s.End,
|
||||
}
|
||||
}
|
||||
paragraphs[i] = TranscriptParagraph{
|
||||
Sentences: sentences,
|
||||
Start: p.Start,
|
||||
End: p.End,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &TranscriptResult{
|
||||
Transcript: alt.Transcript,
|
||||
Words: words,
|
||||
Paragraphs: paragraphs,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user