IFM Station — Desktop Broadcaster Studio
Professional desktop broadcasting application for originating live content into the IFM mesh. Native performance, system audio integration, multi-source mixing.
Overview
| Property | Value |
|---|---|
| Binary | ifm-station |
| Package | packages/ifm-station/ |
| Core | ifm-core via Tauri/N-API |
| UI | React + TypeScript (WebView) |
| Platforms | Windows, macOS, Linux (x64 + arm64) |
| Install | curl -fsSL https://ifm.sh/install-station.sh | bash |
Features
Broadcast Studio
- Multi-source audio mixer — Microphone, system audio, file playback, virtual inputs
- Real-time Opus encoding — 48 kHz stereo, configurable bitrate (32–256 kbps)
- Live monitoring — Latency-compensated headphone feed with VU meters
- Recording — Local WAV/Opus archive of every broadcast session
Frequency Management
- Create stations — Enter FM-style number (
91.700) or name (music.lofi→ auto-assigned) - Access control — Public / Protected (shared key) / Hidden (invite only)
- Station persistence — Stations saved locally; reopen preserves frequency number
- Multi-station — Run multiple stations simultaneously (tabbed interface)
Relay Network
- Relay pool view — Live list of available relays (mDNS + DHT discovered)
- Relay selection — Manual or automatic (closest by RTT)
- Relay health — Latency, uptime, peer count per relay
- Direct peer mode — Bypass relays for LAN-only broadcasts
Communication
- Real-time chat — Text chat with all tuned listeners
- File transfer — Drag-drop files to broadcast to frequency
- Listener view — Live peer count, geographic map, connection quality
System Integration
System tray — Minimize to tray; broadcast continues
Global hotkeys — Push-to-talk, mute, next/prev track
Audio device selection — Per-source input/output device picker
Background mode — Close window → keeps broadcasting in tray
Screen & System Audio Recording permission (macOS) — the console's Window and Desktop Audio sources enumerate and capture targets through
ScreenCaptureKit. macOS requires the Screen & System Audio Recording TCC permission; without it the source lists stay empty and the console shows the "IFM needs permission" hint. Steps:- Apple menu → System Settings → Privacy & Security (sidebar; scroll down if needed)
- Click Screen & System Audio Recording
- Toggle the ability to record on for IFM Station (you can allow both screen and audio, or just audio)
- To add the app manually, click Add below the list and navigate to IFM Station
- Quit and reopen IFM Station — the permission applies only after the app restarts
The app ships
NSScreenCaptureUsageDescriptioninsrc-tauri/Info.plist. On macOS 15+ (Sequoia) the grant only applies to a stable code identity — a baretarget/debugdev executable is ad-hoc signed and its signature changes every rebuild, so granting it in System Settings never sticks. Run a real.appbundle (bun scripts/build.mjs --desktop ifm-station, orcargo tauri build --debug) and grant the permission toIFM Station.app. The console detects the dev-build case and explains this in the source picker. Seedocs/desktop-apps/README.md→ Audio notes (macOS) for the full reference.
Architecture
User Flow
First Launch
Daily Use
Configuration
Stored in platform config dir:
- macOS:
~/Library/Application Support/ifm-station/ - Windows:
%APPDATA%\ifm-station\ - Linux:
~/.config/ifm-station/
# config.toml
[identity]
private_key = "ed25519..." # Generated on first run
public_key = "ed25519..."
[stations]
# Auto-saved per station
"91.700" = { name = "morning.show", access = "public", created = "2024-01-15" }
"92.300" = { name = "team.private", access = "protected", key_hash = "sha256..." }
[audio]
input_device = "default" # or device ID
output_device = "default"
sample_rate = 48000
bitrate = 128000 # bps
[relay]
auto_select = true # Pick closest by RTT
selected_relays = [] # Manual override: [peer_id, ...]
direct_peer_mode = false # LAN only, no relays
[ui]
minimize_to_tray = true
global_hotkeys = true
theme = "system" # light/dark/systemKeyboard Shortcuts
| Action | Shortcut |
|---|---|
| Push-to-talk (hold) | Space (configurable) |
| Toggle mute | M |
| Next station | Ctrl+Right / Cmd+Right |
| Previous station | Ctrl+Left / Cmd+Left |
| Open/close window | Ctrl+Shift+I / Cmd+Shift+I |
| Start/stop broadcast | Ctrl+Shift+Space / Cmd+Shift+Space |
| Open settings | Ctrl+, / Cmd+, |
CLI Flags
ifm-station [OPTIONS]
Options:
--station <FREQ> Auto-tune to frequency on start
--headless No window, broadcast only (for CI/servers)
--config <PATH> Custom config file
--log-level <LEVEL> trace/debug/info/warn/error
--version Print version
--help Show helpDevelopment
cd packages/ifm-station
# Install deps
bun install
# Dev mode (hot reload)
bun run tauri dev
# Build release
bun run tauri build
# Output: src-tauri/target/release/bundle/Project Structure
packages/ifm-station/
├── src/
│ ├── App.tsx # Main app, routing
│ ├── main.tsx # Entry
│ ├── components/
│ │ ├── Studio/ # Mixer, monitor, controls
│ │ ├── Setup/ # Frequency creation wizard
│ │ ├── Stations/ # Station list, tabs
│ │ ├── RelayPool/ # Relay selection UI
│ │ ├── Chat/ # Chat panel
│ │ ├── FileTransfer/ # Drag-drop file broadcast
│ │ └── Header/ # Brand, status, tray menu
│ ├── hooks/
│ │ ├── useStation.ts # Station state + actions
│ │ ├── useMixer.ts # Audio mixer state
│ │ ├── useRelayPool.ts # Relay discovery + selection
│ │ └── useTray.ts # System tray integration
│ ├── lib/
│ │ ├── ifm.ts # Tauri command wrappers
│ │ ├── audio.ts # AudioContext helpers
│ │ └── storage.ts # Config persistence
│ └── styles/
│ ├── globals.css
│ └── variables.css
├── src-tauri/
│ ├── Cargo.toml
│ ├── tauri.conf.json
│ ├── src/
│ │ ├── main.rs # Tauri entry, command registration
│ │ ├── commands/ # Individual command modules
│ │ │ ├── node.rs
│ │ │ ├── audio.rs
│ │ │ ├── mixer.rs
│ │ │ ├── discovery.rs
│ │ │ ├── config.rs
│ │ │ └── tray.rs
│ │ └── lib.rs # Shared types, error handling
│ └── icons/ # App icons (png, icns, ico)
├── package.json
├── tauri.conf.json
└── vite.config.tsRelease Artifacts
| Platform | Format | Size (est.) |
|---|---|---|
| macOS arm64 | .dmg | ~25 MB |
| macOS x64 | .dmg | ~28 MB |
| Windows x64 | .msi | ~30 MB |
| Windows arm64 | .msi | ~28 MB |
| Linux x64 | .AppImage | ~35 MB |
| Linux arm64 | .AppImage | ~32 MB |
| Linux x64 | .deb | ~12 MB |
| Linux x64 | .rpm | ~12 MB |
All signed, notarized (macOS), cosign-verified.