music-assistant / hass-music-assistant

Turn your Home Assistant instance into a jukebox, hassle free streaming of your favorite media to Home Assistant media players.
Apache License 2.0
1.39k stars 51 forks source link

Chromecast - Playback Issues #1501

Closed oneofthemany closed 1 year ago

oneofthemany commented 1 year ago

What version of Music Assistant has the issue?

2.0.0b73

The problem

Playback whether radio or Tidal stream is suffering from some form of jitter as playback quality is really poor

How to reproduce

Initiate playback of any Radio or Tidal stream to a Chromecast group

Relevant log output

No response

Additional information

I have tested to determine if it is indeed my WiFi network or chromecast group by using Phone to cast same media and no issues are seen

What version of Home Assistant Core are your running

2023.8.4

What type of installation are you running?

Home Assistant OS

On what type of hardware are you running?

Raspberry Pi

oneofthemany commented 1 year ago

Please note: Logs are too large to attach

Here is a snippet:

2023-08-31 09:54:17.466 ERROR (MainThread) [asyncio] Task exception was never retrieved
future: <Task finished name='Task-32133' coro=<ChromecastProvider.poll_player() done, defined at /usr/local/lib/python3.11/site-packages/music_assistant/server/providers/chromecast/__init__.py:255> exception=NotConnected('Chromecast 192.168.1.12:32065 is connecting...')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/music_assistant/server/providers/chromecast/__init__.py", line 277, in poll_player
    await asyncio.to_thread(castplayer.cc.media_controller.update_status)
  File "/usr/local/lib/python3.11/asyncio/threads.py", line 25, in to_thread
    return await loop.run_in_executor(None, func_call)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pychromecast/controllers/media.py", line 592, in update_status
    self.send_message(
  File "/usr/local/lib/python3.11/site-packages/pychromecast/controllers/__init__.py", line 121, in send_message
    self.send_message_nocheck(
  File "/usr/local/lib/python3.11/site-packages/pychromecast/controllers/__init__.py", line 133, in send_message_nocheck
    self._message_func(
  File "/usr/local/lib/python3.11/site-packages/pychromecast/socket_client.py", line 963, in send_app_message
    return self.send_message(
           ^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pychromecast/socket_client.py", line 928, in send_message
    raise NotConnected(f"Chromecast {self.host}:{self.port} is connecting...")
pychromecast.error.NotConnected: Chromecast 192.168.1.12:32065 is connecting...
2023-08-31 09:54:17.467 ERROR (MainThread) [asyncio] Task exception was never retrieved
future: <Task finished name='Task-32136' coro=<ChromecastProvider.poll_player() done, defined at /usr/local/lib/python3.11/site-packages/music_assistant/server/providers/chromecast/__init__.py:255> exception=NotConnected('Chromecast 192.168.1.12:32065 is connecting...')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/music_assistant/server/providers/chromecast/__init__.py", line 277, in poll_player
    await asyncio.to_thread(castplayer.cc.media_controller.update_status)
  File "/usr/local/lib/python3.11/asyncio/threads.py", line 25, in to_thread
    return await loop.run_in_executor(None, func_call)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pychromecast/controllers/media.py", line 592, in update_status
    self.send_message(
  File "/usr/local/lib/python3.11/site-packages/pychromecast/controllers/__init__.py", line 121, in send_message
    self.send_message_nocheck(
  File "/usr/local/lib/python3.11/site-packages/pychromecast/controllers/__init__.py", line 133, in send_message_nocheck
    self._message_func(
  File "/usr/local/lib/python3.11/site-packages/pychromecast/socket_client.py", line 963, in send_app_message
    return self.send_message(
           ^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pychromecast/socket_client.py", line 928, in send_message
    raise NotConnected(f"Chromecast {self.host}:{self.port} is connecting...")
pychromecast.error.NotConnected: Chromecast 192.168.1.12:32065 is connecting...
2023-08-31 09:54:17.986 WARNING (Thread-15) [pychromecast.socket_client] [Quadrophonic(192.168.1.12):32065] Error communicating with socket, resetting connection
2023-08-31 09:54:17.986 INFO (Thread-15) [pychromecast.controllers] Receiver:channel_disconnected
2023-08-31 09:54:18.222 INFO (MainThread) [music_assistant.providers.tidal] Track 77632887 has no available lyrics
2023-08-31 09:54:18.386 INFO (Thread-15) [pychromecast.socket_client] [Quadrophonic(192.168.1.12):32065] Connection reestablished!
2023-08-31 09:54:20.582 WARNING (ThreadPoolExecutor-0_0) [tidalapi.request] HTTP error on 401
OzGav commented 1 year ago

It is not valid to assume because your phone casts ok that it is not a bandwidth issue. MA casts high quality by default. You should drop the MA codec for the player back to mp3 and see if things improve.

OzGav commented 1 year ago

Also you say the issue is with a chromecast group so are you saying you can stream fine to a single speaker?

oneofthemany commented 1 year ago

Also you say the issue is with a chromecast group so are you saying you can stream fine to a single speaker?

No i have issue to single speakers also

oneofthemany commented 1 year ago

It is not valid to assume because your phone casts ok that it is not a bandwidth issue. MA casts high quality by default. You should drop the MA codec for the player back to mp3 and see if things improve.

The radio stream is MP3 so I guess this proves the point that's it something to do with MA.

I have just woken up to an automation of radio played using MA version of my Chromecast group and it's broken audio, I then say "hey Google play radio x", the command plays audio to the same Chromecast group and the audio is fixed.

Please note I'm a wireless architect by trade so it's not my WiFi as I've already checked 🙂

marcelveldt commented 1 year ago

The radio stream may be mp3 but MA sends by default lossless audio to the speaker, not matter the source. Asking the google to play audio works entirely different as there is nothing streaming to it, but the speaker itself downloads the music and plays it, and has full control over the buffer. It is why it is so fail proof but there good as well still be a networking issue hidden underneath.

Can you describe what you mean with "poor quality" ?

Is it distorted ? Like overdriven ? -> In that case set volume normalization back to its default of -14 LUFS Hiccups pops and cracks --> not enough bandwidth --> select a lower quality codec in the speaker settings within MA, for example switch to AAC

oneofthemany commented 1 year ago

The radio stream may be mp3 but MA sends by default lossless audio to the speaker, not matter the source. Asking the google to play audio works entirely different as there is nothing streaming to it, but the speaker itself downloads the music and plays it, and has full control over the buffer. It is why it is so fail proof but there good as well still be a networking issue hidden underneath.

Can you describe what you mean with "poor quality" ?

Is it distorted ? Like overdriven ? -> In that case set volume normalization back to its default of -14 LUFS Hiccups pops and cracks --> not enough bandwidth --> select a lower quality codec in the speaker settings within MA, for example switch to AAC

I am going to disagree with you here as when i use tidal I have this:

image

and when i use radio I have this:

image

are saying that the UI cannot be trusted as a source of what codec is being used?

marcelveldt commented 1 year ago

Read my message again and then reply. Did you even follow our suggestions to open the player settings and change the OUTPUT codec ?

oneofthemany commented 1 year ago

Read my message again and then reply. Did you even follow our suggestions to open the player settings and change the OUTPUT codec ?

So what you are saying, without even saying it, is that the UI can't be trusted in relationship to the codec in use and you have not mapped the value of the settings within the system to what is shown to the user in relationship to the codec in use 🙂

And yes I did read it, but wanted to ask the question to see if you would confirm my thoughts.

What I've done is set everything to PCM to see if it's a bandwidth issue, as I don't think going down is what I want.

What I would also like to ask is that I appreciate you have settings for groups and for individual speakers, but could you also have a system wide setting override function so that all speakers and groups follow a common setting as opposed to having to configure each group and speaker individually and configure them all to be the same?

In terms of the audio, I found that if it was a stream and I paused the playing for approx. 6 seconds the audio quality would be comparable to the chromecast stream with zero lag or buffering issues

OzGav commented 1 year ago

The input codec and output codec in MA can be different. The codec shown in the UI is the input codec.

oneofthemany commented 1 year ago

The input codec and output codec in MA can be different. The codec shown in the UI is the input codec.

It potentially would make an easier journey to change the codec where the codec is shown in the audio player as opposed to the player groups

Just a thought

OzGav commented 1 year ago

I’m not sure what you mean. Each player has its own configuration. Except airplay devices can’t change the output codec

oneofthemany commented 1 year ago

I’m not sure what you mean. Each player has its own configuration. Except airplay devices can’t change the output codec

I have about 7 smart speakers which form groups but are also individual speakers

Having to manually configure each speaker with a setting is great for flexibility, but what if you just want them all the same - I guess I'm trying to say that there is no global config

OzGav commented 1 year ago

Ok this is a feature request that is noted however we are straying from the original issue. Do you still have problems after adjusting the output codec?

oneofthemany commented 1 year ago

Ok this is a feature request that is noted however we are straying from the original issue. Do you still have problems after adjusting the output codec?

I have noticed that for any changes to take place on an active stream you have to do the following:

Change codec > change the stream from Radio to Tidal (or vice versa) > then change back and attempt to play media

By using the highest codec value of PCM this prevented audio from playing across both types which would point to a codec issue

Prior to me undertaking the above I could change the codec to anything and nothing would happen which was a false positive and misleading

Are you aware off this issue?

I also appreciate that you may think we are straying, but it's the fact that the UI is misleading when it comes to active codec that is an issue from my stand point and the added methodology to change codec seems clunky IMHO, and I also seem to have uncovered a bug on how you have to change it

OzGav commented 1 year ago

Ok so if I understand correctly the original poor playback quality has been resolved by changing the codec. However, when changing the codec in the settings it is not obvious when that change actually takes place.

marcelveldt commented 1 year ago

1) If changing the codec resolved your original issue, you do have a bandwidth issue. An optimized WiFi should be able to handle the full lossless FLAC stream of even Hi Res 96Khz/24 bits or above. Note that the WiFi chips in chromecast devices are often flaky and you might need to force them to a 5Ghz band (or connect them wired).

2) The UI needs much more work, we're aware of this. Note that this is a relatively new project with only limited capacity, we can't do wonders.

oneofthemany commented 1 year ago

1) If changing the codec resolved your original issue, you do have a bandwidth issue. An optimized WiFi should be able to handle the full lossless FLAC stream of even Hi Res 96Khz/24 bits or above. Note that the WiFi chips in chromecast devices are often flaky and you might need to force them to a 5Ghz band (or connect them wired).

2) The UI needs much more work, we're aware of this. Note that this is a relatively new project with only limited capacity, we can't do wonders.

I'm going to get some pcaps and see what's going on as it's the only thing I've seen that has issues in my network and I'm not convinced that it's a WiFi issue as generally the WiFi is only used by the speakers which means that they have the whole channel to themselves

I'll update when I get around to having time to test

fuslwusl commented 1 year ago

I had strong clipping (what @oneofthemany seems to call jitter) during playback of Deezer FLAC (uncompressed) tracks and i could solve the issue by disabling "Enable volume normalization EBU-R128 based". When enabled the volume levels of the tracks is far too loud and distorted. @oneofthemany Could you please try if jitter/clipping disappears by disabling this option.

marcelveldt commented 1 year ago

If you experience clipping with volume normalization you have set it to a ridiculous value. The recommended value is -17 but some even prefer -23

oneofthemany commented 1 year ago

If you experience clipping with volume normalization you have set it to a ridiculous value. The recommended value is -17 but some even prefer -23

Whereabouts are the settings?

All I see is enable or disable Screenshot_20231028-222122.png

oneofthemany commented 1 year ago

I had strong clipping (what @oneofthemany seems to call jitter) during playback of Deezer FLAC (uncompressed) tracks and i could solve the issue by disabling "Enable volume normalization EBU-R128 based". When enabled the volume levels of the tracks is far too loud and distorted. @oneofthemany Could you please try if jitter/clipping disappears by disabling this option.

I'll give this a go, thanks

OzGav commented 1 year ago

All I see is enable or disable

look in the advanced settings

oneofthemany commented 1 year ago

All I see is enable or disable

look in the advanced settings

Ah you have to swipe left as it's no auto fit on mobile

Question though: if the recommended setting is -17 why is the default -14?

fuslwusl commented 1 year ago

The normalization value to totally avoid clipping should be -23 LUFS based on this official documentation https://tech.ebu.ch/docs/r/r128.pdf but values differ per plattform so it is complicated to get the right value.

Here is a good documentation from the mastering plugin developer izotope comparing different plattforms like YouTube, Spotify, Deezer, Tidal and many more. This page explains the whole topic very well: https://www.izotope.com/en/learn/mastering-for-streaming-platforms.html#loudness-specifications-by-streaming-platform

marcelveldt commented 1 year ago

The default value is -17 which should be a good compromise for 99% of the cases. I had it set the to EBU's standard value of -23 but then we got so many complaints from people finding the music too silent.

Equalizer is indeed bypassed when the value is set to 0.

Question though: if the recommended setting is -17 why is the default -14?

Hmm, I'll check that, if that is the case we have to change it because -14 is (imo) not safe enough.

marcelveldt commented 1 year ago

In general, I wouldn't recommend turning off the volume normalization because there are so many different loudness levels , especially if you play music from different sources. We use an integrated loudness level based on the EBU-R128 standard and only adjust gain of the entire track up or down so there is no compression of dynamic range. For that same reason of not loosing dynamic range we do not use a limiter and it's the user's responsibility to use sane values for the target level of the volume normalization.

That said, we should probably add a few warnings if a value higher than -17 is used, because that can indeed lead to clipping if the measurement was not accurate or a wrong default was assumed.

fuslwusl commented 1 year ago

@marcelveldt Thanx for your info. I had to turn volume normalization off because i had hard clipping when playing from Deezer. I will try if a value of -17 will fix the problem - it was -14 when i tested and it clipped in nearly every song. It would be great to show a prominent short info regarding volume normalization, the different plattforms and their values. Without the info "look in the advanced settings" i wouldn't have found these settings.

marcelveldt commented 1 year ago

I don't test with Deezer a lot so maybe that is part of the problem. I will definitely adjust the default value back to -17 or maybe even -23 and add in some more text and warnings.

fuslwusl commented 1 year ago

@marcelveldt I have one more technical question. Is the normalization calculated in 32 bit and then scaled to the payback device bit depth for example UPnP playback on a Denon AVR in 24 bit? Or is everything calculated in the bit depth of the input track for example FLAC lossless 16 bit? And if there is any dithering applied during the proccess?

marcelveldt commented 1 year ago

All tracks are processed as raw pcm by Music Assistant internally. So everything you play will be first converted to just raw pcm in the sample rate and bit depth of the origin (unless flow mode is enabled) and the gain adjustment is done while extracting the raw source media so the pcm chunks we get into the streaming engine have the gain adjustment applied, that way there should be enough headroom withit the 16 or 24 bits bit depth Converting to 32 or 64 bits floating point is something I have considered but not worth the overhead and comes at the risk of dithering when going back from 64 bits to 16 or 24 bits so instead I settled on applying the correction gain while extracting the raw audio from its base codec.

All further processing in MA is done at PCM raw audio level, such as the optional equalizer (in the future maybe some room correction or other filters) - if "flow mode" is enabled crossfading is also done on the raw pcm chunks but that will upsample all audio into one static sample rate and bit depth to create one "flow" of audio to send to the player.

The final part in the chain is that MA sends either the raw pcm data to the player or encodes it into a coec of the user's choice, by default this is FLAC due to it being lossless while keeping a sane file size

fuslwusl commented 1 year ago

I don't test with Deezer a lot so maybe that is part of the problem. I will definitely adjust the default value back to -17 or maybe even -23 and add in some more text and warnings.

I will give you feedback when i tested the -17 value playback with some Deezer tracks with maximum levels where clipping is very easy detectable when the voice sounds harsh at 0 dBFS. https://deezer.page.link/PLWLc6tk2qsr9Sa17 position 01:46 https://deezer.page.link/Uhp1oTtvsbxeY79n6 position 01:33

fuslwusl commented 1 year ago

All tracks are processed as raw pcm by Music Assistant internally. So everything you play will be first converted to just raw pcm in the sample rate and bit depth of the origin (unless flow mode is enabled) and the gain adjustment is done while extracting the raw source media so the pcm chunks we get into the streaming engine have the gain adjustment applied, that way there should be enough headroom withit the 16 or 24 bits sample rate. Converting to 32 or 64 bits floating point is something I have considered but not worth the overhead and comes at the risk of dithering when going back from 64 bits to 16 or 24 bits so instead I settled on applying the correction gain while extracting the raw audio from its base codec.

All further processing in MA is done at PCM raw audio level, such as the optional equalizer (in the future maybe some room correction or other filters) - if "flow mode" is enabled crossfading is also done on the raw pcm chunks but that will upsample all audio into one static sample rate and bit depth to create one "flow" of audio to send to the player.

The final part in the chain is that MA sends either the raw pcm data to the player or encodes it into a coec of the user's choice, by default this is FLAC due to it being lossless while keeping a sane file size

@marcelveldt Thanx for all this detailed information and insights. So when i disable volume normalization i will get the original uncompressed flac file from deezer without any volume correction applied. I could not hear any clipping and everything sounded perfectly fine! Thanx for your great work!!!

marcelveldt commented 1 year ago

@marcelveldt Thanx for all this detailed information and insights. So when i disable volume normalization i will get the original uncompressed flac file from deezer without any volume correction applied. I could not hear any clipping and everything sounded perfectly fine! Thanx for your great work!!!

Not exactly, as explained above MA always processes all audio content in PCM internally so audio is always decoded and optionally any processing is applied. If you have applied FLAC as the output codec to your player this would theoretically mean that a track is decoded and then re-encoded again but as long as a lossless codec is used, there is no loss of quality at all.

And for the record: FLAC is compressed, its just lossless compressed. Formats like MP3 are lossy compressed.

Like explained above I would really recommend to leave volume normalization enabled and not turn it off. Instead change the target volume if you may experience clipping. I'll look into Deezer because I have never ever experienced any clipping with any of the other providers.

If you only play audio from one single source (e.g. Deezer) and that audio source already has normalized its audio files, then its safe to disable normalization in MA. If you play audio from different sources or audio is not normalized at the source, I really recommend to leave normalization enabled for the best experience.

oneofthemany commented 1 year ago

I've checked all players and the values are indeed -14 as default value

I'll amend them all to -17 and hope all goes well moving forward

Thanks all 🙂

OzGav commented 1 year ago

The defaults and associated text will be updated in the next beta

oneofthemany commented 1 year ago

Thanks all for solving this issue