Add support for HTTP audio output streaming #56

Open
jodal opened this Issue Jan 19, 2011 · 10 comments

6 participants

@jodal
Mopidy member

If one provided a stream of the audio played by Mopidy over HTTP, it could be used by both MPD clients with support for HTTP streams and devices like e.g. Squeezeboxes.

The stream encoding should probably be Ogg Vorbis and/or MP3.

@adamcik
Mopidy member

Asssuming the follwing code:

import logging
from BaseHTTPServer import BaseHTTPRequestHandler

from mopidy import get_version

logger = logging.getLogger('mopidy.outputs.http')

class StreamingHTTPRequestHandler(BaseHTTPRequestHandler):
    server_version = 'HTTPOutput/%s' % get_version()

    def do_GET(self):
        self.send_response(200)
        self.send_header('content-type', 'audio/mpeg')
        self.end_headers()

        register_fd_with_output(self.wfile.fileno())

        self.close_connection = 0

    def log_message(self, format, *args):
        logger.info(format, *args)

where register_fd_with_output() is a function that emits the add signal on the fd sink in a HTTPOutput (audioconvert ! lame ! multifdsink) and we have a BaseHTTPServer.HTTPServer running in a ThreadingActor with the StreamingHTTPRequestHandler we should have working HTTP streaming.

For additional features like metadata the following links should be useful:

@adamcik
Mopidy member

The code above should probably not be used for solving this issue. With the current state of the code base we want something that builds on cherrypy.

First thing that needs to be done is to create and register a GStreamer element we can use in the OUTPUT setting. Using the mixers, the code in #152 or Pitivi examples should be enough to get started. The element will basically be wrapping a multifdsink, handling the cherrypy stuff and passing the FDs between them.

As for the HTTP part, there is at least to ways of going about it. First one is probably the easiest, start an independent cherrypy server to the frontend one and use that. The second one, the one I think we want is having a singleton HTTP server shared between the frontend and streaming parts of the code. This part is currently the big unknown as far as I am concerned.

Once a HTTP server is in place we need to detach the socket from cherrypy, looking at ws4py it seems setting request.rfile.rfile._sock = None is the most likely workaround we can manage. Before we detach we probably want to emit some headers, then we detach and emit the fd to the sink and we should be streaming. Looking at how ws4py takes over sockets should enable us to figure out the details.

Other part the is slightly unknown is if we extend our core audio API to allow for emitting the FDs. That is either something specialized for just that case or something more general that gives access to the output bin we are using.

@adamcik
Mopidy member

Why I never thought of this earlier I have no idea, but as for stealing sockets, we should just us socket.fromfd to create new copy so that the original can be closed with no ill effects.

@jodal jodal added this to the v0.20 - Audio and mixer cleanup milestone Jun 22, 2014
@adamcik adamcik removed this from the v0.20 - Audio cleanup milestone Jun 23, 2014
@PlasmaPower

Are there plans to add output streaming in the near future?

@KittyKatt

I know this is months old, but this is the only thing holding me back from switching from vanilla MPD. I run MPD on my server, which has no speakers attached, and tune in to the HTTP stream from various computers/devices around the house and elsewhere. I'd LOVE to see this in Mopidy. And if it's already there, please point me in the right direction! Been reading the manuals for a while and can't seem to find a way to get this working.

@jodal
Mopidy member

AFAIK it is possible to get working HTTP streaming from Mopidy by combining it with Icecast and a couple of hacks, documented at https://docs.mopidy.com/en/latest/config/#streaming-through-shoutcast-icecast

Work is ongoing on a gapless branch (see #1288) which together with the next round of gapless improvements should make Mopidy+Icecast work without any hacks to keep the stream alive.

@xcellardoor

Just want to chime in that I also have serious interest in HTTP Streaming. I want to use it to listen to Spotify on the awesome Moped web interface, from my web server/VPN, at work. Was rather upset when I ran it locally and heard music, then got a tonne of JACK errors when I tried to run it remotely. If I knew how to code better I'd try it myself. Thanks!

@JohnMaguire

@jodal Are the issues you mentioned regarding #1288 resolved?

i.e. Can this part of the documentation be removed?

Currently, Mopidy does not handle end-of-track vs end-of-stream signalling in GStreamer correctly. This causes the SHOUTcast stream to be disconnected at the end of each track, rendering it quite useless. For further details, see #492. You can also try the workaround mentioned below.

@jodal
Mopidy member

@JohnMaguire I don't if there's a section somewhere in the docs we've forgotten since you don't include a link. AFAIK the "develop" version of the docs are up to date with the upcoming changes in 2.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment