Google Music in HA -- Now as a media player!

Based on the original gmusic in HA code by @Danielhiversen

The gmusic switch and gmusic using appdaemon had a love child and it’s a media player! :tada:

Well sort of… It should be said first that this is probably not a “properly” written custom component. I’m still very new to even the basics of python and have barely scratched the surface when it comes to “properly” writing a custom component for Home Assistant. Did I mention I’m not a programmer?

I can sum it up like this. There’s the right way and there’s the get it done way. This is a get it done way.

So technically this is not really a media player because it does not actually play any music by itself! However, it is a media player in the sense that it contains media player controls (like Play, Stop, Next Track, etc) and advances through a list songs you want to hear. It is better to think of this more as a media controller. The basic function of gmusic_player is using the gmusicapi to retrieve various lists of songs from Google Music. For example a Playlist or a Station. From that list it obtains the unique ID for each song. Using the song ID, gmusic_player makes another request to gmusicapi (or local gmusicproxy) to obtain a playback url. When gmusic_player receives the url, it finally uses the play_media service to start playback on your selected speakers.

While this is not perfect custom component, it does seem to work rather well so far.

Not perfect:
There’s a few things that are simple to do with appdaemon or even a yaml script that I haven’t got to work as needed from inside the custom component itself. Two things I’m using workarounds for are auto-play when powered on and auto-track advance. Auto-play is handled by a yaml script. The auto-track advance is also a yaml script that is being triggered based on an included template sensor. Fortunately in these cases, as mentioned, a few yaml scripts added to the configuration package file do provide a quick and seemingly efficient workaround. These have already been included. They can remain hidden and should require no interaction on your part.

Otherwise:
The setup and function is much like the original gmusic switch. Additionally, this adds most of the media_player services, the ability to play stations you have added to your music library and an option to use oauth-login for the gmusicapi. This still uses additional input_select(s) and media_play entities as the original switch does. From the input_select(s), your media_player (I call speakers) is selected when the power is turned on. (You have to toggle power off/on if you want to change speakers.) A playlist or station is selected when you press play or use media_player.media_play from an ‘idle’ or ‘stopped’ state. Selected tracks are loaded to the track queue (I refer to track queue as the loaded/playing music.) and begin to play. This means stop/play can be used to change music without powering off the speakers but pause/play is still pause and play.


Install with HACS (Home Assistant Community Store)

hacs_badge

You can use HACS to install and update this custom component for you.
In HACS Settings --> Custom Repositories, add the following:

https://github.com/tprelog/homeassistant-gmusic_player

Category: Integration

Install Manually

Inside your Home Assistant custom_components directory, create another named gmusic_player

Add the following files to custom_components/gmusic_player:
The first two files should only contain a single comment on the first line

custom_components/gmusic_player/__init__.py
custom_components/gmusic_player/services.yaml
custom_components/gmusic_player/manifest.json
custom_components/gmusic_player/media_player.py


Configuration after Install

  • Everything for the configuration is provided using packages.
  • You should only need to edit a few things to get this up and running.
  • If you have never used a packages file SEE HERE.

Add both of the following files to your Home Assistant packages directory


Configuration options: packages/gmusic_config.yaml

This file contains the configuration options for gmusic_player. It is the only file that you should edit. The provided gmusic_config.yaml includes minimum required options.

You also need to configure your media_players here

  • At the bottom, edit the example media_players so they match your own
    speakers: # Example media_players
    - bedroom_stereo
    - workshop_stereo

Possible options for gmusic_config.yaml :

Key Type Required Description
username string YES Set your google music username.
password string YES Set your google music password.
device_id string YES Set your valid device_id here.
token_path string NO Directory with RW access for gmusic_authtoken
gmusicproxy string NO Url for your local gmusic proxy server
shuffle boolean NO Default: True
shuffle_mode integer NO Default: 1

Additional topics


How to find your device id

My account uses Google’s two factor authentication

Using oauth login for Google Music

This requires an existing oauth_credentials file

Key Type Required Description
username string YES Username must be set to oauth.
password string YES Path to existing oauth_credentials file.
device_id string YES Set your valid device_id here.
token_path none NO Not used by oauth!

If you experience skipping to the next track before a song is finished

Yes this happens but I can’t control it. You see, gmusic_player itself is not actually playing any music. (which is why the “speakers” are required) A song can get cut off because the playback url returned by gmusicapi is only valid for one minute. Under certain situations the connection can be reset but since the playback url is no longer valid, the song can not continue streaming so it just cuts off. The automation to advance tracks sees this and triggers the next song.

The quick and easiest workaround to use gmusicproxy. This needs to be installed separately
@miikkajo has created a hassio add-on for such an occasion


Enable streaming from gmusicproxy

Set the gmusicproxy url in gmusic_config.yaml

    gmusicproxy: http://192.168.1.73:9999

How to install the gmusicproxy addon in Home Assistant Supervised

  1. In Home Assistant, select Supervisor from left panel
  2. Go to ADD-ON STORE
  3. Add new repository with url: https://github.com/miikkajo/hassio_addons
  4. Refresh repositories with refresh button up right
  5. Select gmusicproxy addon and click install
  6. Finally start the gmusicproxy addon

When the addon is started and no credentials file is found, the addon will sleep for 3600 sec to wait for configuring oauth credentials.


How to create gmusicproxy oauth credentials

1 - Find the name of the addon container:

sudo docker ps --format '{{.Names}}' | grep gmusicproxy

Example Command Output:

#> sudo docker ps --format '{{.Names}}' | grep gmusicproxy
#> addon_f8f3f8ff_gmusicproxy

2 - Using the container name, start a bash session inside container:

sudo docker exec -i -t addon_f8f3f8ff_gmusicproxy bash

Example Command Output:

#> sudo docker exec -i -t addon_f8f3f8ff_gmusicproxy bash
bash-5.0#

3 - While inside the container, configure the oauth credentials:

/GMusicProxy -o

Example Command Output:
This command generated an error (shown below) but gmusicproxy still seems to works as expected.

bash-5.0# /GMusicProxy -o
Visit the following url:
https://accounts.google.com/o/oauth2/v2/auth?client_id=SOME_LONG_URL...
Follow the prompts, then paste the auth code here and hit enter:

/usr/lib/python3.8/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access /root/.local/share/gmusicapi/mobileclient.cred: No such file or directory
warnings.warn(_MISSING_FILE_MESSAGE.format(filename))
2020-04-11 19:13:26,347 - gmusicapi.Mobileclient1 (shared:176) [WARNING]: could not retrieve oauth credentials from ''/root/.local/share/gmusicapi/mobileclient.cred''
Done.

4 - Restart the gmsuicproxy addon


Select and play music

In similar function to the original gmusic switch, you could make your selections to the input selects ( media player and playlist (or station) ) - When you turn on the gmusic_player, the selected music will play to the selected speakers. To change the speakers and playlist, you could make new selections and toggle power using the button or using media_player services media_player.turn_off followed by media_player.turn_on. Basically the same way the switch works. media_player.toggle can be used to control power as well.


media_player.media_play
When you press play on gmusic_player from an ‘idle’ or ‘stopped’ state, it will (re)load whatever playlist or station you have selected.
Depending on the selected source

media_player.media_play_pause
Or when you press play on gmusic_player from a ‘playing’ or ‘paused’ state. Toggle play/pause.
This is the default media_player action.

media_player.media_stop
If you just want to reload or change the playlist you can stop (not pause) the music.
For gmusic_player you only need to toggle power if you want to change the speakers.

media_player.media_pause
Just pause. Does not toggle back to play

media_player.play_media
This has been replaced by a better alternative - script.gmusic_play_media

media_player.media_previous_track
Or when you press prev on gmusic_player, will play the previous track (not start the current track over)
unless shuffle_mode = 2 or 3

media_player.media_next_track
Or when you press next on gmusic_player, will play the next track

media_player.volume_set
Use 2 digit float from 0 - 1. 100% volume is 1

For example on the services page to set volume at 8% use 0.08:

{
  "entity_id": "media_player.gmusic_player",
  "volume_level": 0.08
}

To set 35% volume use 0.35:

{
  "entity_id": "media_player.gmusic_player",
  "volume_level": 0.35
}

media_player.volume_down
Or when you press volume down on gmusic_player
Decrease volume by 5% increments until 1%.
Use volume_mute or set_volume to 0 for no sound.

media_player.volume_up
Or when you press volume up on gmusic_player
Increase volume by 5% increments.

media_player.volume_mute
Or when you press mute on gmusic_player
Toggles mute on/off.

media_player.shuffle_set
This accepts a boolean so you can only turn shuffle off/on. Tracks are shuffled when the playlist is loaded.
Default is True and shuffle_mode: 1 so playback is similar to the switch. You’ll need to reload the playlist (stop/play) for this to take effect.

To turn off shuffle from the services page:

{
  "entity_id": "media_player.gmusic_player",
  "shuffle": False
}

Shuffle Mode
This can only be set in the package configuration file which means for now having to reboot in order to change this.
In the future this will be media_player.select_sound_mode or a custom service.
I’ll use the term “track queue” to refer to the list playing songs. This could be a “playlist” or a “station” from your music library. There are three modes:

shuffle_mode: 1 - Shuffle (Default setting)
This is the default. Tracks are shuffled first then load to the “track queue”
The shuffled queue is played in order from top to bottom. Songs only repeat when the queue has reached the end and starts over.

shuffle_mode: 2 - Random
This loads the playlist songs is the same order they are saved in your library. Tracks are then randomly selected from anywhere in the queue. Since the queue itself is not being reordered, turning shuffle off/on has immediate effect. The downside here is when playing queues with small numbers of tracks it can seem like the same songs always repeat while others hardly get played.

shuffle_mode: 3 - Shuffle Random
Tracks are shuffled first then load to the “track queue”. Tracks are then randomly selected from anywhere in the queue.

14 Likes

From the appdaemon thread but on this the topic here

I do have the instructions for oauth in the appdaemon version, need to get that transferred. I’m not sure how you go about it on hass.io though. It’s the only reason I set legacy as the default login and included those instructions. I figured it’s easier for most people since hass.io has taken over.
If you are using the legacy login you can sign in using App Passwords to avoid exposing you actual password. I think it’s a decent middle ground if you are unable to create the oauth credentials file.
You are correct though, oauth login is very much prefered.

A custom component card would be awesome and I would certainly appreciate some help and advice in the code department! I’ve wrote some simple bash scripts before but otherwise only have a whole 2 months experience with python or any other programming for that matter.

To get rid of the input selects I do already the list of both available playlists and stations in the gmsuic_player attributes. I was thinking to take shortcut and just use media_player.select_source to set the speakers but I just don’t like the term source here. To me the source is either a playlist or station. I was thinking to try and add a custom service to select_receiver or select_speakers.

I haven’t heard of the app “qcast” but what you describe would be awesome!

Its also possible to generate an Oauth token on your personal PC and transfer it to your HA instance

@troy, thanks so much for this! I’ve toyed with integrating this into my instance of home-assistant for a year or more without much success. All three of your methods have worked fantastically, with this iteration being the simplest/cleanest to throw into my config.

Although this works, I’m presented with the following error when validating my configuration:

Invalid config for [media_player]: required key not provided @ data['platform']. Got None. (See ?, line ?). Please check the docs at https://home-assistant.io/components/media_player/

I’ve looked for typos, extra or not enough spaces in the yaml formatting, but can’t seem to determine the issue. I’ve even re-downloaded the files hosted on your Github account thinking that was the issue. What’s puzzling is even with configuration error, it works with my playlists, stations, and Google cast devices.

The version of home-assistant I’m running is: 0.94.3

@wvdeadhead
Welcome to the forums :grinning:

I’ve just downloaded the files myself to be sure but I am unable to reproduce your error.

Would you mind sharing your package.yaml file? If your not using a secrets file be sure to remove your username, password, device_ id first though!

I actually just found the error… not in you package, but coincidentally was due to my

media_player: !include media_player.yaml

configuration which is now blank due to removing my Google Music MPD server config. I commented out the media_player line in my configuration file to fix.

Thanks for your hard work on getting Google Music in HA and sorry for the false alarm.

No worries! Glad you got it sorted.

And Thank You for trying this out! :grinning:

@troy

I just wanted to thank you for your great efforts on this. I have used this to integrate Google Music onto my NuVo system (including browsing playlists and stations from the keypad) and it has been working flawlessly!

While I’m not sure the feasibility, I have come across a couple things that would make it even better. Those would be access to the ratings (thumbs up/down) and the ability to refresh stations / playlists without restarting HA.

1 Like

Is this awesome component likely to make it into the HACS repository?

@smccoy
Refreshing playlist and stations should be an easy add since I had something for that in the appdaemon version already, but that did require another input boolean to trigger. I was hoping to add that back in here using a custom service instead.

I’ve been wanting to do something for ratings as well. Again something I was hoping to use a custom services for. Aside from using a custom service, It’s definitely on my plate but I haven’t spent any time with time with the ratings yet so I’m not sure how difficult it will be integrate but I sure it’s possible

@sparkydave
Definitely something I would like to do in the future. I don’t think I need too much for this to work but I will need to make some new git repos. A requirement is for HACS is only ONE custom component per repo so I need to split some things up on my side.


I’ll admit I’ve been slacking on this (and everything else involving sitting at a computer) for a few week though, Works been busier than expected and summertime hobbies are fighting for attention as well. I will get back soon.

Thanks for all your hard work on this Troy! I’ve just got it working in my own installation and am very pleased with it. :smile:

1 Like

I’m happy to hear that these are in the potential pipeline. I look forward to adding these features when that time comes! I understand the busy thing well. Hence the (extended) delay in my response. There are so many things to occupy time when the weather is nice.

This component is still working great for me. I have noticed that after restarting HA, I cna often only play 1 song from a station (and sometimes playlist) and it stops. It takes some combination of power cycling the media player or switching to playlist to restore playback at which point it works great again. Has anyone else seen similar behavior?

1 Like

Thanks for this. Not directly related but I’m trying use my MiBox3 (as “speakers”) which is setup as a media player using the cast platform, but whenever I try to play content I get an error saying it is not a valid media player and the gmusicplayer wont turn on. Any ideas?

2019-07-24 21:41:27 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection.139909208805456] Received {'type': 'call_service', 'domain': 'media_player', 'service': 'play_media', 'service_data': {'entity_id': 'media_player.gmusic_player', 'media_content_type': 'station', 'media_content_id': "'90s Alternative Rock"}, 'id': 20}
2019-07-24 21:41:27 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=media_player, service=play_media, service_data=entity_id=media_player.gmusic_player, media_content_type=station, media_content_id='90s Alternative Rock>
2019-07-24 21:41:27 ERROR (SyncWorker_5) [custom_components.gmusic_player.media_player] (media_player.mibox3) is not a valid media player.

This looks awesome, thanks for your work. Would love to see it in hacs. Two questions:

Will this work with Google’s two factor authentication?

How do I get a device ID?

Thanks for your help.

If your using two factor auth you need to use an App Password.
To be clear, it’s a Google thing: Instructions can be found here

To get a valid device id is pretty simple trick. Just try to log in without one!
Your username and password (use app password you just created) must be correct. Enter something like 00 as you device id then restart HA. Google Music will fail login with id 00 but in the logs you will find your valid device ids.

Look for this error in HA logs and click on it to view more information.

If your username and password are valid for Google Music, it will give you a list of your valid device ids. You may have more or less device ids in your list but any of them should work.

I’ve tried this now with a Gen3 Chromecast and still get the same error

[custom_components.gmusic_player.media_player] (media_player.chromecast6209) is not a valid media player.

@slipx06 I’m so sorry I missed your first post.

In the package file where you have configured your media_players or “speakers” did you happen to add the media_play. prefix to your speakers? media_player. should not be added to names in this list.

I’m taking a guess here, but I feel like your config might for example look like this:

input_select:
  gmusic_player_speakers:
    name: Speakers
    icon: mdi:speaker
    options: ## ONLY HERE - Replace with entity_ids of your own media_players
    - media_player.mibox3
    - media_player.chromecast6209

Please try removing media_player. so it looks like this:

input_select:
  gmusic_player_speakers:
    name: Speakers
    icon: mdi:speaker
    options: ## ONLY HERE - Replace with entity_ids of your own media_players
    - mibox3
    - chromecast6209
1 Like

Yes that was the problem. Thank you for the help. It’s working now. Great job

1 Like

I finally got this up and running properly, and it’s nice to be able to automate with my harmony for difference scenes. I was curious though, since I’m casting this to a TV, and it only just shows “Default Media Receiver” instead of the song data, is there any way/plan to be able to mirror the song data from the gmusic_player instance to the playing chromecast?

@spcedrgn Welcome!

I’m sorry, off the top of my head I can not provide something as simple to just copy and paste but I think you could use an automation to set the state of these “Default Media Receiver” attributes.

 media_artist
 media_album_name
 media_title
 entity_picture

I can look more into providing a copy and paste solution for this case but it will be a while before I have time to return to working on this project.