Skip to content

Streaming Zones

A streaming zone broadcasts audio over the network instead of playing it to a device channel. The zone's mix — with its volume, EQ, and compressor applied — is encoded to MP3 or Opus and served as an internet-radio stream that listeners can open in VLC, a browser, or any radio app.

Everything else about a zone is unchanged: players route to it through the matrix, jingles duck it, and the scheduler can control it. Only the output differs.

Streaming zones require the Streaming license feature.

A streaming zone has two delivery modes, and you can use either or both:

  • Built-in server — MZAP serves listeners directly. They open http://<pc>:<port>/ and hear the zone. No extra software is needed, but the stream is only reachable from networks that can reach this PC.
  • Cast to Icecast/Shoutcast — MZAP pushes the stream to an external server, which then distributes it. Use this for internet-facing streams, or when you need more listeners than one PC should serve.

At least one of the two must be enabled.

In the Zones view, the Create button is a dropdown:

  • Device zone — the standard zone bound to a device channel.
  • Streaming zone… — a broadcast zone.

The streaming zone form asks for:

SettingNotes
CodecMP3 (default) works with every client. Opus gives better quality per bitrate on modern clients.
BitrateDefault 192 kbps. Range 32320.
Station nameSent to listeners as station metadata. Falls back to the zone name when blank.
Built-in serverOn by default.
Server portDefault 8600. Range 102465535, and must be unique across your streaming zones. MZAP suggests the next free port.
Cast to external serverOff by default. When on, supply the host (no http://), port, mount point (e.g. /mzap, blank for Shoutcast v1), and the source password.
Send now-playing metadataOn by default.

The cast password is saved with the zone in your workspace file and is never returned by the API — the zone response always masks it.

A streaming zone's detail view has an On-Air section showing its broadcast state:

  • On Air — the built-in server is accepting listeners and/or the cast connection is up.
  • Reconnecting — the cast connection dropped and is being retried with backoff. The built-in server keeps serving its listeners throughout, so local listeners hear no interruption.
  • Offline — not broadcasting; the encoder chain is not built or is being rebuilt.
  • Error — the encoder chain could not be built.

Error and Reconnecting states name the reason next to the badge — "Streaming requires a license upgrade", "Port 8600 unavailable", "Encoder start failed", and so on. The reason survives a page reload, so a failure that happened at startup before any browser connected is still explained when you look.

The listen URLs, the firewall guidance, and the listener count are hidden while a zone is in Error or Offline, since nothing is bound to the port in those states and the link could only produce a connection-refused error. They stay visible while Reconnecting.

The built-in server binds all network interfaces, so phones and laptops on the same network can listen. The On-Air panel lists a listen URL per network interface (e.g. http://192.168.1.20:8600/), best candidate first, each with a copy button.

Windows Firewall blocks the port by default, and the failure is silent — the connection is simply refused with nothing logged. The On-Air panel has a collapsed "Not reachable from other devices?" helper with the exact command. Run it once in an elevated PowerShell:

Terminal window
New-NetFirewallRule -DisplayName "MZAP Streaming Zones" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8600 -Profile Private
  • Running several streaming zones? Use a port range instead: -LocalPort 8600-8610.
  • The rule is scoped to Private networks. Widen the profile only if you understand the exposure.

The On-Air panel shows the number of connections reported by the streaming server. Two things make that count higher than the number of people listening:

  • A browser may open more than one connection to the same stream.
  • MZAP itself counts as a listener when a player is pointed at the zone's own stream URL. That is a supported setup — you can re-consume a streaming zone as a player source to monitor the broadcast, or to re-broadcast it elsewhere.

Listeners hear audio 2–10 seconds behind live. This is inherent to buffered internet radio and is not a fault.

A streaming zone is radio-style distribution, not synchronized multiroom audio. Do not use a streaming zone and a device zone to feed speakers in the same physical space — they will be audibly out of step.

Renaming a streaming zone, or changing its stream settings, rebuilds the encoder chain. Connected listeners are dropped and must reconnect.

The zone name and the station name are separate fields. Renaming the zone does not change the station name that listeners see — edit that in the zone's stream settings.

Metadata sent to listeners is encoded so that non-Latin names survive.

  • Track titles and station names on the cast output are sent as UTF-8. A station named "Це тестова зона" reaches listeners intact, where previously non-Latin text arrived as rows of ? and the original was unrecoverable. Verified against Icecast 2.4.
  • The built-in server sends the station name (from Station name, or the zone name when blank), so players such as VLC show it in place of a bare URL. It is sent in ISO-8859-1 as the ICY protocol requires — a name with no Latin-1 equivalent falls back to ?.
  • MZAP also reads stream metadata correctly: a player tuned to an internet radio station shows non-Latin station names and track titles properly. It tries UTF-8 first and falls back to ISO-8859-1, so both modern and legacy stations display correctly.

Now-playing metadata follows the most recently started player routed to the zone.

Streaming zones react to license changes immediately — no restart needed:

  • Activating a license, re-checking it, starting a trial, loading an offline .lic file, or deactivating all re-evaluate streaming zones whenever that changes whether Streaming is entitled.
  • A zone held back by a missing entitlement comes on air as soon as the entitlement arrives.
  • Removing the entitlement takes running zones off air rather than letting them broadcast until the next restart.
  • A license check that leaves the entitlement unchanged does not disturb running zones.

Opening the stream settings of an existing streaming zone on a license that no longer includes streaming explains that streaming is not included, instead of presenting a form that cannot be saved.

Streaming zones are saved and restored with the workspace like any other zone. Because they broadcast over the network and are not bound to an audio device, they are skipped by the pre-load device check — a workspace containing streaming zones no longer triggers a spurious "Devices Offline" warning.

EndpointPurpose
POST /api/zonesAccepts kind: "stream" plus a streamSettings object.
PUT /api/zones/{id}/stream-settingsUpdate an existing streaming zone's broadcast settings.
GET /api/zones/suggest-stream-portNext free built-in-server port.

Zone responses gain kind, streamSettings, streamState, listenerCount, listenUrls (one URL per LAN address; empty when the built-in server is disabled, the host has no LAN address, or the zone is in Error/Offline), and streamError (null for healthy and non-streaming zones).

The SSE event stream at /api/stream/events emits StreamZoneStatusChangedEvent as a zone's broadcast state changes.