refactor(audio): remove audio input subprocess pre-warming feature

The pre-warming feature was removed to simplify the audio input supervisor implementation. This feature added complexity and was not providing significant latency improvements in practice.
This commit is contained in:
Alex P 2025-09-04 19:48:38 +00:00
parent c40459664f
commit c1cc8dd832
3 changed files with 2 additions and 124 deletions

View File

@ -84,21 +84,3 @@ func GetAudioInputSupervisor() *AudioInputSupervisor {
}
return (*AudioInputSupervisor)(ptr)
}
// PrewarmAudioInputSubprocess starts an audio input subprocess in advance to reduce activation latency
func PrewarmAudioInputSubprocess() error {
supervisor := GetAudioInputSupervisor()
if supervisor == nil {
return nil // No supervisor available, skip prewarming
}
return supervisor.PrewarmSubprocess()
}
// IsAudioInputSubprocessPrewarmed returns whether an audio input subprocess is prewarmed and ready
func IsAudioInputSubprocessPrewarmed() bool {
supervisor := GetAudioInputSupervisor()
if supervisor == nil {
return false
}
return supervisor.IsPrewarmed()
}

View File

@ -21,10 +21,6 @@ type AudioInputSupervisor struct {
// Environment variables for OPUS configuration
opusEnv []string
// Pre-warming state
prewarmed bool
prewarmTime time.Time
}
// NewAudioInputSupervisor creates a new audio input supervisor
@ -52,72 +48,7 @@ func (ais *AudioInputSupervisor) SetOpusConfig(bitrate, complexity, vbr, signalT
}
}
// PrewarmSubprocess starts a subprocess in advance to reduce activation latency
func (ais *AudioInputSupervisor) PrewarmSubprocess() error {
ais.mutex.Lock()
defer ais.mutex.Unlock()
// Don't prewarm if already running or prewarmed
if ais.IsRunning() || ais.prewarmed {
return nil
}
// Check for existing audio input server process first
if existingPID, err := ais.findExistingAudioInputProcess(); err == nil {
ais.logger.Info().Int("existing_pid", existingPID).Msg("Found existing audio input server process for prewarming")
ais.prewarmed = true
ais.prewarmTime = time.Now()
return nil
}
// Create context for subprocess management
ais.createContext()
// Get current executable path
execPath, err := os.Executable()
if err != nil {
return fmt.Errorf("failed to get executable path: %w", err)
}
// Build command arguments (only subprocess flag)
args := []string{"--audio-input-server"}
// Create command for audio input server subprocess
cmd := exec.CommandContext(ais.ctx, execPath, args...)
// Set environment variables for IPC and OPUS configuration
env := append(os.Environ(), "JETKVM_AUDIO_INPUT_IPC=true") // Enable IPC mode
env = append(env, ais.opusEnv...) // Add OPUS configuration
cmd.Env = env
// Set process group to allow clean termination
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
ais.cmd = cmd
// Start the subprocess
err = cmd.Start()
if err != nil {
ais.cancelContext()
return fmt.Errorf("failed to prewarm audio input server process: %w", err)
}
ais.logger.Info().Int("pid", cmd.Process.Pid).Strs("args", args).Strs("opus_env", ais.opusEnv).Msg("Audio input server subprocess prewarmed")
// Add process to monitoring
ais.processMonitor.AddProcess(cmd.Process.Pid, "audio-input-server")
// Monitor the subprocess in a goroutine
go ais.monitorSubprocess()
// Mark as prewarmed
ais.prewarmed = true
ais.prewarmTime = time.Now()
return nil
}
// Start starts the audio input server subprocess
func (ais *AudioInputSupervisor) Start() error {
@ -131,16 +62,6 @@ func (ais *AudioInputSupervisor) Start() error {
return fmt.Errorf("audio input supervisor already running")
}
// Use prewarmed subprocess if available
if ais.prewarmed && ais.cmd != nil && ais.cmd.Process != nil {
ais.logger.Info().Int("pid", ais.cmd.Process.Pid).Dur("prewarm_age", time.Since(ais.prewarmTime)).Msg("Using prewarmed audio input server subprocess")
ais.setRunning(true)
ais.prewarmed = false // Reset prewarmed state
// Connect client to the server
go ais.connectClient()
return nil
}
// Check for existing audio input server process
if existingPID, err := ais.findExistingAudioInputProcess(); err == nil {
ais.logger.Info().Int("existing_pid", existingPID).Msg("Found existing audio input server process, connecting to it")
@ -201,30 +122,14 @@ func (ais *AudioInputSupervisor) Start() error {
return nil
}
// IsPrewarmed returns whether a subprocess is prewarmed and ready
func (ais *AudioInputSupervisor) IsPrewarmed() bool {
ais.mutex.RLock()
defer ais.mutex.RUnlock()
return ais.prewarmed
}
// GetPrewarmAge returns how long ago the subprocess was prewarmed
func (ais *AudioInputSupervisor) GetPrewarmAge() time.Duration {
ais.mutex.RLock()
defer ais.mutex.RUnlock()
if !ais.prewarmed {
return 0
}
return time.Since(ais.prewarmTime)
}
// Stop stops the audio input server subprocess
func (ais *AudioInputSupervisor) Stop() {
ais.mutex.Lock()
defer ais.mutex.Unlock()
// Reset prewarmed state
ais.prewarmed = false
if !ais.IsRunning() {
return

11
main.go
View File

@ -68,16 +68,7 @@ func startAudioSubprocess() error {
config.AudioQualityLowOpusDTX,
)
// Pre-warm audio input subprocess to reduce activation latency (if enabled)
if config.EnableSubprocessPrewarming {
if err := audio.PrewarmAudioInputSubprocess(); err != nil {
logger.Warn().Err(err).Msg("failed to pre-warm audio input subprocess")
} else {
logger.Info().Msg("audio input subprocess pre-warmed successfully")
}
} else {
logger.Info().Msg("audio input subprocess pre-warming disabled by configuration")
}
// Note: Audio input supervisor is NOT started here - it will be started on-demand
// when the user activates microphone input through the UI