general refactor for simpler code
This commit is contained in:
@@ -157,27 +157,28 @@ func (d *Daemon) toggle() {
|
|||||||
d.pipeline = p
|
d.pipeline = p
|
||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
|
|
||||||
go d.notifier.RecordingStarted()
|
go d.notifier.Notify("Hyprvoice", "Recording Started")
|
||||||
go d.monitorPipelineErrors(p)
|
go d.monitorPipelineErrors(p)
|
||||||
|
|
||||||
case pipeline.Recording:
|
case pipeline.Recording:
|
||||||
d.stopPipeline() // aborted during recording (chunks not sent to transcriber yet)
|
d.stopPipeline() // aborted during recording (chunks not sent to transcriber yet)
|
||||||
go d.notifier.Aborted()
|
go d.notifier.Error("Recording Aborted")
|
||||||
|
|
||||||
case pipeline.Transcribing:
|
case pipeline.Transcribing:
|
||||||
d.mu.RLock()
|
d.mu.RLock()
|
||||||
if d.pipeline != nil {
|
if d.pipeline != nil {
|
||||||
actionChan := d.pipeline.GetActionCh()
|
actionChan := d.pipeline.GetActionCh()
|
||||||
|
log.Printf("Daemon: Sending inject action to pipeline")
|
||||||
d.mu.RUnlock()
|
d.mu.RUnlock()
|
||||||
actionChan <- pipeline.Inject
|
actionChan <- pipeline.Inject
|
||||||
} else {
|
} else {
|
||||||
d.mu.RUnlock()
|
d.mu.RUnlock()
|
||||||
}
|
}
|
||||||
go d.notifier.RecordingEnded()
|
go d.notifier.Notify("Hyprvoice", "Recording Ended... Transcribing")
|
||||||
|
|
||||||
case pipeline.Injecting:
|
case pipeline.Injecting:
|
||||||
d.stopPipeline() // aborted during injection
|
d.stopPipeline() // aborted during injection
|
||||||
go d.notifier.Aborted()
|
go d.notifier.Error("Injection Aborted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,14 +187,6 @@ func (d *Daemon) monitorPipelineErrors(p pipeline.Pipeline) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case pipelineErr := <-errorCh:
|
case pipelineErr := <-errorCh:
|
||||||
d.handlePipelineError(pipelineErr)
|
|
||||||
case <-d.ctx.Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Daemon) handlePipelineError(pipelineErr pipeline.PipelineError) {
|
|
||||||
message := pipelineErr.Message
|
message := pipelineErr.Message
|
||||||
|
|
||||||
if pipelineErr.Err != nil {
|
if pipelineErr.Err != nil {
|
||||||
@@ -201,4 +194,8 @@ func (d *Daemon) handlePipelineError(pipelineErr pipeline.PipelineError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.notifier.Error(message)
|
d.notifier.Error(message)
|
||||||
|
case <-d.ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Notifier interface {
|
type Notifier interface {
|
||||||
RecordingStarted()
|
|
||||||
RecordingEnded()
|
|
||||||
Aborted()
|
|
||||||
Transcribing()
|
|
||||||
Error(msg string)
|
Error(msg string)
|
||||||
Notify(title, message string)
|
Notify(title, message string)
|
||||||
}
|
}
|
||||||
@@ -20,21 +16,10 @@ func (d Desktop) RecordingStarted() {
|
|||||||
d.Notify("Hyprvoice", "Recording Started")
|
d.Notify("Hyprvoice", "Recording Started")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d Desktop) RecordingEnded() {
|
|
||||||
d.Notify("Hyprvoice", "Recording Ended")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Desktop) Transcribing() {
|
func (d Desktop) Transcribing() {
|
||||||
d.Notify("Hyprvoice", "Transcribing...")
|
d.Notify("Hyprvoice", "Transcribing...")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Desktop) Aborted() {
|
|
||||||
cmd := exec.Command("notify-send", "-a", "Hyprvoice", "-u", "critical", "Hyprvoice: Aborted")
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
log.Printf("Failed to send abort notification: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Desktop) Error(msg string) {
|
func (Desktop) Error(msg string) {
|
||||||
cmd := exec.Command("notify-send", "-a", "Hyprvoice", "-u", "critical", "Hyprvoice Error", msg)
|
cmd := exec.Command("notify-send", "-a", "Hyprvoice", "-u", "critical", "Hyprvoice Error", msg)
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
@@ -51,22 +36,6 @@ func (Desktop) Notify(title, message string) {
|
|||||||
|
|
||||||
type Log struct{}
|
type Log struct{}
|
||||||
|
|
||||||
func (l Log) RecordingStarted() {
|
|
||||||
l.Notify("Hyprvoice", "Recording Started")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l Log) RecordingEnded() {
|
|
||||||
l.Notify("Hyprvoice", "Recording Ended")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l Log) Transcribing() {
|
|
||||||
l.Notify("Hyprvoice", "Transcribing...")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l Log) Aborted() {
|
|
||||||
l.Notify("Hyprvoice", "Aborted")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l Log) Error(msg string) {
|
func (l Log) Error(msg string) {
|
||||||
l.Notify("Hyprvoice Error", msg)
|
l.Notify("Hyprvoice Error", msg)
|
||||||
}
|
}
|
||||||
@@ -77,9 +46,5 @@ func (Log) Notify(title, message string) {
|
|||||||
|
|
||||||
type Nop struct{}
|
type Nop struct{}
|
||||||
|
|
||||||
func (Nop) RecordingStarted() {}
|
|
||||||
func (Nop) RecordingEnded() {}
|
|
||||||
func (Nop) Aborted() {}
|
|
||||||
func (Nop) Transcribing() {}
|
|
||||||
func (Nop) Error(msg string) {}
|
func (Nop) Error(msg string) {}
|
||||||
func (Nop) Notify(title, message string) {}
|
func (Nop) Notify(title, message string) {}
|
||||||
|
|||||||
+120
-146
@@ -3,7 +3,6 @@ package pipeline
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -50,7 +49,7 @@ type pipeline struct {
|
|||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
stopOnce sync.Once
|
stopOnce sync.Once
|
||||||
|
|
||||||
running int32
|
running atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() Pipeline {
|
func New() Pipeline {
|
||||||
@@ -59,6 +58,88 @@ func New() Pipeline {
|
|||||||
errorCh: make(chan PipelineError, 10),
|
errorCh: make(chan PipelineError, 10),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (p *pipeline) Run(ctx context.Context) {
|
||||||
|
if !p.running.CompareAndSwap(false, true) {
|
||||||
|
log.Printf("Pipeline: Already running, ignoring Run() call")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
runCtx, cancel := context.WithTimeout(ctx, 5*time.Minute)
|
||||||
|
p.setCancel(cancel)
|
||||||
|
|
||||||
|
p.wg.Add(1)
|
||||||
|
go p.run(runCtx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipeline) run(ctx context.Context) {
|
||||||
|
defer func() {
|
||||||
|
p.running.Store(false)
|
||||||
|
p.setStatus(Idle)
|
||||||
|
p.wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
log.Printf("Pipeline: Starting recording")
|
||||||
|
p.setStatus(Recording)
|
||||||
|
|
||||||
|
recorder := recording.NewDefaultRecorder()
|
||||||
|
frameCh, rErrCh, err := recorder.Start(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Pipeline: Recording error: %v", err)
|
||||||
|
p.sendError("Recording Error", "Failed to start recording", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer recorder.Stop()
|
||||||
|
|
||||||
|
t, err := transcriber.NewDefaultTranscriber()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Pipeline: Failed to create transcriber: %v", err)
|
||||||
|
p.sendError("Transcription Error", "Failed to create transcriber", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Pipeline: Starting transcriber")
|
||||||
|
p.setStatus(Transcribing)
|
||||||
|
|
||||||
|
tErrCh, err := t.Start(ctx, frameCh)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Pipeline: Transcriber error: %v", err)
|
||||||
|
p.sendError("Transcription Error", "Failed to start transcriber", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if stopErr := t.Stop(ctx); stopErr != nil {
|
||||||
|
log.Printf("Pipeline: Error stopping transcriber: %v", stopErr)
|
||||||
|
p.sendError("Transcription Error", "Failed to stop transcriber cleanly", stopErr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-frameCh:
|
||||||
|
|
||||||
|
case action := <-p.actionCh:
|
||||||
|
switch action {
|
||||||
|
case Inject:
|
||||||
|
p.handleInjectAction(ctx, recorder, t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case err := <-tErrCh:
|
||||||
|
p.handleTranscriberError(err)
|
||||||
|
return
|
||||||
|
|
||||||
|
case err := <-rErrCh:
|
||||||
|
p.handleRecordingError(err)
|
||||||
|
return
|
||||||
|
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pipeline) Status() Status {
|
func (p *pipeline) Status() Status {
|
||||||
p.mu.RLock()
|
p.mu.RLock()
|
||||||
@@ -110,6 +191,43 @@ func (p *pipeline) sendError(title, message string, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *pipeline) handleTranscriberError(err error) {
|
||||||
|
p.sendError("Transcription Error", "Transcription processing error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipeline) handleRecordingError(err error) {
|
||||||
|
p.sendError("Recording Error", "Recording stream error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipeline) handleInjectAction(ctx context.Context, recorder *recording.Recorder, t transcriber.Transcriber) {
|
||||||
|
status := p.Status()
|
||||||
|
|
||||||
|
if status != Transcribing {
|
||||||
|
log.Printf("Pipeline: Inject action received, but not in transcribing state, ignoring")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Pipeline: Inject action received, stopping recording and finalizing transcription")
|
||||||
|
p.setStatus(Injecting)
|
||||||
|
|
||||||
|
recorder.Stop()
|
||||||
|
|
||||||
|
if err := t.Stop(ctx); err != nil {
|
||||||
|
p.sendError("Transcription Error", "Failed to stop transcriber during injection", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
transcriptionText, err := t.GetFinalTranscription()
|
||||||
|
if err != nil {
|
||||||
|
p.sendError("Transcription Error", "Failed to retrieve transcription", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("Pipeline: Final transcription text: %s", transcriptionText)
|
||||||
|
|
||||||
|
log.Printf("Pipeline: Simulating injection work")
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
log.Printf("Pipeline: Injection work done, returning to idle")
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pipeline) Stop() {
|
func (p *pipeline) Stop() {
|
||||||
p.stopOnce.Do(func() {
|
p.stopOnce.Do(func() {
|
||||||
cancel := p.getCancel()
|
cancel := p.getCancel()
|
||||||
@@ -119,147 +237,3 @@ func (p *pipeline) Stop() {
|
|||||||
})
|
})
|
||||||
p.wg.Wait()
|
p.wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pipeline) Run(ctx context.Context) {
|
|
||||||
if !atomic.CompareAndSwapInt32(&p.running, 0, 1) {
|
|
||||||
log.Printf("Pipeline: Already running, ignoring Run() call")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
runCtx, cancel := context.WithTimeout(ctx, 5*time.Minute)
|
|
||||||
p.setCancel(cancel)
|
|
||||||
|
|
||||||
p.wg.Add(1)
|
|
||||||
go p.run(runCtx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *pipeline) run(ctx context.Context) {
|
|
||||||
defer func() {
|
|
||||||
atomic.StoreInt32(&p.running, 0)
|
|
||||||
p.setStatus(Idle)
|
|
||||||
p.wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
log.Printf("Pipeline: Starting recording")
|
|
||||||
p.setStatus(Recording)
|
|
||||||
|
|
||||||
recorder := recording.NewDefaultRecorder()
|
|
||||||
frameCh, errCh, err := recorder.Start(ctx)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Pipeline: Recording error: %v", err)
|
|
||||||
p.sendError("Recording Error", "Failed to start recording", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if stopErr := recorder.Stop(); stopErr != nil {
|
|
||||||
log.Printf("Pipeline: Error stopping recorder: %v", stopErr)
|
|
||||||
p.sendError("Recording Error", "Failed to stop recorder cleanly", stopErr)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
config := transcriber.DefaultConfig()
|
|
||||||
if apiKey := os.Getenv("OPENAI_API_KEY"); apiKey != "" {
|
|
||||||
config.APIKey = apiKey
|
|
||||||
}
|
|
||||||
|
|
||||||
t, err := transcriber.NewTranscriber(config)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Pipeline: Failed to create transcriber: %v", err)
|
|
||||||
p.sendError("Transcription Error", "Failed to create transcriber", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Pipeline: Starting transcriber")
|
|
||||||
p.setStatus(Transcribing)
|
|
||||||
|
|
||||||
tErrCh, err := t.Start(ctx, frameCh)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Pipeline: Transcriber error: %v", err)
|
|
||||||
p.sendError("Transcription Error", "Failed to start transcriber", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if stopErr := t.Stop(ctx); stopErr != nil {
|
|
||||||
log.Printf("Pipeline: Error stopping transcriber: %v", stopErr)
|
|
||||||
p.sendError("Transcription Error", "Failed to stop transcriber cleanly", stopErr)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
frameCount := 0
|
|
||||||
totalBytes := 0
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case frame := <-frameCh:
|
|
||||||
frameCount++
|
|
||||||
totalBytes += len(frame.Data)
|
|
||||||
// log.Printf("Pipeline: Received frame #%d - Size: %d bytes, Timestamp: %v, Total bytes so far: %d", frameCount, len(frame.Data), frame.Timestamp.Format("15:04:05.000"), totalBytes)
|
|
||||||
|
|
||||||
case err := <-tErrCh:
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Pipeline: Transcription error: %v", err)
|
|
||||||
p.sendError("Transcription Error", "Transcription processing error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case err := <-errCh:
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Pipeline: Recording error: %v", err)
|
|
||||||
p.sendError("Recording Error", "Recording stream error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case action := <-p.actionCh:
|
|
||||||
log.Printf("Pipeline: Received action: %v", action)
|
|
||||||
switch action {
|
|
||||||
case Inject:
|
|
||||||
if p.status != Transcribing {
|
|
||||||
log.Printf("Pipeline: Inject action received, but not in transcribing state, ignoring")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Pipeline: Inject action received, stopping recording and finalizing transcription")
|
|
||||||
p.setStatus(Injecting)
|
|
||||||
|
|
||||||
// Stop the recorder first - this will close the frameCh channel
|
|
||||||
if err := recorder.Stop(); err != nil {
|
|
||||||
log.Printf("Pipeline: Error stopping recorder: %v", err)
|
|
||||||
p.sendError("Recording Error", "Failed to stop recorder during injection", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the recorder to fully stop and frameCh to be closed
|
|
||||||
// The transcriber will process any remaining frames when frameCh closes
|
|
||||||
// Drain the frameCh to ensure it's fully closed
|
|
||||||
for range frameCh {
|
|
||||||
// Continue draining until channel is closed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop the transcriber to ensure all buffered audio is processed
|
|
||||||
if err := t.Stop(ctx); err != nil {
|
|
||||||
log.Printf("Pipeline: Error stopping transcriber: %v", err)
|
|
||||||
p.sendError("Transcription Error", "Failed to stop transcriber during injection", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now get the final transcription which includes all processed audio
|
|
||||||
transcriptionText, err := t.GetTranscription()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Pipeline: Error getting transcription: %v", err)
|
|
||||||
p.sendError("Transcription Error", "Failed to retrieve transcription", err)
|
|
||||||
} else {
|
|
||||||
log.Printf("Pipeline: Final transcription text: %s", transcriptionText)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Pipeline: Simulating injection work")
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
log.Printf("Pipeline: Injection work done, returning to idle")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-ctx.Done():
|
|
||||||
log.Printf("Pipeline: Context cancelled, stopping")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -87,21 +87,14 @@ func (r *Recorder) Start(ctx context.Context) (<-chan AudioFrame, <-chan error,
|
|||||||
return frameCh, errCh, nil
|
return frameCh, errCh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Recorder) Stop() error {
|
func (r *Recorder) Stop() {
|
||||||
if !r.recording.Load() {
|
if !r.recording.Load() {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r.mu.Lock()
|
r.requestCancel()
|
||||||
cancel := r.cancel
|
|
||||||
r.cancel = nil
|
|
||||||
r.mu.Unlock()
|
|
||||||
|
|
||||||
if cancel != nil {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
r.wg.Wait()
|
r.wg.Wait()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Recorder) captureLoop(ctx context.Context, frameCh chan<- AudioFrame, errCh chan<- error) {
|
func (r *Recorder) captureLoop(ctx context.Context, frameCh chan<- AudioFrame, errCh chan<- error) {
|
||||||
@@ -110,12 +103,7 @@ func (r *Recorder) captureLoop(ctx context.Context, frameCh chan<- AudioFrame, e
|
|||||||
close(errCh)
|
close(errCh)
|
||||||
r.recording.Store(false)
|
r.recording.Store(false)
|
||||||
|
|
||||||
// Ensure any child process is reaped.
|
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
if r.cmd != nil {
|
|
||||||
_ = r.cmd.Wait()
|
|
||||||
r.cmd = nil
|
|
||||||
}
|
|
||||||
r.cancel = nil
|
r.cancel = nil
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ func (t *SimpleTranscriber) Stop(ctx context.Context) error {
|
|||||||
return t.transcribeAll(ctx)
|
return t.transcribeAll(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *SimpleTranscriber) GetTranscription() (string, error) {
|
func (t *SimpleTranscriber) GetFinalTranscription() (string, error) {
|
||||||
t.transcriptionMu.RLock()
|
t.transcriptionMu.RLock()
|
||||||
defer t.transcriptionMu.RUnlock()
|
defer t.transcriptionMu.RUnlock()
|
||||||
return t.transcriptionText, nil
|
return t.transcriptionText, nil
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package transcriber
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/leonardotrapani/hyprvoice/internal/recording"
|
"github.com/leonardotrapani/hyprvoice/internal/recording"
|
||||||
)
|
)
|
||||||
@@ -11,7 +12,7 @@ import (
|
|||||||
type Transcriber interface {
|
type Transcriber interface {
|
||||||
Start(ctx context.Context, frameCh <-chan recording.AudioFrame) (<-chan error, error)
|
Start(ctx context.Context, frameCh <-chan recording.AudioFrame) (<-chan error, error)
|
||||||
Stop(ctx context.Context) error
|
Stop(ctx context.Context) error
|
||||||
GetTranscription() (string, error)
|
GetFinalTranscription() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapter interface for different transcription backends
|
// Adapter interface for different transcription backends
|
||||||
@@ -59,3 +60,12 @@ func NewTranscriber(config Config) (Transcriber, error) {
|
|||||||
|
|
||||||
return transcriber, nil
|
return transcriber, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDefaultTranscriber() (Transcriber, error) {
|
||||||
|
config := DefaultConfig()
|
||||||
|
if apiKey := os.Getenv("OPENAI_API_KEY"); apiKey != "" {
|
||||||
|
config.APIKey = apiKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewTranscriber(config)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user