mopidy: Buffering Problems while playing audio streams

Hello everyone,

iam facing some problems playing internet radiostreams with mopidy 1.1.0 . Some times the stream stops playing for several seconds before continuing. I used mopidy debbuging capabilities to find out its a buffering issue. Logs look like this:

EBUG    2015-09-10 15:37:27,085 [12014:MainThread] mopidy.audio.gst
  Got state-changed message: old=GST_STATE_PLAYING new=GST_STATE_PAUSED pending=GST_STATE_VOID_PENDING
DEBUG    2015-09-10 15:37:27,085 [12014:MainThread] mopidy.audio.actor
  Audio event: state_changed(old_state=playing, new_state=paused, target_state=playing)
DEBUG    2015-09-10 15:37:27,086 [12014:MainThread] mopidy.audio.gst
  Got async-done.
DEBUG    2015-09-10 15:37:27,086 [12014:MainThread] mopidy.listener
  Sending state_changed to AudioListener: {'old_state': u'playing', 'target_state': u'playing', 'new_state': u'paused'}
DEBUG    2015-09-10 15:37:27,533 [12014:HttpServer] mopidy.http.handlers
  Received WebSocket message from 127.0.0.1: u'{"method":"core.playback.get_time_position","jsonrpc":"2.0","id":31252}'
DEBUG    2015-09-10 15:37:28,533 [12014:HttpServer] mopidy.http.handlers
  Received WebSocket message from 127.0.0.1: u'{"method":"core.playback.get_time_position","jsonrpc":"2.0","id":31253}'
TRACE    2015-09-10 15:37:29,268 [12014:MainThread] mopidy.audio.gst
  Got buffering message: percent=6%
DEBUG    2015-09-10 15:37:29,533 [12014:HttpServer] mopidy.http.handlers
  Received WebSocket message from 127.0.0.1: u'{"method":"core.playback.get_time_position","jsonrpc":"2.0","id":31254}'
TRACE    2015-09-10 15:37:29,737 [12014:MainThread] mopidy.audio.gst
  Got buffering message: percent=7%

When the buffers is filled to 100%, playback keeps on.

The reason i post this here is, this problem doesn’t accur when using another player like mplayer, vlc etc.

I already increased buffer-time und latency time in my config, but Problem still persists.

[audio]
output = alsasink buffer-time=200000 latency-time=10000
mixer = software

I dont finde other possibilities to modify mopidy buffer handling. Maybe increasing the buffersize for gstreamer would solve my problem.

Is there any possiblity to tune this in recent mopidy builds ( iam using current 1.1.0 ). If not, it would be great to see some optons or improvements for stream buffering in future versions.

Thanks alot for your great work. Would be insane if you could help.

About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Comments: 36 (12 by maintainers)

Most upvoted comments

I still encounter the exact same problem on Mopidy 2.0.1 with every single radio stream. Would somebody explain to me, how is such a devastating bug even possible to be unfixed on a god damn music server?

I can offer my solution, this is a patch against 2.1.0 version:

diff --git a/mopidy/audio/actor.py b/mopidy/audio/actor.py
index 6020bc1..6020d2f 100644
--- a/mopidy/audio/actor.py
+++ b/mopidy/audio/actor.py
@@ -415,6 +415,7 @@ class Audio(pykka.ThreadingActor):
         self._buffering = False
         self._tags = {}
         self._pending_uri = None
+        self._is_live = False
         self._pending_tags = None
         self._pending_metadata = None

@@ -547,9 +548,12 @@ class Audio(pykka.ThreadingActor):
         else:
             self._appsrc.reset()

+        if source.get_factory().get_name() == 'souphttpsrc':
+            source.set_property('is-live', self._is_live)
+
         utils.setup_proxy(source, self._config['proxy'])

-    def set_uri(self, uri):
+    def set_uri(self, uri, is_live):
         """
         Set URI of audio to be played.

@@ -558,7 +562,7 @@ class Audio(pykka.ThreadingActor):
         :param uri: the URI to play
         :type uri: string
         """
-
+        self._is_live = is_live
         # XXX: Hack to workaround issue on Mac OS X where volume level
         # does not persist between track changes. mopidy/mopidy#886
         if self.mixer is not None:
diff --git a/mopidy/backend.py b/mopidy/backend.py
index 7412ccc..f15b616 100644
--- a/mopidy/backend.py
+++ b/mopidy/backend.py
@@ -248,7 +248,7 @@ class PlaybackProvider(object):
                 'Backend translated URI from %s to %s', track.uri, uri)
         if not uri:
             return False
-        self.audio.set_uri(uri).get()
+        self.audio.set_uri(uri, track.length is None).get()
         return True
     def resume(self):

@adamcik did you succeed in reproducing the finding? I have discovered that defining on_source_setup as

  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'])

stops the radio hiccuping, but sometimes skips dozen or double that milliseconds of the stream. However, removing the if statement will do the skipping for all sources. So this solution is not correct, but better than silence.

@karlmuuga I guess this hasn’t been addressed because (1) most users don’t use Mopidy to stream other HTTP music streams, but rather play music off of e.g. Spotify or the local file system (if this weren’t the case, a lot more users would suffer this issue); and (2) the problem is likely in GStreamer, a third party component that Mopidy can’t directly fix.

I’m willing to bet that if you do a gst-launch (command line GStreamer client) with playbin and your streaming URI, you’ll hit the same issue there. So we need to figure out if we can tune those parameters to be smarter about buffering data from souphttpsrc, which is likely the offending element ( https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-souphttpsrc.html ). Problem is that it’s buried inside a playbin.

Swearing about it and expressing your indignity that your specific use case hasn’t been as extensively tested does not bring us closer to a solution.