🎤 Meiko is a unified Go application that integrates SDRTrunk and audio transcription services. It provides a local-first, robust, and user-friendly experience for monitoring and transcribing radio communications.
- SDRTrunk Process Management: Launches and monitors SDRTrunk as a child process
- File System Monitoring: Watches for new audio recordings from SDRTrunk
- Dual Transcription Modes:
- Local transcription using faster-whisper
- Remote transcription via API endpoints
- Discord Integration: Real-time notifications and system status updates
- Database Storage: SQLite database for call records and transcriptions
- System Monitoring: Health checks and performance monitoring
- Pre-flight Validation: Comprehensive system checks before startup
- Colored Console Logging: Beautiful, informative console output with spinners
- Graceful Shutdown: Proper cleanup and shutdown handling
- Configuration Validation: Comprehensive config file validation
- Error Recovery: Robust error handling and recovery mechanisms
- Performance Monitoring: CPU, memory, and disk usage tracking
Meiko uses a single-process architecture optimized for SDR monitoring workloads. While pre-forking could improve web performance, it conflicts with SDRTrunk's single-instance requirement.
Why Single-Process:
- SDRTrunk Compatibility - Prevents multiple SDRTrunk instances competing for audio hardware
- Resource Efficiency - Avoids duplicate file watchers and database connections
- Deterministic Behavior - Ensures consistent audio processing and transcription
- Simplified Debugging - Single process makes troubleshooting easier
Performance Optimizations:
- Memory usage reduction enabled
- Optimized connection handling (256K max concurrent)
- Smart idle timeout management (60s)
- Keep-alive connections for faster response times
- Efficient static file serving with compression
Future Scaling Options:
- Reverse Proxy - Use nginx/Apache for static file serving and load balancing
- CDN Integration - Serve static assets from content delivery networks
- Database Optimization - Connection pooling and query optimization
- Caching Layer - Redis/Memcached for frequently accessed data
- Microservices - Separate web dashboard from SDR processing if needed
- Go 1.21 or later
- Java Runtime Environment (for SDRTrunk)
- Python 3.8+ (for local transcription)
- SDRTrunk application
- faster-whisper (for local transcription):
pip install faster-whisper
git clone https://github.com/your-username/Meiko.git
cd Meiko
go mod tidy
go build -o meiko
Copy and customize the configuration file:
cp config.yaml config-local.yaml
sdrtrunk:
# For JAR distribution
path: "/path/to/sdrtrunk.jar"
java_path: "java"
jvm_args: ["-Xmx2g", "-Xms512m"]
# OR for Linux binary distribution
path: "/path/to/sdr-trunk"
# java_path and jvm_args are ignored for binaries
audio_output_dir: "/path/to/recordings"
transcription:
mode: "local" # or "remote"
local:
whisper_script: "./fasterWhisper.py"
python_path: "python"
model_size: "tiny"
device: "cpu"
language: "en"
discord:
token: "YOUR_DISCORD_BOT_TOKEN"
channel_id: "YOUR_CHANNEL_ID"
notifications:
startup: true
shutdown: true
errors: true
transcriptions: true
-
Configure the application:
# Edit config.yaml with your settings nano config.yaml
-
Run Meiko:
./meiko
# Use custom config file
./meiko -config custom-config.yaml
# Enable debug logging
./meiko -debug
# Show version
./meiko -version
Meiko automatically runs pre-flight checks on startup:
- ✅ SDRTrunk path validation
- ✅ Java runtime availability
- ✅ Audio output directory permissions
- ✅ Transcription service configuration
- ✅ Database connectivity
- ✅ USB device detection (optional)
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ SDRTrunk │ │ File Watcher │ │ Transcription │
│ Manager │───▶│ │───▶│ Service │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Process │ │ Call │ │ Database │
│ Monitor │ │ Processor │ │ │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Discord │ │ System │ │ Logger │
│ Client │ │ Monitor │ │ │
└─────────────────┘ └──────────────────┘ └─────────────────┘
- SDRTrunk generates audio recordings
- File Watcher detects new files
- Call Processor extracts metadata and queues for transcription
- Transcription Service processes audio (local or remote)
- Database stores call records and transcriptions
- Discord Client sends notifications
- System Monitor tracks performance and health
Uses the included fasterWhisper.py
script with the faster-whisper library:
transcription:
mode: "local"
local:
whisper_script: "./fasterWhisper.py"
model_size: "tiny" # tiny, base, small, medium, large
device: "cpu" # cpu, cuda
Advantages:
- No internet required
- Lower latency
- Privacy-focused
- No API costs
Sends audio files to a remote transcription API:
transcription:
mode: "remote"
remote:
endpoint: "https://your-api.com/transcribe"
api_key: "your-api-key"
timeout: 30
Advantages:
- More powerful models
- No local compute requirements
- Centralized processing
- Create a Discord application at https://discord.com/developers/applications
- Create a bot and copy the token
- Invite the bot to your server with appropriate permissions
- Configure the bot token and channel ID in
config.yaml
- 🚀 Startup/Shutdown: Application lifecycle events
- ❌ Errors: Critical errors and failures
- 📞 Transcriptions: New call transcriptions
- 📊 System Health: Performance alerts and warnings
CREATE TABLE calls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
filename TEXT NOT NULL,
filepath TEXT NOT NULL UNIQUE,
talkgroup_id TEXT,
from_id TEXT,
to_id TEXT,
unixtime INTEGER,
duration REAL,
transcription TEXT,
processed BOOLEAN DEFAULT FALSE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
- DEBUG: Detailed debugging information
- INFO: General information messages
- WARN: Warning messages
- ERROR: Error messages
- CPU usage monitoring
- Memory usage tracking
- Disk space monitoring
- Process health checks
- Automatic alerting
# Check Java installation
java -version
# Verify SDRTrunk path
ls -la /path/to/sdrtrunk.jar
# Check permissions
chmod +x /path/to/sdrtrunk.jar
# Test Python and faster-whisper
python -c "import faster_whisper; print('OK')"
# Test whisper script directly
python ./fasterWhisper.py test-audio.mp3
- Verify bot token is correct
- Check bot permissions in Discord server
- Ensure channel ID is valid
Enable debug logging for detailed troubleshooting:
logging:
level: "DEBUG"
colors: true
timestamps: true
- Use GPU acceleration:
device: "cuda"
- Adjust model size:
tiny
(fastest) tolarge
(most accurate) - Tune batch processing:
batch_size: 5
- Adjust file monitoring interval:
poll_interval: 1000
- Configure database connection pool:
max_open_conns: 10
- Set appropriate JVM memory:
jvm_args: ["-Xmx4g"]
Meiko/
├── main.go # Application entry point
├── config.yaml # Configuration file
├── fasterWhisper.py # Transcription script
├── internal/ # Internal packages
│ ├── config/ # Configuration management
│ ├── database/ # Database operations
│ ├── discord/ # Discord integration
│ ├── logger/ # Logging system
│ ├── monitoring/ # System monitoring
│ ├── preflight/ # Pre-flight checks
│ ├── processor/ # Call processing
│ ├── sdrtrunk/ # SDRTrunk management
│ ├── transcription/ # Transcription services
│ └── watcher/ # File system monitoring
└── references/ # Reference implementations
# Development build
go build -o meiko
# Production build with optimizations
go build -ldflags "-s -w" -o meiko
# Cross-compilation for Linux
GOOS=linux GOARCH=amd64 go build -o meiko-linux
# Cross-compilation for Windows
GOOS=windows GOARCH=amd64 go build -o meiko.exe
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- SDRTrunk: The excellent SDR trunking application
- faster-whisper: High-performance speech recognition
- Original Projects: Swimtrunks and SdrTrunk-Transcriber for inspiration
- 📖 Documentation: Check this README and inline code comments
- 🐛 Issues: Report bugs via GitHub Issues
- 💬 Discussions: Use GitHub Discussions for questions
Made with ❤️ for the radio monitoring community