Documentation
¶
Overview ¶
Package dictation implements the POST /v1/dictation/transcribe handler. It is a thin adapter around the Framework's STT router: accept audio bytes and metadata, normalize to canonical PCM via internal/server/audio, and delegate to the router. The handler has no knowledge of which provider serves the request; that's the router's job.
Wire protocol for the streaming Dictation WebSocket (GET /v1/dictation/stream/sessions/{id}/ws).
Control frames are JSON text messages with a required "type" field. Audio frames are binary messages containing raw PCM (default 16 kHz S16 mono, client → server only — the server never sends audio on this surface). The first frame a client sends must be a "start" message; after a "segment_done" the client may send another "start" to begin the next segment on the same socket (a keyboard keeps one warm connection across mic presses).
This file is deliberately free of build tags (mirroring internal/server/wyoming/wire.go) so the frame codecs are natively testable on any development host; the handler and adapter stay `//go:build linux`.
Index ¶
- Constants
- type Handler
- type Options
- type StreamAdapter
- type StreamAudioFormat
- type StreamErrorFrame
- type StreamHandler
- type StreamHandlerOptions
- type StreamPongFrame
- type StreamReadyFrame
- type StreamRouter
- type StreamSegmentDoneFrame
- type StreamSessionEndFrame
- type StreamStartFrame
- type StreamTranscriptFrame
- type StreamWord
- type Transcriber
Constants ¶
const ( StreamMsgStart = "start" StreamMsgFinalize = "finalize" StreamMsgStop = "stop" StreamMsgPing = "ping" )
Client-to-server message types.
const ( StreamMsgReady = "ready" StreamMsgTranscript = "transcript" StreamMsgSegmentDone = "segment_done" StreamMsgError = "error" StreamMsgSessionEnd = "session_end" StreamMsgPong = "pong" )
Server-to-client message types.
const ( StreamErrStartRequired = "start_required" StreamErrSegmentActive = "segment_active" StreamErrNoActiveSegment = "no_active_segment" StreamErrProviderStreamFailed = "provider_stream_failed" StreamErrProviderStreamClosed = "provider_stream_closed" StreamErrFormatUnsupported = "format_unsupported" StreamErrInvalidFrame = "invalid_frame" )
Stable error codes emitted on StreamErrorFrame. Clients switch on these, never on the human-readable message.
const ( StreamEndReasonClient = "client" StreamEndReasonIdle = "idle" StreamEndReasonMaxDuration = "max_duration" StreamEndReasonMaxAudio = "max_audio" StreamEndReasonError = "error" StreamEndReasonShutdown = "shutdown" )
Session end reasons carried on StreamSessionEndFrame.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler implements the dictation HTTP surface.
func New ¶
New constructs a Handler. The router must be non-nil; a zero maxBytes defaults to 25 MB to match the documented API contract.
type Options ¶
type Options struct {
Router Transcriber
MaxUploadMB int // request body ceiling; 0 disables the limit (discouraged)
MaxDecodedAudioSeconds int // decoded PCM duration ceiling; 0 disables the decode-duration cap
DefaultPrompt string // applied when the request does not provide a prompt
Store store.Store
ActiveTemplateIDs []string
// DefaultProviderProfileID is the server's configured Dictation primary
// (ModelSelection.Dictate.PrimaryProfileID). It is the lowest-precedence
// provider preference: explicit request override → edge-injected user
// preference → this default → the router's configured fallback order.
DefaultProviderProfileID string
}
Options configures a single handler instance.
type StreamAdapter ¶ added in v0.51.1
type StreamAdapter struct {
Session *wssession.ManagedSession
Conn *websocket.Conn
Router StreamRouter
// IdleTimeout terminates a session without any client- or provider-side
// activity. Zero disables the watchdog.
IdleTimeout time.Duration
// MaxDuration terminates a session after this wall-clock duration. Zero
// disables the hard cap.
MaxDuration time.Duration
// MaxStreamAudio caps cumulative uploaded audio (decoded duration)
// across all segments of this session. Zero disables the budget.
MaxStreamAudio time.Duration
// OnClose runs after the read pump has returned. Typically removes the
// session from the manager.
OnClose func()
// contains filtered or unexported fields
}
StreamAdapter bridges one streaming-Dictation WebSocket to the STT router's provider-native dictation streams. One adapter handles exactly one session; a session carries any number of sequential segments (one provider stream per `start`), which is how a keyboard reuses a warm socket across mic presses.
func (*StreamAdapter) Run ¶ added in v0.51.1
func (a *StreamAdapter) Run(parent context.Context)
Run blocks until the session ends. The first frame from the client MUST be a `start` frame (enforced inside the read pump).
type StreamAudioFormat ¶ added in v0.51.1
type StreamAudioFormat struct {
Encoding string `json:"encoding,omitempty"` // "linear16" (default) | "pcm16"
SampleRateHz int `json:"sample_rate_hz,omitempty"` // default 16000
Channels int `json:"channels,omitempty"` // default 1
}
StreamAudioFormat describes the binary PCM frames the client will send. Zero values normalize to SpeechKit's canonical 16 kHz S16 mono.
type StreamErrorFrame ¶ added in v0.51.1
type StreamErrorFrame struct {
Type string `json:"type"` // "error"
Code string `json:"code"`
Message string `json:"message"`
}
StreamErrorFrame reports a recoverable protocol or provider error. Unless a session_end follows, the socket stays open and the client may retry with a new "start" (or fall back to POST /v1/dictation/transcribe).
type StreamHandler ¶ added in v0.51.1
type StreamHandler struct {
// contains filtered or unexported fields
}
StreamHandler exposes the session-creation endpoint and the WS upgrade endpoint under /v1/dictation/stream/*.
func NewStreamHandler ¶ added in v0.51.1
func NewStreamHandler(opts StreamHandlerOptions) (*StreamHandler, error)
NewStreamHandler constructs the streaming handler.
func (*StreamHandler) Mount ¶ added in v0.51.1
func (h *StreamHandler) Mount(mux *http.ServeMux)
Mount wires the streaming endpoints onto mux:
POST /v1/dictation/stream/sessions — create session + mint ticket
DELETE /v1/dictation/stream/sessions/{id} — force close a session
GET /v1/dictation/stream/sessions/{id}/ws — upgrade to WebSocket with Sec-WebSocket-Protocol: ticket.<ticket>
type StreamHandlerOptions ¶ added in v0.51.1
type StreamHandlerOptions struct {
Manager *wssession.SessionManager
Router StreamRouter
// PublicURL overrides request-derived scheme/host in returned ws_url
// values (Docker/proxy deployments).
PublicURL string
AllowedOrigins []string
TrustedProxyCIDRs []string
// IdleTimeout terminates a session without any client- or provider-side
// activity. Zero defaults to 5 minutes; negative disables.
IdleTimeout time.Duration
// MaxSessionDuration hard-caps a session's wall-clock lifetime. Zero
// disables the cap.
MaxSessionDuration time.Duration
// MaxStreamAudio caps the cumulative PCM a session may upload, expressed
// as decoded audio duration. Zero disables the budget.
MaxStreamAudio time.Duration
// ReadLimit caps per-frame bytes; zero or negative falls back to 64 KiB.
ReadLimit int64
}
StreamHandlerOptions configures the streaming Dictation WebSocket surface.
type StreamPongFrame ¶ added in v0.51.1
type StreamPongFrame struct {
Type string `json:"type"` // "pong"
}
StreamPongFrame answers a client ping.
type StreamReadyFrame ¶ added in v0.51.1
type StreamReadyFrame struct {
Type string `json:"type"` // "ready"
SegmentID uint64 `json:"segment_id"`
}
StreamReadyFrame acknowledges a start frame: the provider stream is up and binary PCM may flow.
type StreamRouter ¶ added in v0.51.1
type StreamRouter interface {
StartDictationStream(ctx context.Context, opts speechkit.DictationStreamOptions, format speaker.AudioFormat) (speechkit.DictationStream, error)
HasDictationStreaming() bool
}
StreamRouter is the minimal surface the streaming handler needs from the STT router. The production implementation is `internal/router.Router`; tests provide a fake.
type StreamSegmentDoneFrame ¶ added in v0.51.1
type StreamSegmentDoneFrame struct {
Type string `json:"type"` // "segment_done"
SegmentID uint64 `json:"segment_id"`
}
StreamSegmentDoneFrame closes a segment: the provider stream is flushed and no further transcript frames will arrive for this segment_id. The client may send the next "start".
type StreamSessionEndFrame ¶ added in v0.51.1
type StreamSessionEndFrame struct {
Type string `json:"type"` // "session_end"
Reason string `json:"reason"`
}
StreamSessionEndFrame is terminal; the server closes the socket after sending it.
type StreamStartFrame ¶ added in v0.51.1
type StreamStartFrame struct {
Type string `json:"type"` // must be "start"
Language string `json:"language,omitempty"`
Model string `json:"model,omitempty"`
ProviderProfileID string `json:"provider_profile_id,omitempty"`
// InterimResults defaults to true when omitted — live partials are the
// point of this endpoint. Send false explicitly for finals-only.
InterimResults *bool `json:"interim_results,omitempty"`
EndpointingMs int `json:"endpointing_ms,omitempty"`
TurnDetection bool `json:"turn_detection,omitempty"`
Keyterms []string `json:"keyterms,omitempty"`
PromptHint string `json:"prompt_hint,omitempty"`
Diarization bool `json:"diarization,omitempty"`
Format *StreamAudioFormat `json:"format,omitempty"`
}
StreamStartFrame is the mandatory first client frame of every segment. It maps 1:1 onto the kernel's speechkit.DictationStreamOptions plus the PCM input format.
func (StreamStartFrame) AudioFormat ¶ added in v0.51.1
func (f StreamStartFrame) AudioFormat() speaker.AudioFormat
AudioFormat converts the start frame's format block into the kernel's speaker.AudioFormat, applying canonical defaults.
func (StreamStartFrame) Options ¶ added in v0.51.1
func (f StreamStartFrame) Options() speechkit.DictationStreamOptions
Options converts the start frame into kernel DictationStreamOptions.
func (StreamStartFrame) ValidFormat ¶ added in v0.51.1
func (f StreamStartFrame) ValidFormat() (ok bool, reason string)
ValidFormat reports whether the requested PCM format is one the adapter accepts, returning a stable reason string when it is not.
type StreamTranscriptFrame ¶ added in v0.51.1
type StreamTranscriptFrame struct {
Type string `json:"type"` // "transcript"
SegmentID uint64 `json:"segment_id"`
Sequence int64 `json:"sequence,omitempty"`
Text string `json:"text"`
Done bool `json:"done"`
Language string `json:"language,omitempty"`
Confidence float64 `json:"confidence,omitempty"`
Provider string `json:"provider,omitempty"`
Model string `json:"model,omitempty"`
Words []StreamWord `json:"words,omitempty"`
Speakers *speaker.DiarizationResult `json:"speakers,omitempty"`
}
StreamTranscriptFrame carries a draft (done=false) or final (done=true) transcript for the active segment. Drafts may update UI state; only finals should be committed to the target text field.
type StreamWord ¶ added in v0.51.1
type StreamWord struct {
Text string `json:"text"`
Confidence float64 `json:"confidence,omitempty"`
StartMs int64 `json:"start_ms,omitempty"`
EndMs int64 `json:"end_ms,omitempty"`
}
StreamWord is the word-level confidence entry on transcript frames. It mirrors speechkit.WordConfidence with stable snake_case JSON names.
type Transcriber ¶
type Transcriber interface {
Route(ctx context.Context, audio []byte, audioDurationSecs float64, opts stt.TranscribeOpts) (*stt.Result, error)
}
Transcriber is the minimal surface the handler needs from an STT router. The production implementation is `internal/router.Router`; tests provide a fake.