Got Chromecast playback working

Folks,
I was playing around with Volumio in the past few weeks and thought I’ve have a crack at getting it to support playback via Google Chromecast. I’m aware that the project focus is to drive audio devices directly. So I’m not trying to suggest this as a feature etc. It was purely a go at seeing how far I could get.

The nearest thing available for Chromecast integration with Volumio at present is mkchromecast which is a project that uses a soft DSP device to act as a sound card on the given Windows, OSX or Linux host. If it could be made work, the rest would fall out of the wash in terms of integrating with your preferred applications such as Volumio.

But rather than go that route, I felt it would be much more efficient to concentrate on getting the integration to serve URLs for the selected music files and let the Chromecast stream the files directly and do its own decoding. Streaming an MP3 or FLAC over the LAN is a much better idea than a raw PCM stream. It’s also less taxing on a small form factor computer like an RPi to handle.

The end result was to prototype a python script that uses pychromecast to control a specified Chromecast on your LAN. The same script then accesses the Volumio API to monitor the current playlist and then direct the Chromecast to stream the file that is currently playing. It uses python module chrerrypy to provide the web server to serve the files to the Chromecast. There is no direct coding changes to Volumio other than the integration with the REST API and a single call to the volumio command line binary for seek commands (that are not supported by the REST API)

I have this working on a Pi1B right now and while there are some niggles and feature gaps, it’s working enough to share out the efforts to others that might be interested.

Install steps
Check the README in github. It has all the steps required to get you up and running:
https://github.com/dresdner353/volumio2chromecast

Once installed, you can then run the script on the command line or follow steps to have it automatically started and kept running for you.

In terms of normal Volumio config, just have it configured to use the default audio interface be that HDMI, Jack or anything else and also leave it configured to use a hardware or software mixer. We want a volume control to be active as it is relayed to the Chromecast.

How it works
When you run the script it will first do a discovery of your specified Chromecast (if you specified it by name) to obtain its IP and port.

Then the script will start showing the current Volumio JSON API state every second (calling the gestate function in the RESTful API).

If it detects that something is playing, it will generate a URL for the current track file and invoke a cast of that URL to the specified Chromecast.

It also ties into events detected from the Volumio gestate… volume changes, play, pause, next, previous etc. All of these get relayed to the Chromecast. So as you change track, pause, stop… Chromecast will follow suit.

However, there is no seek functionality at this stage. So you can’t skip ahead/back within a given track.

If the script loses connectivity to the Chromecast it will detect this, re-establish a cast and start streaming again. Even if someone independently casts to the device from another app, this script will steal back control on the next track change.

To stop the streaming, you clear the queue on Volumio or let the current playlist play out and that will put it into a stopped state on the Volumio end which directs the script to stop casting and release all control over the Chromecast.

I’ve got this to work fine on the normal Google Chromecast, Chromecast Audio and on Google Home devices. It will also work with Grouped devices for multi-room synchronised playback. I did try to get basic artwork working for the video variant but was struggling with converting the Volumio artwork references it into URLs.

Just FYI the skip restriction relates to how I had to sync Volumio playback with that of the Chromecast. When you instruct Volumio to play a file, it really is playing file vie the default audio device. The progress of that playback starts as soon as you hit play. But the Chromecast playback is on it’s own timing and subject to how long it takes the Chromecast to start streaming the file.

If both left to their own devices, the Volumio playback is likely to end first, causing the script to instruct Chromecast to play the next track before it finished playing the current one. So the approach I took was to force 30-second syncs, where the elapsed time as reported from the Chromecast is used to perform a local seek on Volumio and get it back in sync and likely behind by 1-2 seconds. The cool thing is that once the Chromecast finishes playback, that is quickly detected and the script invokes the next track via the API.

Visually what you see on the Volumio I/F is track time progress as the playback continues and a little niggle every 30 seconds as the sync takes place. So you can’t really listen to the native playback as it will experience drops every 30 seconds with the sync. But in fairness the objective is to listen via the Chromecast.

Also, if during playback, you go and seek further on via Volumio GUI, within 30 seconds it will reset itself back to where the Chromecast progress is. For that reason, we don’t (yet) have a reliable way of having a Volumio seek translate into a seek on the Chromecast. But it is something I’d like to tackle at some point.

So enjoy and comments welcome.

Fantastic work! Well done!
Why not making it a plugin?

Hello,

Doesn’t seem like much has happened with this in awhile, but I did manage to get it sort of working on a VM using the current x86 release.

The major issues are that only older releases of CherryPy and pychromecast will work with the last release of the scripts. Oddly, even though the versions of CherryPy and pychromecast of that vintage are supposed to work under < Python 3.5, they don’t. So to make this happen, Python 3.6.3 has to be setup as the python3 on the machine.

After doing that, everything works, but I’ve found that after playing a few tracks, the library becomes unresponsive in the web interface. I disabled sending the album artwork in the script as I am using a CCA, so the thumbs are useless and I lengthened all the delays. This helped, but if I’m cruising around my library, after a while, everything just dies. Also worth noting, the only configuration I could get anything to happen in lost the ability to find my CCA by its friendly name. This might not be an issue with the script though as I’ve had issues with that in the past even with the CCA wired into the network.

These issues could have to do with the fact that the fact that I’m running volumio on a VM and it’s access to the web is through a vpn. The problem I’m having is in particular, the artist view, so I’m wondering if trying to fetch those through my sometimes very slow vpn is making the artist view problematic. I doubt it, but it’s possible. Oddly, the album view comes up fairly reliably.

I would love to get this to work as having it run on my zotac mini that my main system uses would allow me to cast to my bedroom system. I actually don’t really want multiple instances of volumio running as it seems to tax the sort of hacked together excuse I have instead of a NAS (big usb external harddrive running on a laptop on my network).

I’m far from a Linux expert as the post I’m sure reveals, if anyone has had luck running this reliably over the long haul, I’d be very interested in hearing about it. It’s so close to working well and the added functionality would be FANTASTIC!

PS, if anyone else wants a step by step on getting to this point where I am, I’ll share, but given the lack of responses to the thread, I’m not sure if its warranted.

Hi,
sorry for the delay. I only noticed the email notification now on the reply and PM. Gmail had put it into spam.

You are correct, the dependencies are now looking for a later python version and that actually burns me a bit with the Volumio image as the raspbian version it uses does not have the newer python3 version required. I tried to do a refresh on my Pi3 recently and ran into the same issue. Will try and tackle this again when I get time and see what I have to do to get Python updated on the older image.

As for this unresponsiveness, I’d typically look to pychromecast as the likely culprit. It’s by far the most complex part of this mix. My own code is a glorified probe on the volumio status URL and then cast invoke to the chromecast.

You could run the volumio2chromecast.py into a log file if the VM space permitted and try to see what sticks. Another option is to run tcpdump on the VM.

Something like:
sudo tcpdump -i any -s 0 -w /tmp/file.pcap

That will capture all network activity on the VM and it might catch the lock up and at least show us what is not happening in terms of cast requests going out to the CC or stream requests coming in that are not being served.

That capture will end up capturing the actual file being streamed… so you could only run it for a short time.

Hi dresdner353, I do hope you found a solution for this? Because I tried your solution the last couple of days, but it claims the python3.5 issue. So I wonder, how did you solve this issue? Because it would really be great to have this working in my environment.

So, any hints would be very much appreciated!
Regards! Haringstad

Suggestion: why don’t you do a volumio plugin?
This nodejs module looks promising: npmjs.com/package/castv2-player

@michelangelo, I would love to do that, but I am not a programmer… So, any help on that, would be appreciated? Is there documentation on how to build a plugin? (NOOB Questions, I know!)

Regards, Haringstad

Unfortunately I failed miserably to solve this and attempts to try and update Python3 on the image didn’t work.

I think what would help here if Volumio went and upgrade the reference Raspbian image to a latest available to get us past the version gaps in Python. Then we should be able to get all components talking again.

Sorry to hear that! And I appreciate your efforts! I’m surely not the only one with a Google Audio, hooked up to a soundsystem… And it surely would be great if we could fix this, or, as previously mentioned, use a plugin?

To be honest, I dunno where to start with the plugin, so any help would be welcome!

An update… I got it working again but only using a beta Raspian Buster image for Volumio.

So you would need to install the latest Pi image from here:
Volumio Debian Buster Beta - Raspi images debugging and then, reinstall volumio2chromecast based on the updated instructions here… https://github.com/dresdner353/volumio2chromecast. Mileage will vary on well this images works and just FYI it has none of the premium services in case you use any.

I will try to get a UI plugin working at some point to let that Chromecast selection be better integrated. But I’m not going to pursue getting all this working via NodeJS. Someone a lot more node-experienced than me would be a better bet.

To be honest, the problem here is Volumio using an ancient Jesse base stack for the product. Thats from 2015. That’s too old and the Python version fell out of support as have various dependencies.

I tried all kinds of tricks to recompile a later python and some related underlying libraries but it was not getting me anywhere. So the beta image seemed the only alternative.

1 Like

I’ll get a new SD Card to try this out, as soon as time allows. Would be great to have a working and easy to install/manage plugin.

Just committed seek support this morning. So now you can use the progress bar on Volumio to jump to various parts of the track or click he previous track control to go back to the start and it will cue up the Chromecast to match. That was an issue earlier on due to way it had to sync playback between the two.

Very clever!
This can be further extended when the new salsa playback pipeline will be ready :wink:

The code doesn’t interact with the audio DSP in any way whatsoever.

It only checks the API playlist (http://localhost:3000/api/v1/getstate) to determine the current track file path, play/stopped/pause states, seek position & volume values and uses that to ensure that the configured chromecast is engaged and served up a URL for the current track. This works for both music files and even web radio where it serves the radio station URL directly to the chromecast.

The Chromecasts are perfectly suited to play an mp3, flac, m4a and many other formats directly including web streams. They stream the files from the Pi and use on-board hardware to perform the decode and also DAC function in the case of a Chromecast Audio or speaker variants.

Same applies to multi-room playback. The Pi is serving the file URL to just one device in the cast group and they automatically co-ordinate multi-room playback between them. That feature alone is killer IMHO.

In that respect, Volumio is only being used as a management layer for the tracks in terms of controlling playback and organising the music, playlists etc.

I don’t ever see any need to dig deeper into the DSP unless there was some on-the-fly transcoding in play.

Some updates:

  • Updated internal design to leverage python-mpd2 to communicate with the playlist directly via MPD rather than directly to the Volumio API. Seems to respond a lot better this way.

  • The Volumio API is however still used to get album artwork which is important for the default media receiver on normal chromecasts as you get to see it on screen along with the title of the current track/radio station.

  • Also added support for moOde over several days using a separate script and eventually evolved the lot into a single script (mpd2chromecast.py) as the generic one-for-all script that works with both Volumio and moOde and potentially any MPD-based platform. As with Volumio, the script still uses the moOde API to similarly get the current tracks artwork when initiating the cast.

  • Updated install steps as there are subtle differences when installing it on either variant.

See the github link for more details… https://github.com/dresdner353/volumio2chromecast

Some significant rework on the code in the last week.

  • It now runs a web server on http://[your ip]:8080/cast
    You get a drop-down with all discovered Chromecast devices and you can select the desired one or ‘Disabled’ and then click apply. Makes for a very easy means of casting on demand.

  • The device discovery model is redesigned to use a single discovery loop with zeroconf
    This solves problems being observed after long periods where pychromecast/zeroconf would experience socket resource issues. Somehow the mode that had been used was leaking descriptors or something in that regard in zeroconf.

  • Albumart is now served to the cast device direct from album directory
    The code no longer tries to extract albumart from the Volumio API (same for moOde). Instead it checks the files directory for cover.(jpg|png|tiff|bmp|gif) and serves a URL for that to the chromecast. I also added a script to assist in extracting that albumart in case like me, your music collection is mostly made up of embedded albumart.

  • Lastly, the project is renamed to mpd2chromecast (formerly volumio2chromecast)
    So if you have an existing install, you might want to delete the volumio2chromecast directory and follow the install steps again just to get things all synced up to the latest incarnation of this script.

1 Like

Thanks for doing this! I was looking for a way to do it. This seems rather advanced for me, but if I do get a Chromecast speaker, I will try it. I’m looking to buy a HK Citation 500.

Would it be easier to install LMS plugin and the inside LMS installing Castbridge? Can this be done?

Any device that supports Google Cast for audio streaming should just work here. The pychromecast module I used is designed to work that way.

As for LMS, at this stage, IMO it’s not time well spent to keep using it. I was a Squeezebox lover way back but its long-abandoned software now and while it’s a true labour of love for some to keep using it and repackaging it into various modern media streamers, it’s just dragging legacy Perl code around the place with all it’s baggage.

Bear in mind a normal chromecast popped into an AVR or a chromecast audio (if you can find one) via jack RCA/optical might deliver a more optimum experience into better amp hardware than a standalone speaker.

I know, it’s not for my main system, or the second one, it’s for my bedroom, I don’t have the space to setup an amplifier/receiver, or speakers.

I have a dedicated stereo system and an AVR, both have their own RPi with Volumio and an external DAC.

But I’m searching for a solution for my bedroom.

I just installed LMS yesterday and the player. I never knew it existed and what it was for. But I find it remarkable, is the only way to send music to my iPad and iPhone, something that Volumio doesn’t do. And connecting a Dragonfly Red to them I get pretty good sound. It beats having a portable RPi and hauling it around the house!
And also like the iPeng player and remote a whole lot more than Volumio, it gives you the ability to shuffle your library without taking 4 minutes to do it, and gives you an actual queue, something I was hoping Volumio did.

So, for me it’s either LMS or going the Roon way.

Thanks, if I buy that chromecast speaker, I’ll give your solution a shot. Even though I find it rather complex to do. I’ve just been using RPi’s and Volumio for less than a month. Never have used Linux or something similar.

Thank you for this thread!

Unfortunately I have not gotten around to packaging my approach yet into something that could be added like a plugin for Volumio

But bear in mind, even if I could get that plugin written, the latest Volumio releases will just not work with my solution because they are using a Linux release over 5 years old (Raspian Jesse). This causes too many conflicts with versions of the required components.

So my solution only works now on the beta images for Volumio or on moOde or any recent Linux distro running MPD as it’s underlying media layer. I’m hoping Volumio will get their Raspian Buster images on the stable route sooner than later but I can see from a dev thread on this that this will take time.

1 Like