Streaming radio station pausing/buffering


#1

Hi,

I am loving mopidy but get a little frustrated by pauses in the audio when playing an online radio station. If I play the radio station via just gstreamer then I have not had any gaps in playback. I would appreciate any tips on if there are any configuration items I can change or if necessary where to look in the code. I am running Mopidy 2.0.0.

Here is the gstreamer command I am using:

sudo gst-launch-1.0 -vmt playbin uri=http://108.61.73.117:8100 output="alsasink buffer-time=200000 latency-time=1000"

Here are the log prints from mopidy when the pause occurs:

DEBUG    2016-06-09 18:10:02,167 [32206:MainThread] mopidy.audio.gst
  Got BUFFERING bus message: percent=6%
DEBUG    2016-06-09 18:10:02,168 [32206:MainThread] mopidy.audio.gst
  Got STATE_CHANGED bus message: old=GST_STATE_PLAYING new=GST_STATE_PAUSED pending=GST_STATE_VOID_PENDING
DEBUG    2016-06-09 18:10:02,169 [32206:MainThread] mopidy.audio.actor
  Audio event: state_changed(old_state=playing, new_state=paused, target_state=playing)
DEBUG    2016-06-09 18:10:02,169 [32206:MainThread] mopidy.listener
  Sending state_changed to AudioListener: {'old_state': u'playing', 'target_state': u'playing', 'new_state': u'paused'}
DEBUG    2016-06-09 18:10:02,170 [32206:MainThread] mopidy.audio.gst
  Got ASYNC_DONE bus message.
DEBUG    2016-06-09 18:10:11,920 [32206:MainThread] mopidy.audio.gst
  Got BUFFERING bus message: percent=100%
DEBUG    2016-06-09 18:10:11,922 [32206:MainThread] mopidy.audio.gst
  Got STATE_CHANGED bus message: old=GST_STATE_PAUSED new=GST_STATE_PLAYING pending=GST_STATE_VOID_PENDING
DEBUG    2016-06-09 18:10:11,922 [32206:MainThread] mopidy.audio.actor
  Audio event: state_changed(old_state=paused, new_state=playing, target_state=None)
DEBUG    2016-06-09 18:10:11,922 [32206:MainThread] mopidy.listener
  Sending state_changed to AudioListener: {'old_state': u'paused', 'target_state': None, 'new_state': u'playing'}

Frequent audio drops when using streams
#2

I think this is due to the size of the buffer we use in order to reliably support multiple platforms. If you search on here or maybe github you should find the relevant discussions to point you in the right direction.


#3

I tried increasing the buffer size and it seemed no matter how big I made it I still had problems. It also increased playback start up time.

I played around with some different options and so far I am happiest with marking the gstreamer pipe as a Live stream instead of just a Stream. Not sure this is a good/proper solution, but in mopidy/audio/actor.py in _on_source_setup I put a check in to see if the source was a HTTP source, and if so called source.set_live(True);

Stream startup is now quick and I have yet to hear any pauses in the online radio station.


#4

Hi everyone, I got the same problem and I wonder whether there’s a proper solution for this.

Situation:
I use the latest mopidy version on Raspberry PI3 jessie, alle updated/upgraded, with HiFiberry.
I normally listen to online http livestream (e.g. http://stream.srg-ssr.ch/m/rsc_de/mp3_128) with MPD
When I throw the M3U at MPD, mopidy normally first lets out half a second of sound and then seemingly buffers in order to really start playing after around 2-5. During playback it happens quite often that the streaming pauses/buffers for 0.5-2 seconds.

Comparison 1: when I throw a http livestream into volumio (https://volumio.org/), it starts playing the milisecond I pressed the button. Also, there is not one single skipping or buffering afterwards.(same hardware/network setup)
Comparison 2: when I start a Spotify playlist via the mopidy/Spotmop interface, it starts nearly immediately and plays without hiccups!

Is there any setting that I forgot? What does Volumio do differently - it also uses mpd (but an old version, 0.19.0). Is there a GStreamer/mpd/mopidy setting I don’t know about?
Or is it really the case that I have to modify the actor.py the way drewloch described?

@drewloch: can you let me know you http check code in actor.py?

Thanks!!


#5

Is there any setting that I forgot? What does Volumio do differently - it also uses mpd (but an old version, 0.19.0).

Mopidy implements the MPD protocol but it does not use mpd itself. So it’s very different.


#6

Oh I see… thank you for your quick response! Well although I did some learn-by-doing on my raspberries, I am still quite a noob, sorry. :slight_smile:

Could you maybe help me to clarify some things:

  1. Implements the MPD protocol means that when I use a MPD client to access mopidy, it talks to mopidy via MPD protocol but not to mpd itself. Correct?
  2. Is there maybe a better way to handover a m3u with a livestream than using the mpd protocol via port 6600?
  3. If drewloch’s method works for him, does it mean that this might/should be committed as a change to the official mopidy version? Or is the attribute set_live(True) not helpful, and I can only play with buffering times?

Thank you! I love the project by the way. I initially worked with volumio but I don’t like the fact that it is a proprietary image which I cannot control myself (and which uses outdated versions)…

Cheers


#7
  1. Yes
  2. No. (I’m not sure what better means in this context, if it adds the stream what more could you want ?)
  3. The generic gstreamer pipeline works with many different types of audio. That setting might cause problems for other audio sources so we’d have to look at exactly what it does. @adamcik might know.

#8

Can you let us know what did you exactly do?


#9

I modified the mopidy/audio/actor.py file.

In my version of the file, at line 535 is the def _on_source_setup routine. Below is my modified version of the routine. The italic text is what I added.

def _on_source_setup(self, element, source):
    gst_logger.debug(
        'Got source-setup signal: element=%s', source.__class__.__name__)

    if source.get_factory().get_name() == 'appsrc':
        self._appsrc.configure(source)
    else:
        self._appsrc.reset()

    _gst_logger.debug('source-setup %s', element.get_name())_

_ if source.class.name == ‘main.GstSoupHTTPSrc’:_
_ gst_logger.debug(‘HTTP Src - setting live mode’)_
_ source.set_live(True);_

    utils.setup_proxy(source, self._config['proxy'])

#10

Thank you. However, the dashes have ruined your code. The correct definition of the method would be:

    def _on_source_setup(self, element, source):
    gst_logger.debug(
        'Got source-setup signal: element=%s', source.__class__.__name__)

    if source.get_factory().get_name() == 'appsrc':
        self._appsrc.configure(source)
    else:
        self._appsrc.reset()

    if source.__class__.__name__ == '__main__.GstSoupHTTPSrc':
    	gst_logger.debug('HTTP Src - setting live mode')
    	source.set_live(True)

    utils.setup_proxy(source, self._config['proxy'])

#11

I can confirm that is-live solves the buffering problem when listening to internet radio. but i can hear sometimes discontinuities in the audio, so i believe that these are the moments when buffering would start if is-live was not set. for radio stream this discontinuities are better than pauses for buffering but for other http sources that are not live streams this is not desirable behaviour. I’m not familiar with this stuff but maybe there is some way to know if the stream is live or not, for example live stream does not have information about its lenght ?


#12

Hello kmuuga/drewloch,

i have the same problems and want to change the streaming to live mode. But if i change the code as posted my
mopidy isnt starting any more. I tried to copy and paste also i tried to modify it line for line but everytime i change the code it starts no longer.

My changed code from line 535 on (edited with notepad++:

def _on_source_setup(self, element, source):
gst_logger.debug(
‘Got source-setup signal: element=%s’, source.class.name)

if source.get_factory().get_name() == 'appsrc':
    self._appsrc.configure(source)
else:
    self._appsrc.reset()

if source.__class__.__name__ == '__main__.GstSoupHTTPSrc':
    gst_logger.debug('HTTP Src - setting live mode')
    source.set_live(True)

utils.setup_proxy(source, self._config['proxy'])

What is wrong with the code? Or is it a problem that I use an updated version of mopidyTouch?
Thank for your kind help.


#13

Isn’t a semicolon gone missing? See my code exactly. It has been working
fluently for weeks, I love it! Props to @mopidy and @jodal


#14

Check the indentation of the function definition (the very first line). It’s wrong in @kmuuga’s post (needs to be decreased) and the formatting in your post is all messed up so you can’t tell what you’ve got there.


#15

look in the log, if it is a syntax error you will see what is wrong.


#16

Many thanks to you all !!!

It works! I´m an Newbie in Raspbian/Phython and I thought that the allignment of the Code doesn´t matter. So it wasn´t a error in the code.
The problem was the wrong orientation of the code lines.

A great help was the hint to look in the debug log. I used the command “mopidy --save-debug-log” and got the line number with the syntax error. So i fixed line for line till it works.

Thanks for the quick response.


#17

additionally to radio stream buffering problem, today i encountered another issue and maybe it is related. The radio stream stopped entirely (twice during the whole day of listening the radio). In the mopidy log I found this:

Nov 26 18:15:37 kitchen mopidy[489]: ERROR GStreamer error: gst-resource-error-quark: Server does not support seeking. (11)

I’m using mopidy 2.1.0 on a nanopi board (allwinner H3 ARM CPU), OS is Ubuntu 16.04 with 4.11 kernel. And audio is through pulseaudio.