new(all): Got mic stream.

This commit is contained in:
me@rodrigorodriguez.com 2024-10-27 16:01:27 -03:00
parent 19220010c1
commit 0905970207
10 changed files with 203 additions and 23 deletions

View file

@ -36,6 +36,12 @@ const App = () => {
await recorder.startRecording();
};
const handleStopRecording = async () => {
//@ts-ignore
if (window.microphone) {
//@ts-ignore
window.stopMicrophone();
console.log('Microphone stopped');
}
setRecording(false);
const code = await recorder.stopRecording();
setBasicCode(code);
@ -58,8 +64,8 @@ const App = () => {
return (react_1.default.createElement("div", { className: "p-4 h-auto" },
react_1.default.createElement("h1", { className: "text-2xl font-bold mb-4" }, "General Bots Desktop"),
react_1.default.createElement("div", { className: "space-x-4 mb-4 h-auto" },
react_1.default.createElement("button", { className: `px-4 py-2 rounded ${recording ? 'bg-red-500' : 'bg-blue-500'} text-white`, onClick: recording ? handleStopRecording : handleStartRecording }, recording ? 'Stop Recording' : 'Start Recording'),
react_1.default.createElement("button", { className: "px-4 py-2 rounded bg-green-500 text-white", onClick: handlePlayback, disabled: !basicCode }, "Play Recording")),
react_1.default.createElement("button", { id: "startBtn", className: `px-4 py-2 rounded ${recording ? 'bg-red-500' : 'bg-blue-500'} text-white`, onClick: recording ? handleStopRecording : handleStartRecording }, recording ? 'Stop Recording' : 'Start Recording'),
react_1.default.createElement("button", { id: "stopBtn", className: "px-4 py-2 rounded bg-green-500 text-white", onClick: handlePlayback, disabled: !basicCode }, "Play Recording")),
react_1.default.createElement("div", { className: "mt-4 h-20" },
react_1.default.createElement("h2", { className: "text-xl font-bold mb-2" }, "Generated BASIC Code:"),
react_1.default.createElement("pre", { className: "h-20 min-h-100 bg-gray-100 p-2 rounded border" }, basicCode)),

42
dist/main/main.js vendored
View file

@ -59,6 +59,26 @@ function createWindow() {
preload: path.join(__dirname, '../preload/preload.js')
}
});
electron_2.ipcMain.handle('request-microphone', async () => {
try {
const stream = await mainWindow.webContents.executeJavaScript(`
(async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
return stream;
} catch (error) {
console.error('Error accessing microphone:', error);
throw error;
}
})();
`);
return stream; // Return the stream to the UserService
}
catch (error) {
console.error('Failed to get microphone stream:', error);
throw error;
}
});
mainWindow.setAutoHideMenuBar(true);
mainWindow.setMaximizable(false);
if (process.env.NODE_ENV === 'development') {
@ -69,6 +89,26 @@ function createWindow() {
mainWindow.loadFile(path.join(__dirname, '../../src/renderer/index.html'));
}
electron_2.ipcMain.handle('mouse-event', recorder.handleMouseEvent.bind(recorder));
electron_2.ipcMain.handle('request-microphone', async () => {
try {
const stream = await mainWindow.webContents.executeJavaScript(`
(async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
return stream;
} catch (error) {
console.error('Error accessing microphone:', error);
throw error;
}
})();
`);
return stream; // Return the stream to the UserService
}
catch (error) {
console.error('Failed to get microphone stream:', error);
throw error;
}
});
electron_2.ipcMain.handle('keyboard-event', recorder.handleKeyboardEvent.bind(recorder));
// Handler to capture the entire screen
electron_2.ipcMain.handle('get-screenshot', async () => {
@ -103,7 +143,6 @@ function createWindow() {
return true; // On Windows/Linux, permissions are handled by the OS
});
electron_2.ipcMain.handle('start-microphone-capture', async (event) => {
debugger;
const window = electron_2.BrowserWindow.fromWebContents(event.sender);
if (!window) {
throw new Error('No window found for this request');
@ -172,6 +211,7 @@ function sendToWindow(channel, ...args) {
async function startMicrophoneCapture(window) {
console.log('Starting microphone capture...');
try {
navigator.mediaDevices;
// Request microphone access
//@ts-ignore
const stream = await window.myApi.startMicrophone();

View file

@ -1,16 +1,21 @@
const { ipcRenderer } = require('electron');
const { contextBridge } = require('electron');
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
//@ts-nocheck
window.myApi = {
startMicrophone: () => {
alert(1);
// Initialize IPC listeners for microphone access
ipcRenderer.on('request-microphone', async () => {
if (navigator.mediaDevices) {
return navigator.mediaDevices.getUserMedia({ audio: true });
}
else {
console.error("MediaDevices API not supported");
}
// Send the microphone stream back to the renderer
//event.sender.send('microphone-stream', stream);
});
//@ts-nocheck
window.myApi = {
startMicrophone: () => {
alert(1);
},
sendMessage: (message) => {
console.log('[preload] sendMessage called with:', message);

View file

@ -116,13 +116,21 @@ class RecorderService {
throw error;
}
}
getMicrophoneStream() {
if (typeof window !== 'undefined') {
//@ts-ignore
return window.getMicrophoneStream();
}
return null;
}
async startMicrophoneCapture() {
console.log('RecorderService.startMicrophoneCapture()');
try {
this.isListeningToMicrophone = true;
electron_1.ipcRenderer.on('audio-level', this.handleAudioLevel);
electron_1.ipcRenderer.on('audio-chunk', this.handleAudioChunk);
await electron_1.ipcRenderer.invoke('start-microphone-capture');
const stream = this.getMicrophoneStream();
console.log('Got Stream');
}
catch (error) {
console.error('Failed to start microphone capture:', error);

View file

@ -10,11 +10,18 @@ const App: React.FC = () => {
const [basicCode, setBasicCode] = useState('');
const handleStartRecording = async () => {
setRecording(true);
await recorder.startRecording();
};
const handleStopRecording = async () => {
//@ts-ignore
if (window.microphone) {
//@ts-ignore
window.stopMicrophone();
console.log('Microphone stopped');
}
setRecording(false);
const code = await recorder.stopRecording();
setBasicCode(code);
@ -41,6 +48,7 @@ const App: React.FC = () => {
<div className="space-x-4 mb-4 h-auto">
<button
id="startBtn"
className={`px-4 py-2 rounded ${recording ? 'bg-red-500' : 'bg-blue-500'} text-white`}
onClick={recording ? handleStopRecording : handleStartRecording}
>
@ -48,6 +56,7 @@ const App: React.FC = () => {
</button>
<button
id="stopBtn"
className="px-4 py-2 rounded bg-green-500 text-white"
onClick={handlePlayback}
disabled={!basicCode}

View file

@ -43,8 +43,30 @@ function createWindow() {
contextIsolation: false,
preload: path.join(__dirname, '../preload/preload.js')
}
});
ipcMain.handle('request-microphone', async () => {
try {
const stream = await mainWindow.webContents.executeJavaScript(`
(async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
return stream;
} catch (error) {
console.error('Error accessing microphone:', error);
throw error;
}
})();
`);
return stream; // Return the stream to the UserService
} catch (error) {
console.error('Failed to get microphone stream:', error);
throw error;
}
});
mainWindow.setAutoHideMenuBar(true);
mainWindow. setMaximizable(false);
@ -55,6 +77,28 @@ function createWindow() {
} else {
mainWindow.loadFile(path.join(__dirname, '../../src/renderer/index.html'));
} ipcMain.handle('mouse-event', recorder.handleMouseEvent.bind(recorder));
ipcMain.handle('request-microphone', async () => {
try {
const stream = await mainWindow.webContents.executeJavaScript(`
(async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
return stream;
} catch (error) {
console.error('Error accessing microphone:', error);
throw error;
}
})();
`);
return stream; // Return the stream to the UserService
} catch (error) {
console.error('Failed to get microphone stream:', error);
throw error;
}
});
ipcMain.handle('keyboard-event', recorder.handleKeyboardEvent.bind(recorder));
@ -98,7 +142,7 @@ function createWindow() {
ipcMain.handle('start-microphone-capture', async (event) => {
debugger;
const window = BrowserWindow.fromWebContents(event.sender);
if (!window) {
throw new Error('No window found for this request');
@ -175,11 +219,12 @@ function sendToWindow(channel: string, ...args: any[]) {
window.webContents.send(channel, ...args);
}
}
async function startMicrophoneCapture(window: BrowserWindow): Promise<void> {
console.log('Starting microphone capture...');
try {
navigator.mediaDevices;
// Request microphone access
//@ts-ignore
const stream = await window.myApi.startMicrophone()

View file

@ -3,17 +3,24 @@ const { contextBridge } = require('electron');
const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
// Initialize IPC listeners for microphone access
ipcRenderer.on('request-microphone', async () => {
if (navigator.mediaDevices) {
return navigator.mediaDevices.getUserMedia({ audio: true });
} else {
console.error("MediaDevices API not supported");
}
// Send the microphone stream back to the renderer
//event.sender.send('microphone-stream', stream);
});
//@ts-nocheck
(window as any).myApi = {
startMicrophone: () => {
alert(1);
if (navigator.mediaDevices) {
return navigator.mediaDevices.getUserMedia({ audio: true });
} else {
console.error("MediaDevices API not supported");
}
},
sendMessage: (message: any) => {
console.log('[preload] sendMessage called with:', message);

View file

@ -1,12 +1,56 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>General Bots Desktop</title>
<script>var global = global || window;</script>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded', () => {
const stream = navigator.mediaDevices.getUserMedia({
audio: true,
video: false
}).then(stream => {
alert(1);
// Now you have access to the stream
window.microphone = stream;
// You can store it in a global variable
window.getMicrophoneStream = () => stream;
// Or expose it through a global function
window.stopMicrophone = () => {
stream.getTracks().forEach(track => track.stop());
window.microphone = null;
};
}).catch(error => {
console.error('Error accessing microphone:', error);
});
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
startBtn.addEventListener('click', async () => {
try {
await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
}).then(stream => {
window.microphone = stream;
console.log('Microphone started');
});
} catch (error) {
console.error('Failed to start microphone:', error);
}
});
});
</script>
<div id="root"></div>
</body>
</html>

View file

@ -3,6 +3,12 @@ import ReactDOM from 'react-dom/client';
import App from '../components/App';
console.log('[renderer] Initializing React app');
ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
).render(

View file

@ -48,13 +48,23 @@ export class RecorderService {
}
}
getMicrophoneStream(): MediaStream | null {
if (typeof window !== 'undefined') {
//@ts-ignore
return window.getMicrophoneStream();
}
return null;
}
private async startMicrophoneCapture() {
console.log('RecorderService.startMicrophoneCapture()');
try {
this.isListeningToMicrophone = true;
ipcRenderer.on('audio-level', this.handleAudioLevel);
ipcRenderer.on('audio-chunk', this.handleAudioChunk);
await ipcRenderer.invoke('start-microphone-capture');
const stream = this.getMicrophoneStream();
console.log('Got Stream');
} catch (error) {
console.error('Failed to start microphone capture:', error);
throw new Error(`Microphone initialization failed: ${error.message}`);