deepgram-core-workflow-b
Guide for real-time speech-to-text using Deepgram's WebSocket streaming API and SDK.
Install
mkdir -p .claude/skills/deepgram-core-workflow-b && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/6617" && unzip -o skill.zip -d .claude/skills/deepgram-core-workflow-b && rm skill.zipInstalls to .claude/skills/deepgram-core-workflow-b
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Implement real-time streaming transcription with Deepgram WebSocket.Key capabilities
- →Establish a WebSocket connection to Deepgram for live transcription.
- →Capture audio from a microphone using Sox and stream it to Deepgram.
- →Process and display interim and final transcription results.
- →Perform speaker diarization in real-time streaming audio.
- →Implement auto-reconnect with exponential backoff for connection stability.
How it works
This skill establishes a WebSocket connection to Deepgram, streams audio data, and receives real-time transcription results. It handles connection lifecycle events, microphone input, and advanced features like diarization and auto-reconnect.
Inputs & outputs
When to use deepgram-core-workflow-b
- →Building live transcription services
- →Developing voice interfaces
- →Implementing real-time captioning
- →Processing streaming audio for voice AI
About this skill
Deepgram Core Workflow B: Live Streaming Transcription
Overview
Real-time streaming transcription using Deepgram's WebSocket API. The SDK manages the WebSocket connection via listen.live(). Covers microphone capture, interim/final result handling, speaker diarization, UtteranceEnd detection, auto-reconnect, and building an SSE endpoint for browser clients.
Prerequisites
@deepgram/sdkinstalled,DEEPGRAM_API_KEYconfigured- Audio source: microphone (via Sox/
rec), file stream, or WebSocket audio from browser - For mic capture:
soxinstalled (apt install sox/brew install sox)
Instructions
Step 1: Basic Live Transcription
import { createClient, LiveTranscriptionEvents } from '@deepgram/sdk';
const deepgram = createClient(process.env.DEEPGRAM_API_KEY!);
const connection = deepgram.listen.live({
model: 'nova-3',
language: 'en',
smart_format: true,
punctuate: true,
interim_results: true, // Show in-progress results
utterance_end_ms: 1000, // Silence threshold for utterance end
vad_events: true, // Voice activity detection events
encoding: 'linear16', // 16-bit PCM
sample_rate: 16000, // 16 kHz
channels: 1, // Mono
});
// Connection lifecycle events
connection.on(LiveTranscriptionEvents.Open, () => {
console.log('WebSocket connected to Deepgram');
});
connection.on(LiveTranscriptionEvents.Close, () => {
console.log('WebSocket closed');
});
connection.on(LiveTranscriptionEvents.Error, (err) => {
console.error('Deepgram error:', err);
});
// Transcript events
connection.on(LiveTranscriptionEvents.Transcript, (data) => {
const transcript = data.channel.alternatives[0]?.transcript;
if (!transcript) return;
if (data.is_final) {
console.log(`[FINAL] ${transcript}`);
} else {
process.stdout.write(`\r[interim] ${transcript}`);
}
});
// UtteranceEnd — fires when speaker pauses
connection.on(LiveTranscriptionEvents.UtteranceEnd, () => {
console.log('\n--- utterance end ---');
});
Step 2: Microphone Capture with Sox
import { spawn } from 'child_process';
function startMicrophone(connection: any) {
// Sox captures from default mic: 16kHz, 16-bit signed LE, mono
const mic = spawn('rec', [
'-q', // Quiet (no progress)
'-r', '16000', // Sample rate
'-e', 'signed', // Encoding
'-b', '16', // Bit depth
'-c', '1', // Mono
'-t', 'raw', // Raw PCM output
'-', // Output to stdout
]);
mic.stdout.on('data', (chunk: Buffer) => {
if (connection.getReadyState() === 1) { // WebSocket.OPEN
connection.send(chunk);
}
});
mic.on('error', (err) => {
console.error('Microphone error:', err.message);
console.log('Install sox: apt install sox / brew install sox');
});
return mic;
}
// Usage
const mic = startMicrophone(connection);
// Graceful shutdown
process.on('SIGINT', () => {
mic.kill();
connection.finish(); // Sends CloseStream message, waits for final results
setTimeout(() => process.exit(0), 2000);
});
Step 3: Live Diarization
const connection = deepgram.listen.live({
model: 'nova-3',
smart_format: true,
diarize: true,
interim_results: false, // Only final for cleaner diarization
utterance_end_ms: 1500,
encoding: 'linear16',
sample_rate: 16000,
channels: 1,
});
connection.on(LiveTranscriptionEvents.Transcript, (data) => {
if (!data.is_final) return;
const words = data.channel.alternatives[0]?.words ?? [];
if (words.length === 0) return;
// Group consecutive words by speaker
let currentSpeaker = words[0].speaker;
let segment = '';
for (const word of words) {
if (word.speaker !== currentSpeaker) {
console.log(`Speaker ${currentSpeaker}: ${segment.trim()}`);
currentSpeaker = word.speaker;
segment = '';
}
segment += ` ${word.punctuated_word ?? word.word}`;
}
console.log(`Speaker ${currentSpeaker}: ${segment.trim()}`);
});
Step 4: Auto-Reconnect with Backoff
class ReconnectingLiveTranscription {
private client: ReturnType<typeof createClient>;
private connection: any = null;
private reconnectAttempts = 0;
private maxReconnectAttempts = 10;
private baseDelay = 1000;
constructor(apiKey: string, private options: Record<string, any>) {
this.client = createClient(apiKey);
}
connect() {
this.connection = this.client.listen.live(this.options);
this.connection.on(LiveTranscriptionEvents.Open, () => {
console.log('Connected');
this.reconnectAttempts = 0; // Reset on success
});
this.connection.on(LiveTranscriptionEvents.Close, () => {
this.scheduleReconnect();
});
this.connection.on(LiveTranscriptionEvents.Error, (err: Error) => {
console.error('Connection error:', err.message);
this.scheduleReconnect();
});
return this.connection;
}
private scheduleReconnect() {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.error('Max reconnection attempts reached');
return;
}
const delay = this.baseDelay * Math.pow(2, this.reconnectAttempts)
+ Math.random() * 1000; // Jitter
this.reconnectAttempts++;
console.log(`Reconnecting in ${Math.round(delay)}ms (attempt ${this.reconnectAttempts})`);
setTimeout(() => this.connect(), delay);
}
send(chunk: Buffer) {
if (this.connection?.getReadyState() === 1) {
this.connection.send(chunk);
}
}
close() {
this.maxReconnectAttempts = 0; // Prevent reconnect
this.connection?.finish();
}
}
Step 5: SSE Endpoint for Browser Clients
import express from 'express';
import { createClient, LiveTranscriptionEvents } from '@deepgram/sdk';
const app = express();
app.get('/api/transcribe/stream', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const deepgram = createClient(process.env.DEEPGRAM_API_KEY!);
const connection = deepgram.listen.live({
model: 'nova-3',
smart_format: true,
interim_results: true,
encoding: 'linear16',
sample_rate: 16000,
channels: 1,
});
connection.on(LiveTranscriptionEvents.Transcript, (data) => {
const transcript = data.channel.alternatives[0]?.transcript;
if (transcript) {
res.write(`data: ${JSON.stringify({
transcript,
is_final: data.is_final,
speech_final: data.speech_final,
})}\n\n`);
}
});
// Client provides audio via a paired WebSocket (see browser setup)
req.on('close', () => {
connection.finish();
});
});
Step 6: KeepAlive for Long Sessions
// Deepgram closes idle connections after ~10s of no audio.
// Send KeepAlive messages during silence periods.
connection.on(LiveTranscriptionEvents.Open, () => {
const keepAliveInterval = setInterval(() => {
if (connection.getReadyState() === 1) {
connection.keepAlive();
}
}, 8000); // Every 8 seconds
connection.on(LiveTranscriptionEvents.Close, () => {
clearInterval(keepAliveInterval);
});
});
Output
- Live WebSocket transcription with interim/final results
- Microphone capture pipeline (Sox -> Deepgram)
- Speaker diarization in streaming mode
- Auto-reconnect with exponential backoff and jitter
- SSE endpoint for browser integration
- KeepAlive handling for long sessions
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| WebSocket closes immediately | Invalid API key or bad encoding params | Check key, verify encoding/sample_rate match audio |
| No transcripts received | Audio not being sent or wrong format | Verify connection.send(chunk) is called with raw PCM |
| High latency | Network congestion | Use interim_results: true for perceived speed |
rec command not found | Sox not installed | apt install sox or brew install sox |
| Connection drops after 10s | No audio + no KeepAlive | Send connection.keepAlive() every 8s |
| Garbled output | Sample rate mismatch | Ensure audio sample rate matches sample_rate option |
Resources
Next Steps
Proceed to deepgram-data-handling for transcript processing and storage patterns.
When not to use it
- →When the API key is invalid or encoding parameters are incorrect.
- →When audio is not being sent or is in the wrong format.
- →When Sox is not installed for microphone capture.
Prerequisites
Limitations
- →Requires the audio encoding and sample rate to match the Deepgram configuration.
- →Deepgram closes idle connections after approximately 10 seconds of no audio.
- →Microphone capture relies on the `sox` utility being installed.
How it compares
This skill automates the setup and management of a real-time streaming transcription pipeline with Deepgram, including microphone integration and resilience features, which is more complex than batch transcription or manual API calls.
Compared to similar skills
deepgram-core-workflow-b side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| deepgram-core-workflow-b (this skill) | 1 | 25d | Review | Intermediate |
| llama-cpp | 21 | 8mo | Review | Intermediate |
| openrouter | 19 | 9mo | Review | Intermediate |
| opencode-cli | 14 | 7mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
llama-cpp
zechenzhangAGI
Runs LLM inference on CPU, Apple Silicon, and consumer GPUs without NVIDIA hardware. Use for edge deployment, M1/M2/M3 Macs, AMD/Intel GPUs, or when CUDA is unavailable. Supports GGUF quantization (1.5-8 bit) for reduced memory and 4-10× speedup vs PyTorch on CPU.
openrouter
rawveg
OpenRouter API - Unified access to 400+ AI models through one API
opencode-cli
SpillwaveSolutions
This skill should be used when configuring or using the OpenCode CLI for headless LLM automation. Use when the user asks to "configure opencode", "use opencode cli", "set up opencode", "opencode run command", "opencode model selection", "opencode providers", "opencode vertex ai", "opencode mcp servers", "opencode ollama", "opencode local models", "opencode deepseek", "opencode kimi", "opencode mistral", "fallback cli tool", or "headless llm cli". Covers command syntax, provider configuration, Vertex AI setup, MCP servers, local models, cloud providers, and subprocess integration patterns.
qdrant-vector-search
zechenzhangAGI
High-performance vector similarity search engine for RAG and semantic search. Use when building production RAG systems requiring fast nearest neighbor search, hybrid search with filtering, or scalable vector storage with Rust-powered performance.
langchain
zechenzhangAGI
Framework for building LLM-powered applications with agents, chains, and RAG. Supports multiple providers (OpenAI, Anthropic, Google), 500+ integrations, ReAct agents, tool calling, memory management, and vector store retrieval. Use for building chatbots, question-answering systems, autonomous agents, or RAG applications. Best for rapid prototyping and production deployments.
unsloth
zechenzhangAGI
Expert guidance for fast fine-tuning with Unsloth - 2-5x faster training, 50-80% less memory, LoRA/QLoRA optimization