mirror of https://github.com/jetkvm/kvm.git
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:
parent
c40459664f
commit
c1cc8dd832
|
@ -84,21 +84,3 @@ func GetAudioInputSupervisor() *AudioInputSupervisor {
|
||||||
}
|
}
|
||||||
return (*AudioInputSupervisor)(ptr)
|
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()
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,10 +21,6 @@ type AudioInputSupervisor struct {
|
||||||
|
|
||||||
// Environment variables for OPUS configuration
|
// Environment variables for OPUS configuration
|
||||||
opusEnv []string
|
opusEnv []string
|
||||||
|
|
||||||
// Pre-warming state
|
|
||||||
prewarmed bool
|
|
||||||
prewarmTime time.Time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAudioInputSupervisor creates a new audio input supervisor
|
// 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
|
// Start starts the audio input server subprocess
|
||||||
func (ais *AudioInputSupervisor) Start() error {
|
func (ais *AudioInputSupervisor) Start() error {
|
||||||
|
@ -131,16 +62,6 @@ func (ais *AudioInputSupervisor) Start() error {
|
||||||
return fmt.Errorf("audio input supervisor already running")
|
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
|
// Check for existing audio input server process
|
||||||
if existingPID, err := ais.findExistingAudioInputProcess(); err == nil {
|
if existingPID, err := ais.findExistingAudioInputProcess(); err == nil {
|
||||||
ais.logger.Info().Int("existing_pid", existingPID).Msg("Found existing audio input server process, connecting to it")
|
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
|
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
|
// Stop stops the audio input server subprocess
|
||||||
func (ais *AudioInputSupervisor) Stop() {
|
func (ais *AudioInputSupervisor) Stop() {
|
||||||
ais.mutex.Lock()
|
ais.mutex.Lock()
|
||||||
defer ais.mutex.Unlock()
|
defer ais.mutex.Unlock()
|
||||||
|
|
||||||
// Reset prewarmed state
|
|
||||||
ais.prewarmed = false
|
|
||||||
|
|
||||||
if !ais.IsRunning() {
|
if !ais.IsRunning() {
|
||||||
return
|
return
|
||||||
|
|
11
main.go
11
main.go
|
@ -68,16 +68,7 @@ func startAudioSubprocess() error {
|
||||||
config.AudioQualityLowOpusDTX,
|
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
|
// Note: Audio input supervisor is NOT started here - it will be started on-demand
|
||||||
// when the user activates microphone input through the UI
|
// when the user activates microphone input through the UI
|
||||||
|
|
Loading…
Reference in New Issue