A dead simple Icecast transmission library for Go, with support for in-band metadata.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-23 16:44:13 +09:30
internal/icy Fix regressions with new API and add Start and Stop 2026-09-23 16:44:13 +09:30
go.mod Change import path yet again 2026-04-28 22:42:32 +09:30
go.sum Switch to using ffmpeg for transcoding 2026-03-11 21:46:08 +10:30
icy.go Fix regressions with new API and add Start and Stop 2026-09-23 16:44:13 +09:30
LICENSE Initial commit 2026-03-11 00:04:51 +10:30
README.md Add IcyPlayer methods 2026-09-23 10:49:57 +09:30

icy

A dead simple Icecast transmission library for Go, with support for in-band metadata. Icy will figure out the song's title from id3v2 tags in MP3s, or use the filename as a fallback. This behaviour can be changed with SetTitleHandler.

Icy supports whatever input files ffmpeg can transcode. Incidentally, ffmpeg has to be available on the system path for it to work. The original solution decoded MP3 files using a pure Go library, but it didn't work very well.

Icy uses ffmpeg to transcode all input files into a 44.1kHz/192kb double channel MPEG stream.

Installation

go get flipfloppy.io/icy

API

See the pkgsite documentation.

Examples

// shuffle on all MP3 files in every subdirectory of mysongs
icy.Shuffle("./mysongs/*/*.mp3", icy.RadioDetails{})

// play all M4A files in the current directory in order
icy.Play("*.m4a", icy.RadioDetails{})

// shuffle all FLAC files in the current directory on every day except Tuesday.
// On Tuesdays, play WAV files from "special songs" that begin with "tue".
icy.Shuffle("*.flac", icy.RadioDetails{
  Schedule: map[string]string{"Tuesday": "./special songs/tue*.wav"},
})

// shuffle on all Ogg Vorbis files in the current directory,
// except on the 22nd of every month. On the 22nd between 2-3AM/PM,
// play from the "nyan nyan" directory.
icy.Shuffle("*.ogg", icy.RadioDetails{
  Schedule: map[string]string{"22 2:00-2:59 2pm-3pm": "./nyan nyan/*.mp3"},
})

// play all MP3s in the current directory on every day apart from christmas.
// play MP3s in "christmas songs" on christmas.
icy.Play("*.mp3", icy.RadioDetails{
  Schedule: map[string]string{"December 25": "./christmas songs/*.mp3"},
})

Examples (IcyPlayer)

icy.Shuffle and icy.Play return an icy.IcyPlayer, which implements http.Handler but also has some functions for querying and modifying the player while it runs.

player, err := icy.Shuffle("./default/*.mp3")

// player.CurrentSong() returns the path to the currently playing song.
// If you want the title of the song as icy sees it,
// you can get a handle to the file and run it through DefaultTitleHandler.
fmt.Printf("currently playing %q!\n", player.CurrentSong())

// player.SetFallback will set the new fallback for the radio.
// It applies after the current song ends,
// so you don't have to worry about the song suddenly cutting out.
player.SetFallback("./not default/*.mp3")

// You can also add schedules!
// This also takes effect after the current song ends.
player.ScheduleAdd("Thursday", "./different songs/*")

// Schedule returns a copy of the current schedule,
// in the form you would pass into icy.RadioDetails.
player.Schedule()