Skip to content

Repository files navigation

🎵 Radio Player HTML5 — Free Web Radio Player for Your Website

Live Demo License: AGPL-3.0 No API Key PWA Ready Docker

▶ Try the live demo — a modern, dependency-free HTML5 radio player for any stream (Icecast, Shoutcast, Zeno.FM, RadioJar, Azuracast and more): the album art of the current song becomes a blurred full-page backdrop, with glass-style circular controls on top. Now playing metadata, album art, song lyrics, recently played history, YouTube clip mode and installable PWA — no Bootstrap, no jQuery, no API key. Just HTML, CSS and vanilla JavaScript.

🇧🇷 Player de rádio online para o seu site — grátis e sem chave de API. Mostra a música tocando agora com capa do álbum, letra da música, histórico das últimas tocadas e até o clipe do YouTube sincronizado com a rádio. Compatível com Icecast, Shoutcast, Zeno.FM e Azuracast. É só editar duas linhas e hospedar em qualquer servidor (ou de graça na Vercel/Netlify/GitHub Pages) — ou subir com Docker em um comando, configurando tudo por variável de ambiente.

Demo Screenshots

Demo Screenshot

Features

Now playing

  • Live song metadata via the twj.es API, with automatic fallback to an alternative endpoint in case of error
  • Smart metadata parsing — ICY streams that send "Artist - Title" as one string are split correctly, so the artist name is never duplicated on screen
  • Album art delivered straight by the API (albumArt), with search.php + iTunes as fallbacks — no wrong covers from fuzzy matches
  • Blurred full-page backdrop generated from the current cover (1500x1500)
  • Lyrics via lyrics.ovh with LRCLIB fallback — no API key required, with request caching

Recently played

  • The 4 most recent songs, with covers from the search API (iTunes as fallback, filtered to music only)
  • The song currently playing is filtered out of the list (no duplicates)
  • 🎬 Clickable history: songs with a known music video show a play badge — click the card to watch the clip of a song that already played (one-off playback: the radio pauses while it plays and resumes when it ends or you pause it; it does not turn clip mode on)
  • With clip mode ON, a history clip plays to the end and then the player returns to the video programming (the current song's clip) by itself

🎬 Clip mode (music video of the current song)

  • When the metadata API returns a youtubeId in the now-playing payload, a clip button automatically appears (feature-detected)
  • Turned on, the music video takes the place of the album art, synchronized with the radio position (start = elapsed)
  • Every song change swaps the embed; songs without a clip fall back to the radio automatically
  • Pausing the video resumes the radio, playing it again pauses the radio — no external library (YouTube IFrame postMessage)

Player

  • Smooth volume fade in/out on play/pause (no audio "pop")
  • Loading spinner while the stream buffers
  • Automatic reconnection with backoff when the network drops
  • Volume as a circular button with a slider popover (desktop; on mobile the hardware buttons rule)
  • Media Session integration (lock screen / notification controls with artwork)
  • Keyboard shortcuts (see below)

App

  • Responsive design — mobile-first single column, side-by-side layout on desktop
  • Progressive Web App (PWA) with an "Install app" button when the browser allows it
  • Accent color and surfaces themeable via CSS variables
  • Single-file configuration in config.js — no need to touch the player source
  • 🐳 Docker image ready for self-hosting, fully configurable by environment variables (see below)

How do I add this radio player to my website?

Open config.js and edit the lines below:

window.RADIO_CONFIG = {
    // RADIO NAME
    RADIO_NAME: 'Your Radio Name',

    // Change Stream URL Here. Supports ICECAST, ZENO, SHOUTCAST, RADIOJAR and any other stream service.
    URL_STREAMING: 'https://stream.zeno.fm/yn65fsaurfhvv',
};

The metadata API URLs are derived from URL_STREAMING automatically. If config.js is missing, the player falls back to the defaults in js/script.js.

Change Logo

Open the img folder and add your logo named cover.png (it is used as the fallback cover, favicon and PWA icon).

Customizing the Look

All the design tokens live at the top of css/style.css as CSS variables — change the accent color, surfaces and radius in one place:

:root {
    --accent: #00e1e7;   /* accent color (slider, live dot glow, focus rings) */
    --bg: #0b0e13;       /* page background */
    --surface: rgba(255, 255, 255, 0.06);  /* glass surfaces */
    --border: rgba(255, 255, 255, 0.12);   /* glass borders */
    --radius: 20px;      /* card corner radius */
}

Installation

Just put the files in your server, run the Docker image, or use Free Hosting:

Deploy with Vercel Deploy to Netlify

🐳 Docker

Self-hosting? Run it in one line — no need to clone the repo or edit any file:

docker run -d -p 8080:80 \
  -e RADIO_NAME="My Radio" \
  -e URL_STREAMING="https://stream.zeno.fm/yn65fsaurfhvv" \
  --name radioplayer ghcr.io/jailsonsb2/radioplayer:latest

The player is at http://localhost:8080. Or with Docker Compose — see docker-compose.yml:

docker compose up -d

Environment variables

Variable Default Description
RADIO_NAME Jailson Web Rádio Radio name (header, page title, PWA)
URL_STREAMING Zeno.FM demo stream Stream URL (Icecast, Shoutcast, Zeno.FM, Azuracast...)
API_URL derived from the stream Only if you run your own metadata API
FALLBACK_API_URL derived from the stream Fallback metadata endpoint
ACCENT_COLOR #00e1e7 Accent color (--accent)
BG_COLOR #0b0e13 Page background (--bg)
THEME_COLOR #0b0e13 PWA theme color
PWA_NAME same as RADIO_NAME App name on install
PWA_SHORT_NAME same as PWA_NAME Short name (home screen icon)

The container generates config.js and manifest.json from these on startup, so changing a variable and restarting is enough — no rebuild required.

Your own logo — mount it over the default cover:

-v ./my-logo.png:/usr/share/nginx/html/img/cover.png:ro

Building locally instead of pulling the image:

docker build -t radioplayer .

Notes

  • Built for linux/amd64 and linux/arm64 — Raspberry Pi and ARM NAS included. Image size ≈ 76 MB (nginx alpine + ~1.7 MB of player files).
  • Ships a HEALTHCHECK, so Portainer / Unraid / docker ps show the real container health.
  • Everything is served over plain HTTP on port 80 inside the container. Put it behind a reverse proxy with HTTPS if you expose it to the internet — browsers block the PWA install prompt and the Media Session API on insecure origins.
  • The full album art, lyrics and now playing metadata still come from the public APIs listed in Data Sources — the container serves the player, not the metadata.

Progressive Web App (PWA)

When the browser signals that installation is available, an "Install app" button appears (top-right on desktop, bottom of the screen on mobile).

Note: the service worker fetches the HTML and config.js from the network first, so a configuration change reaches returning visitors on the next load. After a bigger update (CSS/JS), still bump the cache version in service-worker.js (CACHE_NAME) to force everything to refresh at once.

Configuring Radio Name and Colors (PWA)

Edit the manifest.json file:

  1. Locate the "name" field and replace it with the name of your radio.
  2. If desired, customize "background_color" and "theme_color" to match your branding.
{
  "name": "Your Radio Name",
  "short_name": "Radio Player",
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#0b0e13",
  "theme_color": "#0b0e13",
  "icons": [
    {
      "src": "img/cover.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ]
}

Supported Hosting Types

  • Icecast / Shoutcast
  • Zeno Radio
  • RadioJar
  • Azuracast
  • Centova Cast
  • Everest Cast
  • MediaCP
  • Sonic Panel

Data Sources

  • twj.es — now playing metadata, song history and album art
  • Apple Music / iTunes — cover art fallback
  • lyrics.ovh + LRCLIB — lyrics

Keyboard Controls

  • M - mute/unmute
  • P and space - play/pause
  • arrow up and arrow down - increase/decrease volume
  • 0 to 9 - volume percent

Related Projects

More free radio players from the same author — pick the style that fits your station:

Project Style
Radioplayer_api Multi-station player with 3 switchable layouts (Retrô Glass, Clássico, Aurora Deck)
bottom_radioplayer Bottom-bar component for websites — the audio never stops while visitors navigate
Radioplayer_html5 Multi-station HTML5 player with API now playing
RadioPlayer-ZenoRadio Full-page player for Zeno.FM streams (SSE metadata)
metadados The free now playing API used by these players (ICY metadata + iTunes + YouTube clips)

Feedback

If you have any feedback, please reach out to me at contato@jailson.es


⚖️ License

This project is licensed under the GNU AGPL-3.0 (see LICENSE): you are free to use, modify and redistribute it — including commercially — provided derivative works remain open source and keep the original copyright notices, even when offered only as a hosted/network service.

Closed-source / commercial licensing: to embed this code in a proprietary product without AGPL obligations, a separate commercial license is available — contact contato@jailson.es.

Copyright (C) 2024-2026 Jailson Bezerra (@jailsonsb2)

About

🎵 HTML5 Radio Player for websites — Icecast, Shoutcast, Zeno.FM & Azuracast. Now playing, album art, lyrics, PWA. Player de rádio online para seu site, grátis e sem API key.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages