Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/170-electron-live-transcription-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ npm start
2. When you click **Start**, the renderer requests microphone access via `getUserMedia` at 16 kHz
3. A `ScriptProcessorNode` captures raw PCM audio and converts float32 samples to linear16
4. Audio chunks are sent to the main process via IPC (`contextBridge` + `ipcRenderer`)
5. The main process connects to Deepgram's live STT WebSocket using `client.listen.v1.live()` and forwards audio
5. The main process connects to Deepgram's live STT WebSocket using `client.listen.v1.connect()` and forwards audio
6. Transcript events (interim and final) stream back and are displayed in the overlay
7. The overlay supports click-through (`setIgnoreMouseEvents`) so it never blocks interaction with other apps
8. Use **Ctrl+Shift+T** (or **Cmd+Shift+T** on macOS) to toggle overlay visibility
Expand Down
17 changes: 10 additions & 7 deletions examples/170-electron-live-transcription-node/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ function createTray() {
}

// ── Deepgram live connection ────────────────────────────────────────────────
function startDeepgramConnection() {
async function startDeepgramConnection() {
if (dgConnection) return;

dgConnection = deepgram.listen.v1.live({
dgConnection = await deepgram.listen.v1.connect({
model: 'nova-3',
encoding: 'linear16',
sample_rate: 16000,
Expand Down Expand Up @@ -94,28 +94,31 @@ function startDeepgramConnection() {

dgConnection.on('message', (data) => {
try {
const msg = typeof data === 'string' ? JSON.parse(data) : data;
const transcript = msg?.channel?.alternatives?.[0]?.transcript;
const transcript = data?.channel?.alternatives?.[0]?.transcript;
if (transcript && overlayWindow) {
overlayWindow.webContents.send('transcript', {
text: transcript,
is_final: msg.is_final,
is_final: data.is_final,
});
}
} catch {}
});

dgConnection.connect();
await dgConnection.waitForOpen();
}

function stopDeepgramConnection() {
if (!dgConnection) return;
try { dgConnection.finish(); } catch {}
try { dgConnection.sendCloseStream({ type: 'CloseStream' }); } catch {}
try { dgConnection.close(); } catch {}
dgConnection = null;
}

// ── IPC handlers ────────────────────────────────────────────────────────────
ipcMain.on('audio-data', (_event, buffer) => {
if (dgConnection) {
try { dgConnection.send(Buffer.from(buffer)); } catch {}
try { dgConnection.sendBinary(Buffer.from(buffer)); } catch {}
}
});

Expand Down
52 changes: 26 additions & 26 deletions examples/170-electron-live-transcription-node/tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ async function testDeepgramLiveTranscription() {
console.log(`Audio ready: ${pcm16.length} bytes of linear16 16 kHz`);

// Connect to Deepgram live STT
const connection = client.listen.v1.live({
const connection = await client.listen.v1.connect({
model: 'nova-3',
encoding: 'linear16',
sample_rate: 16000,
Expand All @@ -106,38 +106,15 @@ async function testDeepgramLiveTranscription() {

connection.on('message', (data) => {
try {
const msg = typeof data === 'string' ? JSON.parse(data) : data;
const transcript = msg?.channel?.alternatives?.[0]?.transcript;
const transcript = data?.channel?.alternatives?.[0]?.transcript;
if (transcript) {
const tag = msg.is_final ? 'final' : 'interim';
const tag = data.is_final ? 'final' : 'interim';
console.log(`[${tag}] ${transcript}`);
transcripts.push(transcript);
}
} catch {}
});

connection.on('open', () => {
console.log('[deepgram] Connected — streaming audio...');

// Stream 5 seconds of audio in real-time-paced chunks
const CHUNK_BYTES = 640; // 20ms at 16kHz * 2 bytes
const MAX_BYTES = 16000 * 2 * 5; // 5 seconds
let pos = 0;

const sendChunk = () => {
if (pos >= pcm16.length || pos >= MAX_BYTES) {
console.log('[deepgram] Audio sent — waiting for final results...');
try { connection.finish(); } catch {}
return;
}
connection.send(pcm16.subarray(pos, pos + CHUNK_BYTES));
pos += CHUNK_BYTES;
setTimeout(sendChunk, 20);
};

sendChunk();
});

connection.on('close', () => {
clearTimeout(timeout);
setTimeout(() => {
Expand All @@ -161,6 +138,29 @@ async function testDeepgramLiveTranscription() {
resolve(transcripts);
}, 1000);
});

connection.connect();
connection.waitForOpen().then(() => {
console.log('[deepgram] Connected — streaming audio...');

const CHUNK_BYTES = 640;
const MAX_BYTES = 16000 * 2 * 5;
let pos = 0;

const sendChunk = () => {
if (pos >= pcm16.length || pos >= MAX_BYTES) {
console.log('[deepgram] Audio sent — waiting for final results...');
try { connection.sendCloseStream({ type: 'CloseStream' }); } catch {}
try { connection.close(); } catch {}
return;
}
connection.sendBinary(pcm16.subarray(pos, pos + CHUNK_BYTES));
pos += CHUNK_BYTES;
setTimeout(sendChunk, 20);
};

sendChunk();
}).catch(reject);
});
}

Expand Down