voice

package
v1.62.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package voice runs the speech engines behind the assistant's voice features: whisper for speech to text and piper for text to speech. It follows the editor intelligence Docker pattern: a fixed profile registry compiled into the binary, each image built locally from an embedded build file under a content hash tag, the containers running as the cockpit's own user with their model caches as host binds under the state directory, stale containers swept at boot. An engine container stays warm behind a small HTTP API inside and stops after an idle timeout, because a cold start per utterance would pay the model load every time.

Index

Constants

View Source
const (
	ModelSettingKey = "voice-stt-model"
	VoiceSettingKey = "voice-tts-voice"
)

ModelSettingKey picks the speech to text model, VoiceSettingKey the speaking voice. Both live install wide beside the engines' own on/off keys.

Variables

This section is empty.

Functions

func CacheRoot

func CacheRoot(stateDir string) string

CacheRoot is where the engines' cache directories live, one place under the state directory this serve process owns. Resolved, because the path travels into a container as a mount. Deliberately not in the backup: the models are downloads the engines repeat, no answer of the cockpit is lost with them.

func DetectLanguage

func DetectLanguage(text string) string

DetectLanguage answers the lowercase two letter code of the language the text reads as, out of the languages the speech voices exist for. Mixed text answers the dominant one, which is the voice that reads most of it right, and text the detector cannot place falls back to English, the same fallback the engine's voice map has. The detector is trigram based and deliberately small: lingua-go would be the more accurate pick, but it embeds every language model into the binary and more than tripled it, and telling German from English does not need that.

func Detected

func Detected() bool

Detected reports whether a docker client exists on this host; the daemon's availability is the caller's docker cache, the same split the editor intelligence settings read.

Types

type Option

type Option struct {
	ID    string
	Label string
}

Option is one runtime choice of a profile: the stored id and what the settings page calls it.

type Profile

type Profile struct {
	// ID is the stable profile identifier, used by the settings key.
	ID string
	// Server is the short name this engine wears everywhere the cockpit
	// names something itself: the image, the container, the cache directory
	// and the stored settings value.
	Server string
	// Image is the local image repository the cockpit builds into.
	Image string
	// Dockerfile is the shipped build file the image is built from.
	Dockerfile string
	// Port is the fixed port the engine's HTTP API listens on inside the
	// container; the host side is an ephemeral publish on loopback.
	Port int
	// SettingKey is the settings key picking this engine's runtime option,
	// EnvVar the variable that option travels into the container in, Options
	// the fixed choices it may take and Default the one an absent or unknown
	// value reads as. The option is an id out of Options and nothing else:
	// the recipe stays compiled in, the value only selects between ways the
	// build file already knows, and the container falls back to the same
	// default for anything it does not know.
	SettingKey string
	EnvVar     string
	Options    []Option
	Default    string
}

Profile is one fixed speech engine profile compiled into the binary. The container recipe is never configurable, so no setting can become a command execution surface; a setting only picks whether the fixed way runs, or not, and which of the profile's own fixed Options it runs with.

func Piper

func Piper() *Profile

Piper is the text to speech profile.

func Whisper

func Whisper() *Profile

Whisper is the speech to text profile.

func (*Profile) Normalize

func (p *Profile) Normalize(stored string) string

Normalize answers the option id to run with: the stored value when the profile offers it, its default for everything else. Absent and unknown read as the default, so a settings file from another version never picks something this binary does not ship.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service owns the engine containers: one per profile, warmed on first use, stopped after the idle timeout and on Close. All methods are safe for concurrent use.

func New

func New(stateDir string, dockerHost func() string, setting func(key string) string, announce func(engineID string)) *Service

New builds the service. stateDir is this serve process's state directory, dockerHost answers the configured daemon, nil or empty for the ambient one, setting reads one install wide setting, nil while nothing stores any, in which case every profile runs its own default, and announce, nil for nobody listening, is told the profile id when a start is about to pay its one time costs, the image build and the model download, so the web layer can tell whoever is waiting.

func (*Service) Close

func (s *Service) Close()

Close stops the engine containers. Call on shutdown, after which the service refuses new work.

func (*Service) Option

func (s *Service) Option(p *Profile) string

Option answers the option id a profile runs with right now: the stored pick when the profile offers it, its default otherwise. The web layer renders the same answer, so what the page shows and what the container gets are one value.

func (*Service) SweepStale

func (s *Service) SweepStale()

SweepStale starts the boot sweep in the background and gates the first engine start behind it. It removes every container of the voice naming scheme labeled with this service's own state root: at serve start none of them has a living owner. The root label is the ownership boundary, so another live instance's engines on the same daemon are never touched. Call once, right after New.

func (*Service) Synthesize

func (s *Service) Synthesize(ctx context.Context, text, language string) ([]byte, error)

Synthesize runs one text through the text to speech engine and answers the spoken wav. language is the lowercase two letter code the cockpit detected; the engine maps it onto its voices and falls back to English for anything it has no voice for.

func (*Service) Transcribe

func (s *Service) Transcribe(ctx context.Context, clip []byte) (Transcript, error)

Transcribe runs one clip through the speech to text engine, warming its container when it is cold. The clip is whatever the browser recorded, webm/opus mostly and mp4/aac on Safari; the engine decodes the container format itself, so no caller has to say which it is.

type Transcript

type Transcript struct {
	Text     string
	Language string
}

Transcript is one transcription answer: the text and the language whisper detected for the utterance.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL