Skip to content

About

An Android application for streaming audio over a local network. It allows you to stream your Android device's internal audio to any device on the network. Developed in Kotlin and Jetpack Compose.

Resources

Stars

162 stars

Watchers

4 watching

Forks

Repository files navigation

WiFi Audio Streaming Icon

WiFi Audio Streaming (Android)

Get it on GitHub Get it on IzzyOnDroidGitLab

Turn your Android device into a versatile wireless audio transmitter, receiver, or web server.
This application allows you to send your phone's audio to any device on the local network (PC, browser, media player), or listen to audio from another device, all without root.

🌐 Website: marcomorosi.eu/wifi-audio-streaming


πŸ“Έ Overview


✨ Key Features

  • Multi-Protocol Architecture: Stream using the native low-latency protocol (WFAS v2), standard RTP for external media players, HTTP to listen directly from any web browser (Chrome, Safari, Smart TVs), DLNA/UPnP to push audio to AV receivers and smart TVs with no app on the receiving end, or Snapcast to drive a synchronised multiroom setup.
  • Password Protection & End-to-End Encryption: Choose who can connect with Off, Ask, or Key authorization modes. In Key mode, the client proves it knows the shared password through a mutual HMAC-SHA256 challenge-response (the password itself never touches the wire), and the same key derives per-session ChaCha20-Poly1305 encryption β€” every audio packet is sealed and authenticated end-to-end, on both unicast and multicast, no PKI required. See WFAS_PROTOCOL.md.
  • Smart Auto-Connect: The app can automatically connect to prioritized IP addresses as soon as they are detected on the network, even in the background.
  • Automation & Scripting: Trigger the app from the outside via home-screen shortcuts, deep links (wifiaudio://), or broadcast intents (Tasker, MacroDroid, NFC tags). Save full server/client configurations as named, one-tap presets. External commands are refused until you enable them in Automation & Scripting, and once enabled every command coming from outside the app must carry a per-install secret token, shown on that same screen β€” the URIs and commands generated there already include it, so no other app on the device can drive the streaming. The token is sealed with an Android Keystore key that never leaves the device, and is excluded from cloud backup and device-to-device transfer, so it stays bound to the phone that generated it.
  • Widgets & Quick Settings: Control your server or client directly from your home screen using Material You widgets, or use the Quick Settings tiles in your notification shade for instant access.
  • Internal Audio Streaming: Stream your device's internal audio (apps, games, music) to other devices (requires Android 10+).
  • Automatic & Smart Manual Discovery: Clients automatically find available servers via a UDP multicast beacon (group 239.255.0.1, port 9091), and the device list badges each server as Multicast/Unicast and whether it is encrypted or requires a key. If entering an IP manually, the app automatically detects if the host is using Unicast or Multicast.
  • Network Interface Selection: Manually select your active network interface to bypass VPN routing issues or handle multiple Wi-Fi/LAN connections.
  • Server Volume Control: Adjust the transmission volume directly from the UI or by using your device's physical volume buttons while streaming.
  • Dark Screen Mode: When your phone is acting as a client, locking the screen or leaving the app lets Android throttle the background process to save battery, which can introduce audio artifacts. Dark Screen mode keeps the app active with the screen technically on, showing either a pure-black overlay or an outlined theme, ideal for OLED displays that want to look "off" without actually going to sleep.
  • Automatic Update Checker: Optionally check GitHub for new releases on startup, or trigger a manual check any time, with release notes shown right inside the app.
  • Modern Interface: Rebuilt from the ground up with Jetpack Compose and a full Material 3 Expressive redesign, featuring dynamic colors and bilingual support (EN/IT).

⚠️ Security & Encryption Notice

The optional WFAS encryption feature is provided "AS IS" and is intended primarily as a lightweight privacy and traffic-protection layer for trusted local networks (LAN/P2P).

It is not intended to provide protection against high-threat attackers, hostile networks, or security-critical environments, and it should not be relied upon as a substitute for a dedicated secure transport or other security mechanisms where stronger guarantees are required.

Users and integrators are responsible for evaluating whether WFAS's security properties and their network environment are appropriate for their intended use.

The WFAS protocol and its reference implementations are provided under the terms of their respective open-source licenses. No additional security guarantees are implied beyond those explicitly documented by the protocol and implementation.

Security issues should be reported to the project maintainers so they can be investigated and addressed in future releases.


πŸ“‘ Protocol Guide

Choose the best streaming protocol for your needs:

  • WFAS v2 (Native): Best for minimal latency and strict synchronization. Requires the app installed on both the sender and receiver. Ideal for gaming and watching videos. Optional password protection and end-to-end encryption. The wire protocol is openly documented and versioned, with a dependency-free C99 reference implementation for embedded and firmware projects: πŸ‘‰ wfas-protocol on GitHub.
  • RTP: The industry standard for external media players. Generates an .sdp file that can be opened with VLC, Kodi, or FFplay.
  • HTTP (Web): Maximum compatibility using high-efficiency hardware AAC encoding. Listen from any device with a browser. (Note: Browsers enforce internal buffering, introducing a standard 1–3 second delay).
  • Snapcast: Turn the phone into a Snapcast server so every snapclient on the network plays the same audio in lockstep. The stream protocol lives on TCP 1704 and the JSON-RPC control API on 1705, both advertised over mDNS, so Raspberry Pi and ESP32 clients, Home Assistant and the official Snapcast apps discover and manage it without any extra configuration. PCM, FLAC and Opus are all available; the sync itself is driven by chunk timestamps generated from a sample counter, so playback stays aligned across rooms.
  • DLNA / UPnP: Push the stream straight to AV receivers, soundbars and smart TVs, with no app on the other side. The app discovers renderers over SSDP, negotiates the audio format with each one through ConnectionManager::GetProtocolInfo (LPCM, WAV or AAC), then drives them over AVTransport. Selected renderers are remembered and reconnected automatically, and a watchdog re-issues playback if a device drops the stream. (Note: DLNA receivers buffer heavily β€” expect several seconds of delay, so this is meant for music, not for video or gaming).

Devices on the local network running an incompatible protocol version are now detected immediately during the handshake, both sides get a clear error instead of silently timing out.


πŸ’» Desktop Version

The project is also available for Windows and Linux!
Turn your computer into a wireless audio transmitter, receiver, or web server.

Available on GitHub
Available on GitLab


πŸš€ Quick Start

Required Permissions

  • Screen Capture (for Internal Audio): To stream internal audio, Android requires starting a temporary "screen capture" session. Only audio is recorded, no images.
  • Notifications: A persistent notification keeps the streaming service active and stable in the background.
  • Audio (Optional): RECORD_AUDIO is only requested if you manually enable the microphone streaming feature in the settings.

Sending Audio (Server Mode)

  1. Launch the app and select Send (Server).
  2. In Audio Source, enable Internal Audio.
  3. Choose your preferred protocol in the settings (WFAS, RTP, or HTTP Web).
  4. For WFAS/RTP, choose Multicast (multiple clients) or Unicast (single client). In Unicast the server serves one client at a time: while a session is running it disappears from other devices' lists, and any other device that tries to connect is told the server is busy instead of being left waiting.
  5. Optionally set an authorization mode (Off, Ask, or Key) in Server Mode β†’ Security to control who can connect, and enable encryption if you set a key.
  6. Tap Start Server.

Receiving Audio (Client Mode)

  1. Launch the app and select Receive (Client).
  2. The app will automatically search for active servers on the network.
  3. Select a server from the list to connect. If it's password-protected, you'll be prompted for the key.
  4. Fallback (Manual IP): If your router blocks discovery, type the server's IP address into the manual input field. The app will automatically configure the correct connection mode.
  5. If the server is already streaming to someone else in Unicast, the app reports "That server is already streaming to another device" right away and returns to the list.

πŸ› οΈ Building from Source

To build the project from source code:

git clone https://gitlab.com/marcomorosi.dev/wifiaudiostreaming-android.git

Open the project with Android Studio, sync the Gradle dependencies, and run.

./gradlew assembleDebug

πŸ’» Tech Stack

  • Language: Kotlin
  • UI Framework: Jetpack Compose (Material 3 + Material 3 Expressive)
  • Architecture: MVVM (Model-View-ViewModel)
  • Asynchronous Handling: Coroutines & StateFlow
  • Networking: Ktor Networking (UDP/TCP sockets, HTTP Server)
  • Audio Management: Android AudioRecord, AudioTrack, and Hardware AAC MediaCodec APIs
  • Cryptography: HMAC-SHA256 challenge-response authentication, ChaCha20-Poly1305 AEAD encryption, HKDF-SHA256 key derivation (Bouncy Castle)

β˜• Support the Project

This project is free and open-source. If it helped you as much as it helped me, consider buying me a coffee to support its ongoing development!

ko-fi


πŸ“„ License

Copyright (c) 2025-2026 Marco Morosi and contributors.

This project is licensed under the European Union Public Licence v1.2 (EUPL v1.2), except for the two sound files listed below.

You are free to:

  • Use: use the software in any circumstances and for all usage types.
  • Modify: adapt, transform, or modify the software.
  • Distribute: distribute, lend, or communicate the software to the public.
  • Commercial use: use the software for commercial purposes.

Key Obligations:

  • Copyleft: If you modify and distribute the software, you must release it under the EUPL (or, where its Article 5 allows it, under a compatible licence).
  • Attribution: You must retain all copyright, patent, and trademark notices.
  • No Warranty: The software is provided "as is", without any warranties.

For the full legal text, see the LICENSE.md file included in this repository or visit the official EUPL website.

The app is EUPL, but the WFAS v2 wire protocol is not locked up: a C reference implementation is published separately under the permissive MIT License (wfas-protocol, Β© 2026 Marco Morosi), so anyone β€” including embedded/firmware projects β€” can implement WFAS v2 freely. The copyleft protects this app; the protocol stays open.

Not under the EUPL: the sounds. app/src/main/res/raw/connection_sound.wav and app/src/main/res/raw/disconnection_sound.wav were generated with ElevenLabs on its free plan, whose terms require the attribution "elevenlabs.io" and do not allow commercial use. If you redistribute this app, or a work based on it, for a commercial purpose, remove or replace them. Sound effects: elevenlabs.io


🧩 Third-Party Software & Licenses

This app contains open-source components, each under its own licence. The complete list, with the full licence texts and NOTICE files they require, is app/src/main/res/raw/third_party_licenses.txt, also shown inside the app (Settings β†’ Open-source licenses); THIRD_PARTY_LICENSES.md summarises it.

Almost everything is under the Apache License 2.0 (AndroidX and Jetpack Compose, CameraX, Kotlin, kotlinx, Ktor, ZXing, zxing-cpp, Tink, Gson, Typesafe Config, Jansi and a few annotation libraries); Bouncy Castle and SLF4J are under MIT-style licences.

Unlike the desktop app, the Android app does not bundle FFmpeg: AAC encoding is performed by the platform's built-in MediaCodec API.

About

An Android application for streaming audio over a local network. It allows you to stream your Android device's internal audio to any device on the network. Developed in Kotlin and Jetpack Compose.

Resources

Stars

162 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages