diff --git a/public/config.json b/public/config.json index 8d398c7..fdbb182 100644 --- a/public/config.json +++ b/public/config.json @@ -63,7 +63,8 @@ }, "audio": { "enable_audio_capture_for_screen_sharing": false, - "lookahead_time": 0.05 + "lookahead_time": 0.05, + "playback_delay": 0.2 }, "templates": { "custom_instructions": "" diff --git a/src/components/settings/sections/BehaviorSettings.tsx b/src/components/settings/sections/BehaviorSettings.tsx index 02b7b25..eed41ea 100644 --- a/src/components/settings/sections/BehaviorSettings.tsx +++ b/src/components/settings/sections/BehaviorSettings.tsx @@ -5,8 +5,10 @@ import { KGAudioInterface } from '../../../core/audio-interface/KGAudioInterface const BehaviorSettings: React.FC = () => { const [chatboxDefaultOpen, setChatboxDefaultOpen] = useState(true); const [audioLookaheadTime, setAudioLookaheadTime] = useState('50'); + const [playbackDelay, setPlaybackDelay] = useState('200'); const [enableAudioCapture, setEnableAudioCapture] = useState(false); - const [validationErrors, setValidationErrors] = useState([]); + const [lookaheadValidationErrors, setLookaheadValidationErrors] = useState([]); + const [playbackDelayValidationErrors, setPlaybackDelayValidationErrors] = useState([]); const configManager = ConfigManager.instance(); @@ -20,6 +22,8 @@ const BehaviorSettings: React.FC = () => { setChatboxDefaultOpen((configManager.get('chatbox.default_open') as boolean) ?? true); const lookaheadTimeSeconds = (configManager.get('audio.lookahead_time') as number) ?? 0.05; setAudioLookaheadTime(((lookaheadTimeSeconds * 1000).toFixed(0))); + const playbackDelaySeconds = (configManager.get('audio.playback_delay') as number) ?? 0.2; + setPlaybackDelay(((playbackDelaySeconds * 1000).toFixed(0))); setEnableAudioCapture((configManager.get('audio.enable_audio_capture_for_screen_sharing') as boolean) ?? false); }; @@ -48,7 +52,7 @@ const BehaviorSettings: React.FC = () => { errors.push('Lookahead time must be between 0 and 0.5 seconds (0-500ms)'); } - setValidationErrors(errors); + setLookaheadValidationErrors(errors); // Only apply if valid if (errors.length === 0) { @@ -63,6 +67,32 @@ const BehaviorSettings: React.FC = () => { } }; + const handlePlaybackDelayChange = async (value: string) => { + // Allow empty string, treat as 0 ms + const numValueMs = value === '' ? 0 : parseFloat(value); + const numValueSeconds = numValueMs / 1000; + const errors: string[] = []; + + // Validate the input + if (isNaN(numValueMs)) { + errors.push('Playback delay must be a valid number'); + } else if (numValueSeconds < 0) { + errors.push('Playback delay must be between 0 and 0.5 seconds (0-500ms)'); + } else if (numValueSeconds > 0.5) { + errors.push('Playback delay must be between 0 and 0.5 seconds (0-500ms)'); + } + + setPlaybackDelayValidationErrors(errors); + + // Only apply if valid + if (errors.length === 0) { + setPlaybackDelay(value); + await configManager.set('audio.playback_delay', numValueSeconds); + + console.log(`Playback delay changed to: ${numValueSeconds}s (${numValueMs}ms)`); + } + }; + const handleEnableAudioCaptureChange = async (value: string) => { const boolValue = value === 'yes'; setEnableAudioCapture(boolValue); @@ -110,9 +140,9 @@ const BehaviorSettings: React.FC = () => { max="500" step="1" /> - {validationErrors.length > 0 && ( + {lookaheadValidationErrors.length > 0 && (
- {validationErrors.map((error, index) => ( + {lookaheadValidationErrors.map((error, index) => (
{error}
@@ -124,6 +154,33 @@ const BehaviorSettings: React.FC = () => {
+
+ + handlePlaybackDelayChange(e.target.value)} + min="0" + max="500" + step="1" + /> + {playbackDelayValidationErrors.length > 0 && ( +
+ {playbackDelayValidationErrors.map((error, index) => ( +
+ {error} +
+ ))} +
+ )} +
+ Playback will start with a short delay after pressing the start button (0-500ms). Increasing this value might help stabilize playback, especially for the first few ticks if the lookahead value is too low. Changes apply immediately without restart. +
+
+