Spritz is a nano DLNA media server for the terminal. No setup, no config.
Run it in a folder, and its video and audio files show up on the TVs, phones, and speakers on your local network.
Install:
brew install dfallman/tap/spritzNavigate to the folder your media files are in and start Spritz:
cd /mnt/nas/movies
spritz
...alternatively, run it from anywhere and specify which path(s) to serve up:
spritz /mnt/nas/movies /mnt/nas/music
DLNA clients (including most modern TVs, Apple TV (via Infuse or VLC), PS5, Xbox, Kodi, tablets, phones, and many more) should now see the Spritz share appear in their network sources within a few seconds.
- Runs from a single command,
spritz— zero config, zero state - Announces itself via SSDP/UPnP, so clients find it without typing an IP
- Serves one or more folders (recursively, subdirectories are indexed automatically) from a single instance
- Presents three browse views at the root:
Videos,Music, andBy folder(the on-disk structure) - Supports video and audio formats (MP4/MKV/AVI/MOV/... and MP3/FLAC/OGG/...)
- Implements
ContentDirectory:1andConnectionManager:1for DLNA Browse and Search - Advertises sidecar subtitles (
.srt/.vtt/.ass) next to matching media files - Advertises duration, resolution, honest DLNA profile names (from the file, not the extension), and sidecar album art (
cover.jpg/ matching stem) - Exposes an M3U playlist at
/spritzfor VLC, Infuse, and similar players - Sends
ssdp:byebyeon Ctrl+C so clients drop it immediately
Most DLNA and media servers (such as Plex, Jellyfin, Emby, MiniDLNA/ReadyMedia, Rygel, Serviio, and others) are meant to be persistent servers: that is, you install a service, point a config file at your media library, often on a NAS or similar, maintain a database, and leave it running.
Spritz is the opposite — you've downloaded a file, you point spritz opportunistically at the folder that file is in, share it for as long as you need, and Ctrl+C when done. No config files, no database, no indexing and reindexing jobs, and no background services. As we say in Australia, no dramas.
A typical use case for spritz is that you've just downloaded something you want to watch right away, for instance a football game. To make that game available with Spritz, just:
cd Downloads
spritz
So Spritz isn't a replacement for other media servers; it sits alongside them.
Spritz is built for ad hoc sharing, as in folders you don't serve every day. But it also works as a no-nonsense alternative to the heavier servers above. Point it at your NAS's media folder, leave it running, and it does its thing.
Note: Spritz reads the file tree at startup and doesn't watch it for changes. If you add files to a share, restart Spritz. Or let watchexec do it for you: watchexec -r -- spritz
brew install dfallman/tap/spritzDownload the latest archive for your platform from the Releases page. Builds are provided for:
- Linux x86_64 and aarch64
- macOS x86_64 and Apple Silicon
- Windows x86_64
Each archive ships with a .sha256 checksum.
To compile Spritz from source, you'll need Rust. Use rustup for the installation:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Once installed:
git clone https://github.com/dfallman/spritz
cd spritz
cargo install --path cliUsage: spritz [OPTIONS] [FOLDER]...
Arguments:
[FOLDER]... Folders to serve (defaults to current directory)
Options:
-p, --port <PORT> Port to listen on [default: 8080]
--bind <BIND> Address to bind (a specific interface IP on multi-homed hosts) [default: 0.0.0.0]
-n, --name <NAME> Friendly name shown to DLNA clients [default: "Spritz Media Server"]
-h, --help Print help
-V, --version Print version
# Serve the current directory
spritz
# Serve a specific folder
spritz /mnt/nas/movies
# Serve multiple folders
spritz /mnt/nas/movies /mnt/nas/tv /mnt/nas/music
# Use a different port
spritz --port 9000 /media/videos
# Bind a specific interface and set the name TVs display
spritz --bind 192.168.1.10 --name "Living Room" /media/videosOpen your TV's Media Server or Network source. Spritz should show up within a few seconds. Inside, you'll see three containers — Videos, Music, and By folder. The first two are flat lists of every file by type; By folder mirrors your on-disk directory structure so you can navigate Shows → Season 1 → ep1.mkv the way you'd expect.
Media → Open Network Stream → http://<your-spritz-server-ip>:8080/spritz, or browse via View → Playlist → Local Network → Universal Plug and Play. VLC only scans at startup and when it receives a NOTIFY packet, so if it doesn't appear, restart VLC once Spritz is already running.
Add Files → Network Share and pick Spritz Media Server from the list, or enter the M3U URL manually. Works on tvOS as well — the share browses the three-container layout described above.
Point it at http://<your-spritz-server-ip>:8080/spritz.
Note: <your-spritz-server-ip> is the IP address of the machine you run spritz on, that's the "server" here — the "client" (see above) is the device from which you play your content. To find your server's IP, use ipconfig in the Windows Command Prompt. On macOS, check System Settings → Network (or use ipconfig getifaddr en0 in a terminal). On linux, run ip addr or hostname -I.
Video
| Extension | MIME type |
|---|---|
.mp4, .m4v |
video/mp4 |
.mkv |
video/x-matroska |
.avi |
video/x-msvideo |
.mov |
video/quicktime |
.webm |
video/webm |
.flv |
video/x-flv |
Audio
| Extension | MIME type |
|---|---|
.mp3 |
audio/mpeg |
.m4a |
audio/mp4 |
.aac |
audio/aac |
.flac |
audio/flac |
.ogg, .oga, .opus |
audio/ogg |
.wav |
audio/wav |
.wma |
audio/x-ms-wma |
.aiff, .aif |
audio/aiff |
Subtitles (sidecar files next to a video/audio item; not listed as their own library entries)
| Extension | MIME type |
|---|---|
.srt |
text/srt |
.vtt |
text/vtt |
.ass, .ssa |
text/x-ssa |
| Device | Status | Notes |
|---|---|---|
| Samsung (Tizen) | Works | Requires <dc:date> on each DIDL item — included |
| LG (webOS) | Works | Device icon served at /upnp/icon.png |
| Sony / Bravia | Works | Strict about Content-Type: text/xml; charset="utf-8" — handled |
| Apple TV — Infuse (tvOS, iOS, iPadOS) | Works | Requires the full DIDL treatment for tvOS playback |
| Apple TV — VLC (tvOS, iOS, iPadOS) | Works | tvOS VLC sometimes misses SSDP; add the M3U URL manually |
| Xbox | Works | Advertises Microsoft MediaReceiverRegistrar |
DLNA is fiddly by nature, especially in combination with certain devices and operating systems (looking at you, Apple TV).
If your client can't find Spritz, check your firewall rules first (on both the server and client side, but typically the server side): SSDP needs UDP 1900 open, and HTTP needs your serving port (8080 by default).
On a VPN, Docker, or multi-homed machine, discovery may succeed while playback URLs point at the wrong address. Infuse and VLC using the M3U URL (/spritz) pick up the Host header; SSDP LOCATION tries to reply with the interface on the same subnet as the client.
IPv6-only LANs: SSDP also joins [FF02::C]:1900. When --bind is the default unspecified address, HTTP tries a dual-stack socket so IPv6 clients can fetch LOCATION. Link-local (fe80::) addresses are not advertised.
On Apple TV, Infuse tends to work better than VLC. If you're using VLC and can't find the share, you can bypass discovery entirely by pasting the M3U URL into VLC: Media → Open Network Stream → http://192.168.X.X:8080/spritz. If that plays, the server is fine and the issue is discovery.
Restart VLC once Spritz is already running as VLC only scans at startup and on NOTIFY packets.
Spritz works under WSL2 with mirrored networking. Add this to your ~/.wslconfig:
[wsl2]
networkingMode=mirroredThen open the required ports in Windows Firewall (PowerShell, running as Administrator):
New-NetFirewallRule -DisplayName "Spritz HTTP" `
-Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow
New-NetFirewallRule -DisplayName "Spritz SSDP" `
-Direction Inbound -Protocol UDP -LocalPort 1900 -Action AllowKnown issue: SSDP multicast sometimes requires elevated privileges under WSL2. If devices don't auto-discover the server, you could try granting the binary CAP_NET_RAW or (as a last resort) sudo spritz. HTTP file serving and the M3U endpoint work either way.
Spritz implements DLNA/UPnP AV directly instead of wrapping an existing library. At a glance:
- Discovery (SSDP). Sends
ssdp:aliveon IPv4 and IPv6 on startup, responds toM-SEARCH, and sendsssdp:byebyeon exit. - Device description.
GET /upnp/description.xmlreturns aMediaServer:1description advertising ContentDirectory, ConnectionManager, and Xbox MediaReceiverRegistrar. - Browse / Search (SOAP).
POST /upnp/control/contentdirectoryhandlesBrowse,Search, and related actions, exposing three root containers: Videos (flat), Music (flat), and By folder (recursive). - File serving. Each source directory is mounted at
/m/{index}/and served over HTTP with range support. Only media, sidecar-subtitle, and album-art extensions are reachable; directory listings, other files, and symlinks are not.
See ARCHITECTURE.md for the full protocol walkthrough.
I've been writing code for over 30 years, and lately LLM agent-assisted coding has rekindled my sense of awe at what's possible. This project was built in Rust using a range of tools, including Anthropic's Claude Code. For me, these tools are simply means to move faster, explore more ideas, and test those ideas and implementations more rigorously than I could on my own.
Issues and pull requests welcome. For bugs, please include your client device/OS, firewall setup, and the terminal output of spritz when the client tries to connect.
MIT — see LICENSE.