radio

package
v2.22.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 10, 2026 License: GPL-3.0 Imports: 30 Imported by: 0

Documentation

Overview

Package radio plays internet radio: Icecast and Shoutcast streams, pls and m3u playlists of them, and audio HLS. A background goroutine owns the network and the decoder and fills a bounded buffer of PCM, so the audio player reading a Stream never waits on the network.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrLive is returned by Stream.Seek: a live stream has no positions.
	ErrLive = errors.New("radio: live streams cannot seek")
	// ErrUnsupported is a stream in a codec or format this package does not
	// play, such as Opus.
	ErrUnsupported = errors.New("radio: unsupported stream format")
	// ErrTooLarge is a response bigger than its limit.
	ErrTooLarge = errors.New("radio: response too large")
	// ErrClosed is returned once a Stream is closed.
	ErrClosed = errors.New("radio: stream closed")
)

Functions

func NewHTTPClient

func NewHTTPClient() *http.Client

NewHTTPClient returns the client radio uses: the Zaparoo User-Agent, the configured TLS roots, bounded dial, TLS and header waits, at most ten redirects, and plain http allowed, as many radio stations still serve it. It reads Shoutcast v1 servers, which answer "ICY 200 OK" instead of an HTTP status line. There is no overall timeout: a stream is endless. It is meant for audio only.

Types

type Kind

type Kind int

Kind is what a probed URL serves.

const (
	// KindNotAudio is anything this package cannot play, such as a web page.
	KindNotAudio Kind = iota
	// KindStream is a direct Icecast or Shoutcast stream of MP3, AAC or Ogg
	// Vorbis.
	KindStream
	// KindHLS is an HTTP Live Streaming playlist.
	KindHLS
	// KindPlaylist is a pls or m3u playlist of stream URLs.
	KindPlaylist
)

func (Kind) String

func (k Kind) String() string

type Options

type Options struct {
	// OnMeta is called with the new title whenever the stream announces
	// one (ICY StreamTitle, HLS ID3 tags). It runs on the network
	// goroutine, so it must not block or call Close.
	OnMeta func(title, artist string)
	// HTTPClient makes every request; nil uses NewHTTPClient.
	HTTPClient *http.Client

	// ResourceConstrained picks the lowest bandwidth HLS variant.
	ResourceConstrained bool
	// contains filtered or unexported fields
}

Options configures Open.

type Probe

type Probe struct {
	// contains filtered or unexported fields
}

Probe is a URL opened and classified by ProbeURL. A stream probe holds its response open so Open can play from it without connecting again.

func ProbeURL

func ProbeURL(ctx context.Context, c *http.Client, rawURL string) (*Probe, error)

ProbeURL requests rawURL, with ICY metadata asked for, and classifies the response by Content-Type, sniffing its first bytes when the type is generic. ctx bounds only the request, headers and sniffing: the stream response the probe keeps is not tied to it, so the caller may cancel ctx once ProbeURL returns. A KindNotAudio probe is still open; Close it.

func (*Probe) Close

func (p *Probe) Close()

Close releases the probe's connection. It is idempotent and safe on nil.

func (*Probe) Kind

func (p *Probe) Kind() Kind

Kind is what the URL serves.

func (*Probe) Name

func (p *Probe) Name() string

Name is the station name the server sent, or "" when it sent none.

func (*Probe) URL

func (p *Probe) URL() string

URL is the URL after redirects.

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream is a playing radio stream: a beep.StreamSeekCloser whose audio a background goroutine reads from the network, decodes and buffers. Stream never blocks on the network.

func Open

func Open(ctx context.Context, p *Probe, opts Options) (*Stream, error)

Open starts playing a probed stream and takes ownership of p. It resolves a playlist to the first entry that plays, and returns once audio is decoded, so the sample rate is known; ctx bounds only that wait. It reuses the probe's connection when it is still usable.

func (*Stream) Buffered

func (s *Stream) Buffered() int

Buffered is how many frames Stream can return now. Once no more audio will arrive it is larger, so a reader pulling at most Buffered frames also reaches the end.

func (*Stream) Close

func (s *Stream) Close() error

Close stops the stream and waits for its goroutine. It is safe to call more than once and while the network is blocked.

func (*Stream) Err

func (s *Stream) Err() error

Err is why the stream stopped, or nil while it plays, after a clean end and after Close.

func (*Stream) Len

func (*Stream) Len() int

Len is -1: a live stream has no length.

func (*Stream) Live

func (*Stream) Live() bool

Live is true: a radio stream plays in real time.

func (*Stream) Name

func (s *Stream) Name() string

Name is the station name the server or playlist gave, or "".

func (*Stream) Position

func (s *Stream) Position() int

Position is how many frames Stream has returned.

func (*Stream) Resume

func (s *Stream) Resume()

Resume reconnects a suspended stream at the live point.

func (*Stream) SampleRate

func (s *Stream) SampleRate() int

SampleRate is the rate of the frames Stream returns, fixed for the life of the stream.

func (*Stream) Seek

func (*Stream) Seek(int) error

Seek fails with ErrLive.

func (*Stream) Stream

func (s *Stream) Stream(samples [][2]float64) (int, bool)

Stream copies buffered audio into samples. It never waits: with nothing buffered it returns (0, true). It returns (0, false) once the stream is closed, or has ended or failed for good (see Err) and the buffered audio is used up.

func (*Stream) Suspend

func (s *Stream) Suspend()

Suspend drops the connection and the buffered audio, as for a pause.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL