Live Radio Streaming

Embed any ShoutCast or Icecast station on your site with a single iframe, or broadcast live from your browser — mic, system audio, or both. No relay scripts, no MediaSource, no external software needed.

Running Drops. This tutorial uses Drops, a compact language that replaces curl commands. Run them via POST /exec or paste into the live editor.

How it works: ShoutCast and Icecast streams are plain HTTP audio. An <audio> element plays them directly — the browser handles all buffering natively. InfiniteOcean adds an optional metadata layer for track titles via SSE, plus a browser-based broadcast mode that uses IO blobs for audio delivery.

DJ's ShoutCast/Icecast stream URL
         |
         v
  <audio src="stream-url">   browser plays natively
         +
  IO metadata (optional)
    |- fn/radio-meta          reads ICY metadata, writes now-playing drops
    '- GET /stream/*          SSE delivers track titles to player

Browser broadcast (no stream server needed)
         |
         v
  MediaRecorder (2s chunks) → POST /blob → segment drops → SSE → AudioContext playback

1 Get Your Stream URL

You need a ShoutCast or Icecast stream URL. This is the direct URL to the audio stream — the same one you'd paste into VLC or Winamp. Examples:

If you're DJing with Virtual DJ, BUTT, or Mixxx, they can broadcast to a ShoutCast/Icecast server. The server gives you a stream URL your listeners connect to.

HTTPS required. The stream URL must be https://. Browsers block HTTP audio on HTTPS pages (mixed content). If your ShoutCast/Icecast server only supports HTTP, put a reverse proxy like Caddy in front of it to add TLS — or skip the stream server entirely and broadcast from your browser (step 5).

Don't have a stream server? You can broadcast directly from your browser (step 5) — no Icecast or ShoutCast server needed. Or use free options: ShoutCast (DNAS), Icecast (open source), or hosted services like Radio.co. For testing, use any SomaFM URL above.

2 Embed the Player

One line of HTML. Paste your stream URL as the src parameter:

html
<iframe
  src="https://view.infiniteocean.io/radio-player/?src=https://ice1.somafm.com/groovesalad-128-mp3"
  width="340" height="180"
  frameborder="0"
  allow="autoplay"
></iframe>

That's it. Click play and audio starts instantly.

The player uses a native <audio> element. The browser handles buffering, reconnection, and codec decoding automatically.

Player parameters:

Two playback modes: When src is set, the player uses a native <audio> element for Icecast/ShoutCast. When only route is set (no src), it switches to IO blob playback mode for browser broadcasts — fetching audio chunks via SSE and playing them with AudioContext.

3 Add Track Titles (optional)

The player works great without this step. But if you want live "Now Playing" titles, InfiniteOcean can read them from your stream's ICY metadata and push them to the player in real-time.

Start the metadata monitor:

drops
-- Start metadata tracking (runs for 5 minutes)
run fn/radio-meta { source: "https://ice1.somafm.com/groovesalad-128-mp3", route: "radio/live", duration: 300 } async

Returns: {"job_id": "abc123"} — the metadata monitor runs in the background, writing now-playing and status drops to your route.

Now update your embed to include the route:

html
<iframe
  src="https://view.infiniteocean.io/radio-player/?src=https://your-stream:8000/live&route=radio/live&key=YOUR_KEY"
  width="340" height="180"
  frameborder="0"
  allow="autoplay"
></iframe>

The player subscribes to SSE on that route and updates the track title in real-time.

For continuous 24/7 metadata tracking, schedule it with cron:

drops
-- Restart metadata monitor every 5 minutes
cron "*/5 * * * *" radio-meta: run fn/radio-meta { source: "https://your-stream:8000/live", route: "radio/live", duration: 300 }

4 Verify It Works

Check that metadata is appearing:

drops
-- Check station status
read radio/live @status

-- Check now-playing
read radio/live @now-playing

HTTP only. SSE streams use a persistent HTTP connection — use curl -N or EventSource in JavaScript.

bash
# Watch live metadata via SSE
curl -N "https://api.infiniteocean.io/stream/radio/live?_key=YOUR_KEY"

Status: {"live": true, "bitrate": 128, "station": "Groove Salad"}

Now playing: {"title": "Tycho - A Walk", "timestamp": 1709438400}

5 Broadcast from Your Browser

Don't have a ShoutCast or Icecast server? You can broadcast directly from your browser — just your microphone, system audio, or both. No external software needed.

Open the broadcast page:

url
https://view.infiniteocean.io/radio-broadcast/

Sign in with your email (magic link), and you're ready to go. A personal route is assigned automatically based on your account — or set a custom one in the route field.

The broadcast page lets you:

How it works: The browser captures audio with MediaRecorder (2-second standalone chunks, Opus codec at 64kbps). Each chunk is uploaded as an IO blob, then a segment drop is written to your route. The player picks up these segment drops via SSE, fetches the audio blobs, and decodes them with AudioContext for gapless playback.

Share the player link with your listeners — note there's no src parameter, just the route:

html
<iframe
  src="https://view.infiniteocean.io/radio-player/?route=radio/my-show&name=My%20Station"
  width="340" height="180"
  frameborder="0"
  allow="autoplay"
></iframe>

When only route is set (no src), the player automatically uses IO blob playback. Listeners hear your broadcast within ~4 seconds.

6 Customize

Ideas to extend your radio setup:

Cost: The player and SSE connections are completely free. Only the metadata function uses compute (a few io per run). Browser broadcasting costs 1 io per 100 KB of audio uploaded (roughly 4 io per minute at 64kbps).