Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Building a Local Voice-to-Text Pipeline with Node.js and Whisper

Building a Local Voice-to-Text Pipeline with Node.js and Whisper A few months ago, I needed to transcribe hours of meeting recordings. Cloud APIs from Google and AWS would have cost $50-100 per month. I had a GPU sitting idle in my dev…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




Building a Local Voice-to-Text Pipeline with Node.js and Whisper



A few months ago, I needed to transcribe hours of meeting recordings. Cloud APIs from Google and AWS would have cost $50-100 per month. I had a GPU sitting idle in my dev machine.



So I built a fully local pipeline: record audio, transcribe with Whisper, generate SRT subtitles, and store results in SQLite. All in Node.js, all free.






The Architecture



Three stages:




  1. Audio ingestion - normalize via FFmpeg

  2. Transcription - run Whisper (whisper.cpp) as child process

  3. Post-processing - SRT subtitles + SQLite storage




Input -> FFmpeg -> Whisper -> Node.js -> SRT + SQLite









Step 1: Audio Normalization with FFmpeg



Whisper needs 16kHz mono WAV input. Here is the Node.js helper:




const { execa } = require('execa');
const path = require('path');

async function normalizeAudio(inputPath, outputDir) {
const ext = path.extname(inputPath);
const base = path.basename(inputPath, ext);
const outputPath = path.join(outputDir, base + '_16khz.wav');

await execa('ffmpeg', [
'-i', inputPath,
'-ar', '16000',
'-ac', '1',
'-sample_fmt', 's16',
'-y',
outputPath
]);

return outputPath;
}

module.exports = { normalizeAudio };









Step 2: Running Whisper from Node.js



We call whisper.cpp CLI as a child process:




const { execa } = require('execa');
const path = require('path');

const MODEL = 'base'; // tiny, base, small, medium, large-v3

async function transcribe(audioPath) {
const outputDir = path.dirname(audioPath);

const { stdout } = await execa(
'./whisper.cpp/build/bin/whisper-cli',
[
'-m', './whisper.cpp/models/ggml-' + MODEL + '.bin',
'-f', audioPath,
'-otxt', '-osrt',
'--output-dir', outputDir
]
);

return {
text: stdout,
srtPath: path.join(outputDir, path.basename(audioPath, '.wav') + '.srt')
};
}

module.exports = { transcribe };









Step 3: SQLite Storage



Using better-sqlite3 for zero-config persistence:




const Database = require('better-sqlite3');

function initDatabase(dbPath) {
const db = new Database(dbPath);
db.exec([
'CREATE TABLE IF NOT EXISTS transcriptions (',
' id INTEGER PRIMARY KEY AUTOINCREMENT,',
' filename TEXT NOT NULL,',
' duration_seconds REAL,',
' model TEXT,',
' text TEXT NOT NULL,',
' srt_content TEXT,',
' created_at DATETIME DEFAULT CURRENT_TIMESTAMP',
');',
'CREATE INDEX IF NOT EXISTS idx_created_at',
' ON transcriptions(created_at DESC);'
].join('
'));
return db;
}

function saveTranscription(db, data) {
const stmt = db.prepare([
'INSERT INTO transcriptions',
'(filename, duration_seconds, model, text, srt_content)',
'VALUES (?, ?, ?, ?, ?)'
].join(' '));
return stmt.run(
data.filename, data.duration, data.model,
data.text, data.srtContent
);
}

function searchTranscriptions(db, query) {
return db.prepare([
'SELECT * FROM transcriptions',
'WHERE text LIKE ? ORDER BY created_at DESC'
].join(' ')).all('%' + query + '%');
}

module.exports = { initDatabase, saveTranscription, searchTranscriptions };









Step 4: The Pipeline Runner






const { normalizeAudio } = require('./audio/normalize');
const { transcribe } = require('./transcription/whisper');
const { initDatabase, saveTranscription } = require('./storage/db');
const fs = require('fs');
const path = require('path');

async function runPipeline(inputAudio, dbPath) {
dbPath = dbPath || './transcriptions.db';
const workDir = './work';
fs.mkdirSync(workDir, { recursive: true });

console.log('[1/3] Normalizing audio...');
const normalizedPath = await normalizeAudio(inputAudio, workDir);

console.log('[2/3] Transcribing with Whisper...');
const result = await transcribe(normalizedPath);

console.log('[3/3] Saving to database...');
const db = initDatabase(dbPath);
const srtContent = fs.readFileSync(result.srtPath, 'utf-8');

saveTranscription(db, {
filename: path.basename(inputAudio),
duration: 0,
model: 'whisper-base',
text: result.text,
srtContent: srtContent
});

console.log('Done!');
return result;
}

const audioFile = process.argv[2];
if (!audioFile) {
console.error('Usage: node pipeline.js <audio-file>');
process.exit(1);
}
runPipeline(audioFile).catch(console.error);









Performance Benchmarks



Tested on Ryzen 5 5600X with RTX 3060 (12GB VRAM):


















































Model 1 min audio 10 min audio VRAM WER
tiny 4.2s 38s 1GB 8.1%
base 7.8s 72s 1.5GB 6.7%
small 18.1s 164s 2.8GB 4.3%
medium 42.3s 401s 5.8GB 3.1%
large 89.7s 852s 10.2GB 2.5%


The base model hits the sweet spot: sub-10s for short clips, about 1 minute for a podcast episode, with no noticeable quality loss for English content.






Setup Script






npm init -y
npm install execa better-sqlite3

mkdir -p whisper.cpp/models
wget https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin \
-O whisper.cpp/models/ggml-base.bin

cd whisper.cpp
cmake -B build
cmake --build build --config Release
cd ..

ffmpeg -version || echo "Install FFmpeg first"









Going Further



This pipeline is fully local: no data leaves your network, no API bills, no rate limits.



I have been using this for 3 months to transcribe client calls and podcast episodes. The full source with speaker diarization and WebSocket live transcription is on GitHub.






Have you built something similar? Share your approach in the comments.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Building a Local Voice-to-Text Pipeline with Node.js and Whisper

Thematisch verwandte Begriffe: Building, Local, VoicetoText, Pipeline · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-18163 | IBM Financial Transaction Manager (FTM) for RedHat OpenShift could allow…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick