Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/features/tui/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ export OPENAI_API_KEY=your_openai_api_key
docker agent run agent.yaml
```

Run `/speak` to start voice input. Press <kbd>Enter</kbd> to stop and send the transcribed message, or <kbd>Escape</kbd> to stop without sending it.
Run `/speak` to start voice input. Press <kbd>Enter</kbd> to finish transcription and send the message once the final text arrives. Press <kbd>Escape</kbd> to cancel without sending; text already received stays in the draft. Errors or a finalization timeout keep the draft instead of sending a partial message.

Dictation stays with the tab where it started. Switching tabs while transcription finishes keeps the text in the original draft without sending it.

### Plans Sidebar

Expand Down
26 changes: 26 additions & 0 deletions pkg/audio/capture/capture.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Package capture provides microphone capture using CoreAudio on macOS.
package capture

import "errors"

// Common sample rates.
const (
SampleRate44100 = 44100 // CD quality, used for WAV recording
SampleRate24000 = 24000 // Required by OpenAI Realtime API
)

// ErrNotSupported is returned when audio capture is unavailable on the current platform.
var ErrNotSupported = errors.New("audio capture is only supported on macOS")

// AudioHandler receives mono, 16-bit signed PCM (little-endian) audio chunks.
type AudioHandler func(data []byte)

// Capturer configures independent microphone capture runs.
type Capturer struct {
sampleRate int
}

// NewCapturer creates a capturer with the specified sample rate.
func NewCapturer(sampleRate int) *Capturer {
return &Capturer{sampleRate: sampleRate}
}
Loading
Loading