Skip to main content

Local-Only Stack

This guide shows how to run LLMRTC entirely locally without any cloud APIs. By the end, you'll have a fully offline voice assistant running on your machine.


What You'll Build

Benefits:

  • Complete privacy—data never leaves your machine
  • No API costs
  • Works offline
  • Full control over models

Requirements:

  • Decent CPU (or GPU for faster inference)
  • 8GB+ RAM (16GB+ recommended)
  • 10GB+ disk space for models

Step 1: Install Ollama

Ollama runs LLMs locally.

macOS

# Install
brew install ollama

# Start Ollama service
ollama serve

Linux

# Install
curl -fsSL https://ollama.com/install.sh | sh

# Start Ollama service
ollama serve

Windows

Download from ollama.com/download and install.

Download a Model

# Recommended for voice (fast, good quality)
ollama pull llama3.2

# Alternative: smaller model for low-resource machines
ollama pull phi3

# Alternative: larger model for better quality
ollama pull llama3.1:8b

Verify

# Test the model
ollama run llama3.2 "Hello, how are you?"

# Check API
curl http://localhost:11434/api/tags

Step 2: Install Faster-Whisper

Faster-Whisper provides fast local speech-to-text.

docker run -d \
--name faster-whisper \
-p 9000:8000 \
fedirz/faster-whisper-server:latest-cpu

# Or with GPU (NVIDIA)
docker run -d \
--gpus all \
--name faster-whisper \
-p 9000:8000 \
fedirz/faster-whisper-server:latest-cuda

Using pip

# Install
pip install faster-whisper-server

# Run
faster-whisper-server --host 0.0.0.0 --port 9000

Verify

curl http://localhost:9000/health
# Should return: {"ok":true}

Step 3: Install Piper

Piper provides fast local text-to-speech.

docker run -d \
--name piper \
-p 5002:5000 \
rhasspy/piper:latest

Manual Installation

# Download Piper
wget https://github.com/rhasspy/piper/releases/latest/download/piper_linux_x86_64.tar.gz
tar -xzf piper_linux_x86_64.tar.gz
cd piper

# Download a voice model
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/amy/medium/en_US-amy-medium.onnx
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/amy/medium/en_US-amy-medium.onnx.json

# Run HTTP server (requires piper-http-server)
pip install piper-http-server
piper-http-server --port 5002 --model en_US-amy-medium.onnx

Available Voices

VoiceLanguageQualitySize
en_US-amy-mediumEnglish (US)Good60MB
en_US-lessac-mediumEnglish (US)Good60MB
en_GB-cori-mediumEnglish (UK)Good60MB
de_DE-thorsten-mediumGermanGood60MB
es_ES-mls_9972-mediumSpanishGood60MB

Browse all voices at rhasspy.github.io/piper-samples.

Verify

# Test TTS endpoint
curl -X POST http://localhost:5002/synthesize \
-H "Content-Type: application/json" \
-d '{"text": "Hello world"}' \
--output test.wav

# Play the audio
ffplay test.wav # or: aplay test.wav

Step 4: Configure LLMRTC Server

Create server.js:

import 'dotenv/config';
import {
LLMRTCServer,
OllamaLLMProvider,
FasterWhisperProvider,
PiperTTSProvider
} from '@llmrtc/llmrtc-backend';

// Create local providers
const llmProvider = new OllamaLLMProvider({
baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
model: 'llama3.2'
});

const sttProvider = new FasterWhisperProvider({
baseUrl: process.env.FASTER_WHISPER_URL || 'http://localhost:9000'
});

const ttsProvider = new PiperTTSProvider({
baseUrl: process.env.PIPER_URL || 'http://localhost:5002',
voice: 'en_US-amy-medium'
});

// Create server
const server = new LLMRTCServer({
providers: {
llm: llmProvider,
stt: sttProvider,
tts: ttsProvider
},
systemPrompt: `You are a helpful voice assistant running entirely locally.
Keep responses concise and conversational.`,
streamingTTS: true,
port: 8787
});

server.on('connection', ({ id }) => {
console.log(`Connected: ${id}`);
});

server.on('error', (error) => {
console.error('Error:', error);
});

await server.start();
console.log('Local voice server running on ws://localhost:8787');
console.log('Using: Ollama + Faster-Whisper + Piper');

Create .env:

# .env
OLLAMA_BASE_URL=http://localhost:11434
FASTER_WHISPER_URL=http://localhost:9000
PIPER_URL=http://localhost:5002

Step 5: Start Everything

Start Services

In separate terminals (or use Docker Compose):

# Terminal 1: Ollama
ollama serve

# Terminal 2: Faster-Whisper
docker start faster-whisper
# or: faster-whisper-server --host 0.0.0.0 --port 9000

# Terminal 3: Piper
docker start piper
# or: piper-http-server --port 5002 --model en_US-amy-medium.onnx

# Terminal 4: LLMRTC Server
node server.js

Verify All Services

# Check Ollama
curl http://localhost:11434/api/tags

# Check Faster-Whisper
curl http://localhost:9000/health

# Check Piper
curl http://localhost:5002/health

# Check LLMRTC
curl http://localhost:8787/health

Docker Compose Setup

Create docker-compose.yml for easy management:

version: '3.8'

services:
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
volumes:
- ollama_data:/root/.ollama
# Uncomment for GPU support
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]

faster-whisper:
image: fedirz/faster-whisper-server:latest-cpu
ports:
- "9000:8000"
# Use latest-cuda for GPU

piper:
image: rhasspy/piper:latest
ports:
- "5002:5000"

volumes:
ollama_data:

Start all services:

docker-compose up -d

# Pull Ollama model
docker exec -it ollama ollama pull llama3.2

# Start LLMRTC server
node server.js

Vision Support

There are two ways to add local vision:

Use OllamaLLMProvider with a vision-capable model. The provider automatically detects vision support.

# Pull Gemma3 (recommended for vision)
ollama pull gemma3

# Or pull LLaVA
ollama pull llava

Update server to use a vision model:

import {
LLMRTCServer,
OllamaLLMProvider,
FasterWhisperProvider,
PiperTTSProvider
} from '@llmrtc/llmrtc-backend';

const server = new LLMRTCServer({
providers: {
llm: new OllamaLLMProvider({
baseUrl: 'http://localhost:11434',
model: 'gemma3' // Vision-capable model handles images natively
}),
stt: new FasterWhisperProvider({
baseUrl: 'http://localhost:9000'
}),
tts: new PiperTTSProvider({
baseUrl: 'http://localhost:5002'
})
// No separate vision provider needed!
},
systemPrompt: 'You are a helpful assistant that can see and hear.'
});

Option B: Separate Vision Provider

Use a dedicated vision provider alongside a text-only LLM:

# Pull LLaVA for vision
ollama pull llava
import {
LLMRTCServer,
OllamaLLMProvider,
LlavaVisionProvider,
FasterWhisperProvider,
PiperTTSProvider
} from '@llmrtc/llmrtc-backend';

const server = new LLMRTCServer({
providers: {
llm: new OllamaLLMProvider({
baseUrl: 'http://localhost:11434',
model: 'llama3.2' // Text-only model
}),
stt: new FasterWhisperProvider({
baseUrl: 'http://localhost:9000'
}),
tts: new PiperTTSProvider({
baseUrl: 'http://localhost:5002'
}),
vision: new LlavaVisionProvider({
baseUrl: 'http://localhost:11434',
model: 'llava'
})
},
systemPrompt: 'You are a helpful assistant that can see and hear.'
});

Vision Model Comparison

ModelProviderNotes
gemma3OllamaLLMProviderGoogle's multimodal, good balance of speed/quality
llavaOllamaLLMProvider or LlavaVisionProviderGeneral vision tasks
llama3.2-visionOllamaLLMProviderMeta's vision model, larger but more capable

Performance Tuning

Ollama Options

const llmProvider = new OllamaLLMProvider({
baseUrl: 'http://localhost:11434',
model: 'llama3.2',
options: {
// Context window size
num_ctx: 4096,

// Number of tokens to predict
num_predict: 256,

// Temperature (lower = more focused)
temperature: 0.7,

// Number of CPU threads
num_thread: 8
}
});

Faster-Whisper Options

const sttProvider = new FasterWhisperProvider({
baseUrl: 'http://localhost:9000',
model: 'base', // tiny, base, small, medium, large-v3
language: 'en' // Force language for faster processing
});

Model size comparison:

ModelSizeSpeedAccuracy
tiny75MBFastestBasic
base145MBFastGood
small500MBMediumBetter
medium1.5GBSlowerGreat
large-v33GBSlowestBest

Troubleshooting

Ollama Not Responding

# Check if Ollama is running
curl http://localhost:11434/api/tags

# Restart Ollama
ollama serve

# Check logs
journalctl -u ollama -f

Slow LLM Responses

  1. Use a smaller model: ollama pull phi3 or llama3.2:3b
  2. Reduce context: num_ctx: 2048
  3. Enable GPU acceleration if available

Faster-Whisper Errors

# Check container logs
docker logs faster-whisper

# Restart container
docker restart faster-whisper

# Try CPU-only if GPU issues
docker run -d -p 9000:8000 fedirz/faster-whisper-server:latest-cpu

Piper No Audio

# Test directly
curl -X POST http://localhost:5002/synthesize \
-H "Content-Type: application/json" \
-d '{"text": "Test"}' \
--output test.wav

# Check voice model is loaded
curl http://localhost:5002/voices

High Latency

Local models are slower than cloud APIs. To improve:

  1. Use smaller models (llama3.2:3b, phi3)
  2. Enable GPU acceleration
  3. Pre-warm models by sending a test request on startup
  4. Reduce num_predict for shorter responses

Resource Requirements

SetupRAMCPUGPU
Minimal (tiny models)4GB4 cores-
Standard (base models)8GB8 cores-
Quality (medium models)16GB8 coresOptional
Best (large models)32GB8 coresRecommended

Next Steps

Your local stack is running! Explore more: