Files
Captioneer/src/config/config.go
T

223 lines
5.4 KiB
Go
Raw Normal View History

// Package config defines Captioneer's command-line configuration.
package config
import (
"errors"
"strings"
"time"
)
const (
CurrentConfigVersion = 1
DefaultModelsDir = "models"
DefaultVADThreshold = 0.5
DefaultOverlayFontFamily = "Sans"
MinimumOverlayFinalLifetime = 3 * time.Second
DefaultModelTimeout = 30 * time.Second
DefaultModelShutdownTimeout = 2 * time.Second
)
type Mode string
const (
ModeFixed Mode = "fixed"
ModeVAD Mode = "vad"
)
type Settings struct {
Mode Mode
ChunkDuration time.Duration
ModelsDir string
Threads int
PreviewThresholdDB float64
VADThreshold float64
ModelAutoRestart bool
ModelTimeout time.Duration
ModelShutdownTimeout time.Duration
}
func DefaultSettings() Settings {
return Settings{
Mode: ModeVAD,
ChunkDuration: time.Second,
ModelsDir: DefaultModelsDir,
Threads: 2,
PreviewThresholdDB: -45,
VADThreshold: DefaultVADThreshold,
ModelAutoRestart: true,
ModelTimeout: DefaultModelTimeout,
ModelShutdownTimeout: DefaultModelShutdownTimeout,
}
}
type OutputMode string
const (
OutputTerminal OutputMode = "terminal"
OutputOverlay OutputMode = "overlay"
OutputBoth OutputMode = "both"
)
type OverlayBackend string
const (
BackendAuto OverlayBackend = "auto"
BackendWayland OverlayBackend = "wayland"
BackendX11 OverlayBackend = "x11"
)
type OverlaySettings struct {
Backend OverlayBackend
Opacity float64
FontSize int
FontFamily string
BottomMargin int
MaxWidth int
Monitor string
FinalTimeout time.Duration
ClickThrough bool
}
func DefaultOverlaySettings() OverlaySettings {
return OverlaySettings{
Backend: BackendAuto,
Opacity: 0.90,
FontSize: 28,
FontFamily: DefaultOverlayFontFamily,
BottomMargin: 100,
MaxWidth: 1200,
Monitor: "auto",
FinalTimeout: MinimumOverlayFinalLifetime,
ClickThrough: true,
}
}
type OutputSettings struct {
Overlay bool
History bool
StdoutCaptions bool
StderrDiagnostics bool
}
type GUISettings struct {
StartCaptions bool
MainWindowAlwaysOnTop bool
}
type TranscriptLogSettings struct {
Enabled bool
Directory string
}
type AppConfig struct {
Version int
Settings Settings
Overlay OverlaySettings
Outputs OutputSettings
GUI GUISettings
TranscriptLog TranscriptLogSettings
}
func DefaultAppConfig() AppConfig {
return AppConfig{
Version: CurrentConfigVersion,
Settings: DefaultSettings(),
Overlay: DefaultOverlaySettings(),
Outputs: OutputSettings{
Overlay: true,
History: true,
StdoutCaptions: false,
StderrDiagnostics: true,
},
GUI: GUISettings{StartCaptions: true},
TranscriptLog: TranscriptLogSettings{
Directory: DefaultTranscriptDirectory(),
},
}
}
type DesktopSettings struct {
Settings
Output OutputMode
Overlay OverlaySettings
}
func (s Settings) Validate() error {
if s.Mode != ModeFixed && s.Mode != ModeVAD {
return errors.New("--mode is required and must be either fixed or vad")
}
if s.ChunkDuration <= 0 {
return errors.New("--chunk-duration must be positive")
}
if s.Threads <= 0 {
return errors.New("--threads must be positive")
}
if s.VADThreshold < 0 || s.VADThreshold > 1 {
return errors.New("--vad-threshold must be between 0 and 1")
}
if s.ModelTimeout < 0 {
return errors.New("--model-timeout cannot be negative")
}
if s.ModelShutdownTimeout <= 0 {
return errors.New("--model-shutdown-timeout must be positive")
}
return nil
}
func (s DesktopSettings) Validate() error {
if err := s.Settings.Validate(); err != nil {
return err
}
if s.Output != OutputTerminal && s.Output != OutputOverlay && s.Output != OutputBoth {
return errors.New("--output is required and must be terminal, overlay, or both")
}
return s.Overlay.Validate()
}
func (s OverlaySettings) Validate() error {
if s.Backend != BackendAuto && s.Backend != BackendWayland && s.Backend != BackendX11 {
return errors.New("--overlay-backend must be auto, wayland, or x11")
}
if s.Opacity < 0 || s.Opacity > 1 {
return errors.New("--overlay-opacity must be between 0 and 1")
}
if s.FontSize <= 0 {
return errors.New("--overlay-font-size must be positive")
}
if strings.TrimSpace(s.FontFamily) == "" {
return errors.New("--overlay-font-family cannot be empty")
}
if s.BottomMargin < 0 {
return errors.New("--overlay-bottom-margin cannot be negative")
}
if s.MaxWidth <= 0 {
return errors.New("--overlay-max-width must be positive")
}
if s.FinalTimeout < 0 {
return errors.New("--overlay-final-timeout cannot be negative")
}
if s.FinalTimeout > 0 && s.FinalTimeout < MinimumOverlayFinalLifetime {
return errors.New("--overlay-final-timeout must be zero or at least 3s")
}
if s.Monitor == "" {
return errors.New("--overlay-monitor cannot be empty")
}
return nil
}
func (c AppConfig) Validate() error {
if c.Version != CurrentConfigVersion {
return errors.New("unsupported configuration version")
}
if err := c.Settings.Validate(); err != nil {
return err
}
if err := c.Overlay.Validate(); err != nil {
return err
}
if c.TranscriptLog.Enabled && strings.TrimSpace(c.TranscriptLog.Directory) == "" {
return errors.New("caption log directory cannot be empty when logging is enabled")
}
return nil
}