README
DudelDu
DudelDu is a simple audio/video streaming server using the SHOUTcast protocol.
Features
- Supports various streaming clients: VLC, ServeStream, ... and most Icecast clients.
- Supports sending of meta data (sending artist and title to the streaming client).
- Playlists are simple JSON files and data files are normal media (e.g.
.mp3
,.nsv
) files on disk. - Can be used as a stand-alone server or embedded in other Go projects.
- Supports HTTP basic user authentication.
Getting Started (standalone application)
You can download a pre-compiled package for Windows (win64) or Linux (amd64) here.
You can also pull the latest docker image of DudelDu from Dockerhub:
docker pull krotik/dudeldu
Create an empty directory, change into it and run the following to start DudelDu:
docker run --rm --user $(id -u):$(id -g) -v $PWD:/data -p 9091:9091 krotik/dudeldu -host 0.0.0.0 <playlist>
The container will have access to the current local directory and all subfolders.
Demo
DudelDu comes with a demo playlist. After extracting DudelDu switch to the directory examples/demo
. Run ./run_demo.sh (Linux) or run_demo.bat (Windows) to start the server.
Open a browser and view the demo.html
in the examples/demo
directory. To access the demo streams you are prompted for a username and password. The credentials are:
username: web
password: web
You can also point your favourite audio streaming client (e.g. VLC) to the streaming URL:
http://localhost:9091/bach/cello_suite1
The demo includes also a small video in the Nullsoft Streaming Video format (NSV). To see it point a video streaming client (e.g. VLC) to:
http://localhost:9091/trailer/big_buck_bunny
Note: By default you can only reach the streams via localhost. Use the -host parameter with a host name or IP address to expose it to external network peers.
Command line options
The main DudelDu executable has the following command line options:
DudelDu x.x.x
Usage of ./dudeldu [options] <playlist>
-? Show this help message
-auth string
Authentication as <user>:<pass>
-debug
Enable extra debugging output
-fqs int
Frame queue size (default 10000)
-host string
Server hostname to listen on (default "127.0.0.1")
-loop
Loop playlists
-port string
Server port to listen on (default "9091")
-pp string
Prefix all paths with a string
-shuffle
Shuffle playlists
-tps int
Thread pool size (default 10)
Authentication can also be defined via the environment variable: DUDELDU_AUTH="<user>:<pass>"
Building DudelDu
To build DudelDu from source you need to have Go installed (go >= 1.12):
Create a directory, change into it and run:
git clone https://devt.de/krotik/dudeldu/ .
You can build DudelDu's executable with:
go build ./server/dudeldu.go
Building DudelDu as Docker image
DudelDu can be build as a secure and compact Docker image.
- Create a directory, change into it and run:
git clone https://devt.de/krotik/dudeldu/ .
- You can now build the Docker image with:
docker build --tag krotik/dudeldu .
License
DudelDu source code is available under the MIT License.
Documentation
Overview ¶
Package dudeldu is a simple audio streaming server using the SHOUTcast protocol.
Server ¶
Server is the main server object which runs a shoutcast server instance.
Using a WaitGroup a client can wait for the start and shutdown of the server. Incoming new connections are served with a ConnectionHandler method. The default implementation for this is the HandleRequest method of the DefaultRequestHandler object.
DefaultRequestHandler ¶
DefaultRequestHandler is the default request handler implementation for the DudelDu server. DefaultRequestHandler has a customizable ServeRequest function. ServeRequest is called once a request was successfully decoded.
The default implementation supports sending meta data while streaming audio. The metadata implementation is according to:
http://www.smackfu.com/stuff/programming/shoutcast.html
Playlists ¶
Playlists provide the data which is send to the client. A simple implementation will just read .mp3 files and send them in chunks (via the Frame() method) to the client.
A request handler uses a PlaylistFactory to produce a Playlist for each new connection.
Index ¶
Constants ¶
const FrameSize = 3000
FrameSize is the suggested size of a frame which should be send to the client at a time.
The absolute theoretical maximum frame size for a MPEG audio is 2881 bytes:
MPEG 2.5 Layer II, 8000 Hz @ 160 kbps, with a padding slot. Theoretical frame sizes for Layer III range from 24 to 1441 bytes there is a "soft" limit imposed by the standard of 960 bytes.
see: http://www.mars.org/pipermail/mad-dev/2002-January/000425.html
const MaxRequestSize = 1024
MaxRequestSize is the maximum size for a request
const ProductVersion = "1.3.1"
ProductVersion is the current version of DudelDu
Variables ¶
var ErrPlaylistEnd = errors.New("End of playlist")
ErrPlaylistEnd is a special error code which signals that the end of the playlist has been reached
var MaxMetaDataSize = 4080
MaxMetaDataSize is the maximum size for meta data (everything over is truncated)
Must be a multiple of 16 which fits into one byte. Maximum: 16 * 255 = 4080
var MetaDataInterval uint64 = 65536
MetaDataInterval is the data interval in which meta data is send
Functions ¶
Types ¶
type ConnectionHandler ¶
ConnectionHandler is a function to handle new connections
type DebugLogger ¶
type DebugLogger interface { /* IsDebugOutputEnabled returns true if debug output is enabled. */ IsDebugOutputEnabled() bool /* PrintDebug will print debug output if `DebugOutput` is enabled. */ PrintDebug(v ...interface{}) }
DebugLogger is the debug logging interface of the Server
type DefaultRequestHandler ¶
type DefaultRequestHandler struct { PlaylistFactory PlaylistFactory // Factory for playlists ServeRequest func(c net.Conn, path string, metaDataSupport bool, offset int, auth string) // Function to serve requests LoopTimes int // Number of loops -1 loops forever // contains filtered or unexported fields }
DefaultRequestHandler data structure
func NewDefaultRequestHandler ¶
func NewDefaultRequestHandler(pf PlaylistFactory, loop bool, shuffle bool, auth string) *DefaultRequestHandler
NewDefaultRequestHandler creates a new default request handler object.
func (*DefaultRequestHandler) HandleRequest ¶
func (drh *DefaultRequestHandler) HandleRequest(c net.Conn, nerr net.Error)
HandleRequest handles requests from streaming clients. It tries to extract the path and if meta data is supported. Once a request has been successfully decoded ServeRequest is called. The connection is closed once HandleRequest finishes.
func (*DefaultRequestHandler) SetDebugLogger ¶
func (drh *DefaultRequestHandler) SetDebugLogger(logger DebugLogger)
SetDebugLogger sets the debug logger for this request handler.
type Playlist ¶
type Playlist interface { /* Name is the name of the playlist. */ Name() string /* ContentType returns the content type of this playlist e.g. audio/mpeg. */ ContentType() string /* Artist returns the artist which is currently playing. */ Artist() string /* Title returns the title which is currently playing. */ Title() string /* Frame returns the current audio frame which is playing. */ Frame() ([]byte, error) /* ReleaseFrame releases a frame which has been written to the client. */ ReleaseFrame([]byte) /* Finished returns if the playlist has finished playing. */ Finished() bool /* Close any open files by this playlist and reset the current pointer. After this call the playlist can be played again unless an error is returned. */ Close() error }
Playlist is an object which provides a request handler with a constant stream of bytes and meta information about the current playing title.
type PlaylistFactory ¶
type PlaylistFactory interface { /* Playlist returns a playlist for a given path. */ Playlist(path string, shuffle bool) Playlist }
PlaylistFactory produces a Playlist for a given path.
type Server ¶
type Server struct { Running bool // Flag indicating if the server is running Handler ConnectionHandler // Handler function for new connections DebugOutput bool // Enable additional debugging output LogPrint func(v ...interface{}) // Print logger method. // contains filtered or unexported fields }
Server data structure
func NewServer ¶
func NewServer(handler ConnectionHandler) *Server
NewServer creates a new DudelDu server.
func (*Server) IsDebugOutputEnabled ¶
IsDebugOutputEnabled returns true if debug output is enabled.
func (*Server) PrintDebug ¶
func (ds *Server) PrintDebug(v ...interface{})
PrintDebug will print debug output if `DebugOutput` is enabled.
func (*Server) Run ¶
Run starts the DudelDu Server which can be stopped via ^C (Control-C).
laddr should be the local address which should be given to net.Listen. wgStatus is an optional wait group which will be notified once the server is listening and once the server has shutdown.
This function will not return unless the server is shutdown.