Change your rgb lights color according to spotify album background

Hi

Recently I’ve stumbled upon https://github.com/davidkrantz/Colorfy , and thought it would be great to integrate somewhow in HA. After few hours or reading docs, Ive came to following setup, with for me works great.

Custom component code: https://github.com/zewelor/ha_custom_components/blob/master/color_recognizer/init.py

add custom sensor, to track change of media content id being played, to force light change. In other words, when song change, reanalyze picture, and set matching lights.

- platform: template
  sensors:
    tv_chromecast_media_content_id:
      value_template: "{{ state_attr('media_player.living_room_tv', 'media_content_id') }}"
      friendly_name: TV Chromecast media content id

My automation:

- id: chromecast_ambilight_automation
  alias: Chromecast ambilight
  trigger:
  - entity_id: sensor.tv_chromecast_media_content_id
    platform: state
  condition:
  - condition: template
    value_template: "{{ states('sensor.tv_chromecast_media_content_id') != 'None' }}"
  - delay: 00:00:02
  - data_template:
      entity_id: light.livingroom_wall_lights
      url: 'http://0.0.0.0:8123{{ state_attr(''media_player.living_room_tv'', ''entity_picture'') }}'
      transition: 3
    service: color_recognizer.turn_light_to_recognized_color

its being triggered, when new content is being played on specified chromecast, then it waits 2 seconds, to be sure entity_picture gets updated, and calls custom component service, to change lights.

My custom service color_recognizer.turn_light_to_recognized_color , is passing all arguments to service light.turn_on https://www.home-assistant.io/components/light/#service-lightturn_on, except url param. So you can play with brightness and etc.

If you find some album covers, that gets different background color in spotify vs that custom component, you can play with k and color_tol settings here. I’m not expert in that algos, and I’ve changes k to 4 instead of 8, and you can find in original work. In tests I’ve made it allowed better color recognition. It probably depends on specific cases.

5 Likes

Very cool, I am trying to do the same thing on my hassio installation. On hassio I am not able to install the custom component. Do you have any other ideas how this is possible on hassio?

Im using dockerized HA and custom components works. Afaik they should also work on hassio etc. I dont have any experience with hassio, maybe try on hassio board or file an issue if there is some kind of error handling custom compoents.

I’m attempting to get this working with 0.95.4.

I’ve created a folder in custom_components called color_recognizer and dropped the init.py in there.

Home Assistant doesn’t even tried to load the component on restart, even after adding an empty manifest.json into the same folder. The automation is triggering as I’m seeing an error:

Error while executing automation automation.living_room_spotify_ambilight. Service not found for call_service at pos 2: Unable to find service color_recognizer/turn_light_to_recognized_color

The service doesn’t exist in the Services menu either. Does this component still work for you? I know there have been a lot of changes to the way that custom components work lately, but I’d love to see this working.

Edit: the following is also appearing in the logs on startup:

Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 131, in async_run
    await self._handle_action(action, variables, context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 210, in _handle_action
    action, variables, context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 299, in _async_call_service
    context=context
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 89, in async_call_from_config
    domain, service_name, service_data, blocking=blocking, context=context)
  File "/usr/src/homeassistant/homeassistant/core.py", line 1127, in async_call
    raise ServiceNotFound(domain, service) from None
homeassistant.exceptions.ServiceNotFound: Unable to find service color_recognizer/turn_light_to_recognized_color

I’ve did not use it from some time, it probalby needs update to recent HA version. I will probably work on restoring it, not sure when.

Thanks for the swift response. I’ve been able to overcome the issues above by including an empty services.yaml in the custom component folder, and adding a color_recognizer: in the configuration.yaml.

Now it has issues at startup due to being unable to download scipy:

No module named 'scipy'

I’m going to keep working on it…

Scipy is not installable on hassio, try to install it using https://github.com/home-assistant/hassio-addons-development/tree/master/custom_deps

I think this should work ( custom deps config ) :

{
  "pypi": [
    "numpy",
    "scipy"
  ],
  "apk": [
    "lapack-dev",
    "gfortran",
    "musl-dev",
    "g++"
  ]
}

Thanks for the suggestion, still no joy. I think I’ve found another way to achieve this, so I’ll give that a try next.

Error while executing automation automation.chromecast_ambilight. Unknown error for call_service at pos 1: 
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/automation/__init__.py", line 393, in action
    await script_obj.async_run(variables, context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 131, in async_run
    await self._handle_action(action, variables, context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 210, in _handle_action
    action, variables, context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 299, in _async_call_service
    context=context
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 89, in async_call_from_config
    domain, service_name, service_data, blocking=blocking, context=context)
  File "/usr/src/homeassistant/homeassistant/core.py", line 1150, in async_call
    self._execute_service(handler, service_call))
  File "/usr/src/homeassistant/homeassistant/core.py", line 1174, in _execute_service
    await self._hass.async_add_executor_job(handler.func, service_call)
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/color_recognizer/__init__.py", line 32, in turn_lights_to_recognized_color
    colors = ColorRecognizer(hass, config[DOMAIN], call_data.pop(ATTR_URL)).best_colors()
  File "/config/custom_components/color_recognizer/__init__.py", line 159, in best_colors
    return SpotifyBackgroundColor(image, image_processing_size=DEFAULT_IMAGE_RESIZE).best_color(k=4, color_tol=5)
  File "/config/custom_components/color_recognizer/__init__.py", line 105, in best_color
    from scipy.cluster.vq import kmeans
ModuleNotFoundError: No module named 'scipy'

Would you mind sharing the other method you were able to achieve this with hassio?

Apologies, I hate it when you stumble upon a thread where someone has the same issue as you and they sign off with “it’s ok, I got it working”, whilst giving no explanation!

Here’s what I’ve been using instead:

Ensure you read the thread in full as the user mate2002 has an a link to their github repo where it’s tidied up a bit.

Pros are that you can provide more than one light and it’ll provide each one with a colour from what’s playing, cons are that it requires appdaemon and it isn’t as straight forward as an automation.

In order to get the script to run properly, I had to use the following config in the AppDaemon addon:

{
  "disable_auto_token": false,
  "system_packages": [
    "libcurl",
    "zlib-dev",
    "libjpeg-turbo-dev",
    "libwebp",
    "tk",
    "openjpeg",
    "python3-dev",
    "curl-dev",
    "gcc",
    "g++"
  ],
  "python_packages": [
    "pip==19.0.3",
    "pycurl",
    "Pillow"
  ]
}

There are probably a few components there that are no longer required, worth a bit of a play.

Let us know if you have any trouble getting this working.

1 Like

Well I’ll be, it worked! Thank you so much, I’ve been wrestling with this for way too long.

Happy to help!

There are definitely some packages in that list that aren’t required. When I get the time, I’ll work out which ones to remove and report back here.

1 Like

I am trying this with appdeamon too, but I can’t get it working. My hassio fails to install g++ every time.

I have the same issue since updating from 0.97 to 0.97.1

Ok, there’s an update to AppDaemon that fixes this issue. If you don’t see it available in the Hass.io tab, go to the Addd-on store, press the refresh button, wait a minute or two then go into the AppDaemon add on and it should show the option to update.

However… There’s a new issue, at least for me:

2019-08-10 10:58:10.699066 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/tv_lights_sync.py
2019-08-10 10:58:10.742953 WARNING AppDaemon: ------------------------------------------------------------
2019-08-10 10:58:10.743103 WARNING AppDaemon: Unexpected error loading module: /config/appdaemon/apps/tv_lights_sync.py:
2019-08-10 10:58:10.743460 WARNING AppDaemon: ------------------------------------------------------------
2019-08-10 10:58:10.747003 WARNING AppDaemon: Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/appdaemon/appdaemon.py", line 2026, in check_app_updates
    self.read_app(mod["name"], mod["reload"])
  File "/usr/lib/python3.7/site-packages/appdaemon/appdaemon.py", line 1809, in read_app
    self.modules[module_name] = importlib.import_module(module_name)
  File "/usr/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/config/appdaemon/apps/tv_lights_sync.py", line 5, in <module>
    from PIL import Image
  File "/usr/lib/python3.7/site-packages/PIL/Image.py", line 95, in <module>
    from . import _imaging as core
ImportError: Error loading shared library libtiff.so.5: No such file or directory (needed by /usr/lib/python3.7/site-packages/PIL/_imaging.cpython-37m-x86_64-linux-gnu.so)

I think I have it working again, as well as the AppDaemon update mentioned above; a new system package, tiff is required. My Config now looks like the following:

{
  "disable_auto_token": false,
  "system_packages": [
    "libcurl",
    "zlib-dev",
    **"tiff",**
    "libjpeg-turbo-dev",
    "libwebp",
    "tk",
    "openjpeg",
    "python3-dev",
    "curl-dev",
    "gcc",
    "g++"
  ],
  "python_packages": [
    "pip==19.0.3",
    "pycurl",
    "Pillow"
  ]
}

Everything’s restarted OK, but I won’t have a chance to properly test it until later. Hopefully this fixes it.

I Will have a look at this. I was on version 0.95 and updates to 0.97 Because it didn’t work. The appdeamon update makes sense.

I can confirm it works now. Do you know if it is possible to make a switch in home assistant to enable and disable the app from appdeamon.

Glad it’s working again!

I’m afraid I don’t know the answer to that question. Mine is triggered by an automation. I have it set up so that if the sun is below the horizon and I am playing the Spotify app on one of my Shield TV’s it engages. I’m also thinking about adding an input_boolean into the mix for a manual override.

Yes, indeed I have already tried the input boolean. In condition:, the same way as on Github. Only it doesn’t seem to work for me. If the input boolean is off it stil turns on and changes the lights. Any idea Why?