From c1cc8dd832a1e9605f0ce49b4573f6d4dc9978f3 Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 4 Sep 2025 19:48:38 +0000 Subject: [PATCH] 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. --- internal/audio/api.go | 18 ------ internal/audio/input_supervisor.go | 97 +----------------------------- main.go | 11 +--- 3 files changed, 2 insertions(+), 124 deletions(-) diff --git a/internal/audio/api.go b/internal/audio/api.go index e813fd85..5d9fe5fa 100644 --- a/internal/audio/api.go +++ b/internal/audio/api.go @@ -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() -} diff --git a/internal/audio/input_supervisor.go b/internal/audio/input_supervisor.go index 0d709f63..509f4e6f 100644 --- a/internal/audio/input_supervisor.go +++ b/internal/audio/input_supervisor.go @@ -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 diff --git a/main.go b/main.go index bfd228c9..0245ae4f 100644 --- a/main.go +++ b/main.go @@ -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