diff --git a/public/config.json b/public/config.json index 3072057..acdc552 100644 --- a/public/config.json +++ b/public/config.json @@ -54,6 +54,9 @@ "chatbox": { "default_open": true }, + "audio": { + "enable_audio_capture_for_screen_sharing": false + }, "templates": { "custom_instructions": "" } diff --git a/src/components/settings/sections/BehaviorSettings.tsx b/src/components/settings/sections/BehaviorSettings.tsx index 555680c..82fa4c5 100644 --- a/src/components/settings/sections/BehaviorSettings.tsx +++ b/src/components/settings/sections/BehaviorSettings.tsx @@ -3,6 +3,7 @@ import { ConfigManager } from '../../../core/config/ConfigManager'; const BehaviorSettings: React.FC = () => { const [chatboxDefaultOpen, setChatboxDefaultOpen] = useState(true); + const [enableAudioCapture, setEnableAudioCapture] = useState(false); const configManager = ConfigManager.instance(); @@ -14,6 +15,7 @@ const BehaviorSettings: React.FC = () => { } setChatboxDefaultOpen((configManager.get('chatbox.default_open') as boolean) ?? true); + setEnableAudioCapture((configManager.get('audio.enable_audio_capture_for_screen_sharing') as boolean) ?? false); }; loadConfig(); @@ -26,6 +28,12 @@ const BehaviorSettings: React.FC = () => { await configManager.set('chatbox.default_open', boolValue); }; + const handleEnableAudioCaptureChange = async (value: string) => { + const boolValue = value === 'yes'; + setEnableAudioCapture(boolValue); + await configManager.set('audio.enable_audio_capture_for_screen_sharing', boolValue); + }; + return (
@@ -50,6 +58,29 @@ const BehaviorSettings: React.FC = () => {
+ +
+

Audio

+ +
+ + +
+ Restart KGStudio (refresh the page) to take effect. Enable this option when KGStudio's audio cannot be captured during screen sharing in video calls (e.g., Zoom, Teams). This creates an additional audio stream that screen capture applications can detect. +
+ It is important to make sure when screen sharing in Zoom, the "Share Sound" option is enabled. +
+
+
); diff --git a/src/core/audio-interface/KGAudioInterface.ts b/src/core/audio-interface/KGAudioInterface.ts index 79850c1..a480145 100644 --- a/src/core/audio-interface/KGAudioInterface.ts +++ b/src/core/audio-interface/KGAudioInterface.ts @@ -7,6 +7,7 @@ import * as Tone from 'tone'; import { KGAudioBus } from './KGAudioBus'; import type { InstrumentType } from '../track/KGMidiTrack'; import { KGCore } from '../KGCore'; +import { ConfigManager } from '../config/ConfigManager'; /** * KGAudioInterface - Audio engine interface for the DAW @@ -32,6 +33,10 @@ export class KGAudioInterface { // Master volume control private masterGain: Tone.Gain | null = null; + // Audio capture for screen sharing + private captureDestination: MediaStreamAudioDestinationNode | null = null; + private captureStream: MediaStream | null = null; + // Private constructor to prevent direct instantiation private constructor() { console.log("KGAudioInterface initialized"); @@ -66,6 +71,14 @@ export class KGAudioInterface { Tone.Transport.bpm.value = TIME_CONSTANTS.DEFAULT_BPM; // Default BPM Tone.Transport.timeSignature = [TIME_CONSTANTS.DEFAULT_TIME_SIGNATURE.numerator, TIME_CONSTANTS.DEFAULT_TIME_SIGNATURE.denominator]; // Default time signature + // Check config and setup audio capture if enabled + const configManager = ConfigManager.instance(); + const enableCapture = configManager.get('audio.enable_audio_capture_for_screen_sharing') as boolean; + + if (enableCapture) { + this.setupAudioCapture(); + } + this.isInitialized = true; console.log("Audio engine initialized successfully"); } catch (error) { @@ -115,6 +128,12 @@ export class KGAudioInterface { this.masterGain = null; } + // Clean up capture resources + if (this.captureDestination) { + this.captureDestination = null; + this.captureStream = null; + } + this.isInitialized = false; this.isAudioContextStarted = false; @@ -602,8 +621,27 @@ export class KGAudioInterface { return Object.keys(FLUIDR3_INSTRUMENT_MAP) as InstrumentType[]; } + public getCaptureStream(): MediaStream | null { + return this.captureStream; + } + // ===== PRIVATE UTILITY METHODS ===== + /** + * Setup audio capture for screen sharing + */ + private setupAudioCapture(): void { + if (this.masterGain && !this.captureDestination) { + this.captureDestination = Tone.getContext().createMediaStreamDestination(); + this.captureStream = this.captureDestination.stream; + + // Connect master gain to both speakers AND capture destination + this.masterGain.connect(this.captureDestination); + + console.log('Audio capture enabled for screen sharing'); + } + } + /** * Check if any tracks are currently soloed */ diff --git a/src/core/config/ConfigManager.ts b/src/core/config/ConfigManager.ts index e540827..cafde76 100644 --- a/src/core/config/ConfigManager.ts +++ b/src/core/config/ConfigManager.ts @@ -60,6 +60,9 @@ interface AppConfig { chatbox: { default_open: boolean; }; + audio: { + enable_audio_capture_for_screen_sharing: boolean; + }; templates: { custom_instructions: string; }; @@ -205,6 +208,9 @@ export class ConfigManager { chatbox: { default_open: true }, + audio: { + enable_audio_capture_for_screen_sharing: false + }, templates: { custom_instructions: '' }