Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for HTTP audio output streaming #56

Open
jodal opened this issue Jan 19, 2011 · 17 comments
Open

Add support for HTTP audio output streaming #56

jodal opened this issue Jan 19, 2011 · 17 comments
Labels
A-audio Area: Audio layer C-enhancement Category: A PR with an enhancement or an issue with an enhancement proposal

Comments

@jodal
Copy link
Member

jodal commented Jan 19, 2011

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
Copy link
Member

adamcik commented May 12, 2011

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
Copy link
Member

adamcik commented Dec 20, 2012

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
Copy link
Member

adamcik commented Apr 29, 2013

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
Copy link

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

@KittyKatt
Copy link

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
Copy link
Member Author

jodal commented Sep 22, 2015

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
Copy link

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
Copy link

@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
Copy link
Member Author

jodal commented Feb 15, 2016

@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.

@johnmaguire
Copy link

Sorry: https://docs.mopidy.com/en/latest/config/#streaming-through-shoutcast-icecast

It seems it was updated in the develop version of the docs, you're correct: https://docs.mopidy.com/en/develop/audio/#streaming-through-icecast

Thanks @jodal!

@ibrokemypie
Copy link

any updates in the past 2 years?

@Sungray
Copy link

Sungray commented May 1, 2020

any updates in the past 5 years?

@kingosticks
Copy link
Member

No. Icecast remains the best solution.

As part of Mopidy 3 we bumped out minimum supported version of GStreamer which opens up some better options for HTTP streaming e.g. hlssink2. If anyone is interested in pursuing this then that might be a good place to start.

@trygveaa
Copy link
Member

trygveaa commented May 1, 2020

Snapcast is another solution. It's made for multiroom playback, but I don't see any reason it can't be used for streaming to a single client too. I haven't tested it, but it looks promising.

@kingosticks
Copy link
Member

Yes, I've used snapcast. The use of a fifo is a bit fiddly and a new alternate method was being developed but last I heard that method came with its own issues. Also note that it is not http streaming.

@didotx
Copy link

didotx commented Dec 17, 2021

Hi there, for a long time I have been looking for a solution to get my mopidy / snapcast server combination to send a music stream to my devices on my local network.

I have mopidy and snapcast running on a RASPI as my central music server:
With Mopidy I can receive radio stations using tunein
and as an alternative I can listen to my locally stored music using Mopidy-Local.
This works perfect on a Samsung tablet using the snapcast app.

Now I have other devices on my network, that are capable to receive mp3 streams for example: https://hermes.bcs-systems.de/radio-lausitz_simulcast_192k_mp3, but I have no idea how to convert the mopidy server ip: http://192.168.10.32:6680 into the mp3 streaming URL required by my device.

Finally I found in this thread the statement from kingosticks "Yes, I've used snapcast. The use of a fifo is a bit fiddly and a new alternate method was being developed but last I heard that method came with its own issues. Also note that it is not http streaming."

Please direct me to a description, how mopidy or snapcast has to be setup and configured to do what I am looking for. Thanks so much! DidoTx

@kingosticks
Copy link
Member

General questions belong at https://discourse.mopidy.com/. If you have any follow up questions, start a new topic there and not here.

Snapserver utilises a custom protocol i.e. not HTTP and only streams to snapclient. You can either wait for a fixed version of icecast (looks like it'll be available in Ubuntu 22.04) and and use Mopidy feeding both Snapcast and Icecast (such a dual output setup can be adapated from the one provided at https://docs.mopidy.com/en/latest/icecast/). Or, stay with Mopidy feeding only Snapcast and have a snapclient whos job it is to pipe output into a HTTP server like:

snapclient -h 192.168.0.3 --logsink null --player file | something

That something needs to take raw PCM, covert it to MP3 and serve that over HTTP. Maybe ffmpeg can do that? I've no idea. There isn't really an off-the-shelf solution for this use-case, as strange as that may seem. Good luck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-audio Area: Audio layer C-enhancement Category: A PR with an enhancement or an issue with an enhancement proposal
Projects
None yet
Development

No branches or pull requests