A lightweight, cross-platform audio streaming application built with Tauri. Stream system audio over TCP with minimal latency and robust architecture.
- Overview
- Features
- Use Cases
- Installation
- Quick Start
- Configuration
- System Requirements
- Architecture
- Development
- Troubleshooting
TCP Streamer is a desktop application designed to capture and stream audio from your computer to any TCP server. It's perfect for integrating with multi-room audio systems like Snapcast, creating custom audio pipelines, or building distributed audio setups.
- Captures audio from any input device (microphone, system audio via loopback)
- Streams raw PCM audio data over TCP to a specified IP and port
- Optimizes bandwidth by detecting silence and skipping transmission when no audio is playing
- Manages multiple configuration profiles for different streaming scenarios
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Audio │ │ TCP │ │ Server │
│ Input │─────▶│ Streamer │─────▶│ (Snapcast, │
│ (Device) │ │ │ │ Custom) │
└─────────────┘ └──────────────┘ └─────────────┘
- Capture: Reads audio from selected input device at configurable sample rate/buffer size
- Buffer: Pushes audio into a lock-free Ring Buffer to absorb network jitter
- Process: Analyzes RMS to detect silence
- Stream: A separate network thread reads from buffer and sends data via Async TCP
- Monitor: Real-time health monitoring (buffer usage, latency, bitrate)
- ✅ Connection Reliability - 5s Write Timeout & Graceful Shutdown (v1.6.0)
- ✅ Smart Deep Sleep - Auto-disconnect on prolonged silence to prevent "zombies" (v1.6.0)
- ✅ Precision Audio Pacing - Token Bucket algorithm for mathematically perfect transmission timing
- ✅ Hybrid Spin-Wait Strategy - Sub-millisecond timing precision via spin-loop (v1.7.0)
- ✅ Robust Audio Engine (v1.8.0) - Native F32 internal architecture; eliminates clipping and Linux noise issues
- ✅ Prefill Gate (v1.8.1) - Eliminates startup stutter by buffering 1000ms before transmission
- ✅ Real-time Audio Streaming - Low-latency PCM audio over TCP
- ✅ Adaptive Buffer Sizing - Automatically adjusts buffer based on network jitter
- ✅ Silence Detection - RMS-based "Stop Sending" bandwidth saver (v1.6.0)
- ✅ Auto-Reconnect - Resilient connection management
- ✅ Multi-Profile Support - Save and switch between configurations
- ✅ System Tray Integration - Runs in background, accessible from tray
- ✅ Windows Native Loopback - Capture system audio without virtual cables (WASAPI)
- 📊 Sample Rates: 44.1 kHz or 48 kHz
- 🔧 Buffer Sizes: 256, 512, 1024, or 2048 samples
- 🎤 Input Devices: Scans all host APIs (WASAPI, MME, CoreAudio) to find all devices
- 🎚️ Visual Volume Indicator: Real-time RMS meter for precise threshold tuning
- 🚀 Auto-start on Boot - Launch automatically when system starts
- 🔄 Auto-stream - Begin streaming immediately on startup
- 🔒 Auto-reconnect - Retry connection on failure
- 🎨 Modern UI - Clean, icon-based tabbed interface
- � Real-time Statistics - Monitor bitrate, uptime, data sent
- �📶 Network Quality Metrics - Real-time health score (Excellent/Good/Fair/Poor)
- 📉 Jitter Monitoring - Live tracking of network stability
- 📝 Activity Logs - Track connection events, buffer resizes, and errors
- 🌙 Minimize to Tray - Never quits, always accessible
- ⚡ Thread Priority - High priority thread option for reduced jitter
- ⏱️ Precision Pacer - Drift-aware Token Bucket algorithm to eliminate micro-bursts
- 🎛️ Network Presets - One-click optimization for Ethernet/WiFi/Poor connections
- 🚦 DSCP/TOS Support - QoS tagging (VoIP, Low Delay, Throughput)
- 📦 Dynamic Chunk Size - Configurable buffer chunks (128-4096 samples)
Stream audio from your computer to a Snapcast server, enabling synchronized playback across multiple rooms.
# Snapcast server listening on port 4953
TCP Streamer → 192.168.1.100:4953 → Snapcast Server → Multiple SpeakersSend audio from a security camera's microphone or monitoring device to a central server.
Distribute audio from a single source to multiple recipients via a TCP relay server.
Test audio processing pipelines, codecs, or streaming protocols with a reliable audio source.
Stream DJ mixes or live broadcasts from your computer to a remote server for distribution.
Download the latest release for your platform:
| Platform | File Type | Installation |
|---|---|---|
| macOS | .dmg |
Open and drag to Applications |
| Windows | .msi or .exe |
Run installer |
| Linux | .AppImage or .deb |
See LINUX_GUIDE.md |
- Node.js (v18 or later)
- Rust (latest stable)
- Platform-specific dependencies:
- Ubuntu/Debian:
libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libasound2-dev - macOS: Xcode Command Line Tools
- Windows: Microsoft Visual Studio C++ Build Tools
- Ubuntu/Debian:
# Clone repository
git clone https://github.com/NaturalDevCR/TCP-Streamer.git
cd TCP-Streamer
# Install dependencies
npm install
# Run in development mode
npm run tauri dev
# Build for production
npm run tauri buildChoose the audio source you want to stream (microphone, virtual audio device, etc.).
Windows Loopback: Check the "Enable Loopback (Windows)" box to capture system audio directly (no extra software needed, but you need to have speakers, or headphones plugged in to your computer in order to capture audio). or use software like VB Audio Cable to create a virtual audio device. macOS Loopback: Use software like BlackHole or Loopback to capture system audio.
Enter the IP address and port of your TCP server:
- IP:
192.168.1.100(example Snapcast server) - Port:
4953(Snapcast default TCP port)
- Sample Rate: 48 kHz (recommended) or 44.1 kHz
- Buffer Size: 1024 (balanced) or adjust for latency/stability
Click Start Streaming. Monitor connection status and statistics in the UI.
- Enable Auto-start on launch to run on system boot
- Enable Auto-stream to start streaming automatically
- Enable Auto-reconnect for resilient connections
Save different configurations for various scenarios:
- Create Profile: Click ➕ New, enter a name, click ✓ Create
- Save Settings: Adjust settings, click 💾 Save to update current profile
- Switch Profile: Select from dropdown to load saved configuration
- Delete Profile: Select profile, click 🗑️ Delete (cannot delete Default)
Example Profiles:
Home-Snapcast: 192.168.1.100:4953, 48kHz, Auto-reconnect ONStudio-Monitor: 10.0.0.50:8000, 44.1kHz, High bufferTesting: localhost:9999, 48kHz, Low latency
| Setting | Options | Recommendation |
|---|---|---|
| Sample Rate | 44.1 kHz, 48 kHz | 48 kHz for modern systems |
| Buffer Size | 256, 512, 1024, 2048 | 1024 (balanced) or 512 (low latency) |
| Ring Buffer | 2000ms - 15000ms | 4000ms for WiFi, 2000ms for Ethernet |
Automatically resizes the ring buffer based on network conditions to prevent audio dropouts.
- Enable: Toggles the adaptive logic.
- Min Buffer: The floor value for the buffer (e.g., 2000ms).
- Max Buffer: The ceiling value (e.g., 10000ms).
The system checks jitter every 10 seconds and adjusts the buffer size within these bounds.
As of v1.5.3, the application automatically adjusts buffer settings based on device type:
WASAPI Loopback (Windows):
- Base ring buffer: 8000ms (handles WiFi jitter + laptop CPU throttling + WASAPI timing variability)
- Adaptive range: 4000-12000ms (wider range for unpredictable conditions)
- Best latency: ~4 seconds (wired network, low jitter)
- Worst latency: ~12 seconds (WiFi laptop, high jitter)
Standard Input/VB Audio Cable:
- Base ring buffer: 5000ms (WiFi tolerance)
- Adaptive range: 2000-6000ms (more aggressive, tighter control)
- Best latency: ~2 seconds (wired network, low jitter)
- Worst latency: ~6 seconds (WiFi, high jitter)
How it works: The adaptive buffer uses real-time jitter measurements to dynamically adjust within these device-specific ranges. On stable wired networks, it shrinks toward the minimum. On WiFi or under load, it expands toward the maximum.
Located in the Advanced tab, these presets configure multiple settings at once:
| Preset | Description | Settings Applied | | ~ | ~ | ~ | | Ethernet | For stable wired connections | Ring Buffer: 2s, Chunk: 512, Adaptive: 2s-6s | | WiFi | For standard wireless | Ring Buffer: 4s, Chunk: 1024, Adaptive: 3s-10s | | WiFi (Poor) | For unstable/far connections | Ring Buffer: 8s, Chunk: 2048, Adaptive: 5s-15s |
- Visual Indicator: Use the real-time volume bar to see your current audio level.
- Threshold: Set the slider just above the "noise floor" (white line).
- Timeout: Stop streaming after X seconds of silence to save bandwidth.
| Feature | Description |
|---|---|
| Auto-start on launch | Launch app when system starts (minimized to tray) |
| Auto-stream | Begin streaming immediately after app starts |
| Auto-reconnect | Retry connection every 3 seconds on failure |
Goal: Lowest latency, highest stability.
- Preset: Ethernet
- Sample Rate: 48 kHz
- Buffer Size: 512
- Adaptive Buffer: Enabled (Min: 1000ms, Max: 4000ms)
Goal: Balanced stability for multi-room sync.
- Preset: WiFi
- Sample Rate: 44.1 kHz or 48 kHz
- Buffer Size: 1024
- Adaptive Buffer: Enabled (Min: 3000ms, Max: 10000ms)
Goal: Prevent dropouts at all costs.
- Preset: WiFi (Poor Signal)
- Sample Rate: 44.1 kHz
- Buffer Size: 2048
- Adaptive Buffer: Enabled (Min: 5000ms, Max: 20000ms)
- OS: macOS 10.15+, Windows 10+, Ubuntu 20.04+
- RAM: 100 MB
- CPU: Any modern processor
- Network: Stable network connection to TCP server
- ✅ macOS (Intel & Apple Silicon)
- ✅ Windows 10/11
- ✅ Linux (Ubuntu, Debian, Fedora, Arch)
- Frontend: HTML, CSS, JavaScript (Vite)
- Backend: Rust (Tauri v2)
- Audio: cpal (cross-platform audio library)
- Storage: tauri-plugin-store (settings persistence)
Input Device → cpal → Producer → Ring Buffer → Consumer (Thread) → TCP Stream- Format: Raw PCM, 16-bit signed integers, little-endian
- Channels: 2 (stereo)
- Buffering: Lock-free Ring Buffer (approx 2s capacity)
- Silence Threshold: RMS < 50.0 (skips transmission)
- Capture: cpal reads audio from device and pushes to Ring Buffer (Producer)
- Process: Calculate RMS to detect silence before pushing
- Pacing: Precision Pacer waits for the exact mathematically calculated time for the next chunk
- Transmit: Dedicated Network Thread (Consumer) sends data via TCP without bursting
- Monitor: Network thread calculates stats (bitrate, uptime) and emits events to UI
tcp-streamer/
├── src/ # Frontend (HTML/CSS/JS)
│ ├── index.html # Main UI
│ ├── main.js # Application logic
│ └── styles.css # Styling
├── src-tauri/ # Backend (Rust)
│ ├── src/
│ │ ├── lib.rs # App setup, tray, window management
│ │ └── audio.rs # Audio streaming logic
│ └── Cargo.toml # Rust dependencies
├── package.json # Node dependencies
└── README.md
# Development mode (hot reload)
npm run tauri dev
# Build for production
npm run tauri build
# Run tests
cargo test --manifest-path=src-tauri/Cargo.toml
# Format code
cargo fmt --manifest-path=src-tauri/Cargo.toml
npm run formatContributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
Problem: Audio stutters or has dropouts when using Windows WASAPI loopback
Solutions:
- WASAPI loopback is more sensitive to network conditions than VB Audio Cable
- The application automatically uses larger buffers (8000ms base) for loopback mode
- Enable Adaptive Buffer to handle varying network conditions
- On WiFi laptops, expect 4-12 seconds of latency (trade-off for stability)
- For wired networks, adaptive buffer will shrink toward 4 seconds
- Memory usage is minimal (~2.3MB max @ 12 seconds)
Problem: "Failed to connect" error
Solutions:
- Verify TCP server is running and listening on specified port
- Check firewall settings (allow TCP connections)
- Ensure IP address and port are correct
- Try
localhostor127.0.0.1if server is on same machine
Problem: Input device doesn't appear in dropdown
Solutions:
- macOS: Grant microphone permissions in System Settings → Privacy & Security
- Windows: Check audio device is enabled in Sound settings
- Linux: Ensure ALSA/PulseAudio is configured correctly
- Restart the application after connecting new audio devices
Problem: Connection established but no audio is being sent
Possible Causes:
- Silence detection is working correctly (no audio playing)
- Audio input device is muted or volume is too low
- Wrong input device selected
Solutions:
- Play audio on your computer while streaming
- Check input device volume/mute status
- Try a different input device
- Check logs for "Silence detected" (RMS values)
Problem: Application uses excessive CPU
Solutions:
- Increase Buffer Size to 2048 (reduces processing frequency)
- Lower Sample Rate to 44.1 kHz if 48 kHz is unnecessary
- Disable unused features
Problem: "App is damaged and can't be opened"
Solution:
# Remove quarantine attribute
xattr -cr /Applications/TCP\ Streamer.appThis project is licensed under the MIT License - see the LICENSE file for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
If you find TCP Streamer useful and would like to support its development, consider making a donation:
Your support helps maintain and improve this project. Thank you! 🙏
For anyone concerned, this project was vibe-coded (with some personal tweaks) using Gemini 3 Pro and Sonnet 4.5, I did this, just because I needed something specific to send audio from computers to a Snapcast server, it started simple, but it beceame more complex as I was realizing there are many things to optimize and many scenarios... so, while this is a work in progress, so far it's working well.
Made with ❤️ for the audio streaming community