Hello everyone.
When connected via AirPlay, the Apple TV integration in Home Assistant cannot retrieve the thumbnail of a YouTube video playing on the Apple TV’s YouTube app
I was searching for a solution to this issue when I came across matt8707’s project. youtube-watching
However, it did not work well in my environment, so I integrated it into AppDaemon.
It can be installed via HACS, and the MQTT integration is required. It’s easy to use.
You no longer need to use Appdaemon
in a complicated way. Mattias Persson has provided us with an excellent solution.
However, I’ll keep maintaining the AppDaemon project for those who find the following setup difficult. Haha.
For Haos
- A
cookies.txt
file is still required. - Your version of yt-dlp must be
2025.03.31
or later. Even if your Home Assistant core version is2025.4.1
, you still need to update it.
2-1. Log in to the console window. It’s not an ssh addon or putty!
2-2. Runlogin
2-3. Rundocker exec -it homeassistant /bin/bash
2-4. Runpip install -U yt-dlp
2-5. Runpython3 -c "import yt_dlp; print(yt_dlp.version.__version__)"
(Verify that the update is complete. If it outputs 2025.03.31, then it’s OK.) - In the
/config(homeassistant)
/python(any folder name)/
, create two files:youtube_thumbnail.py
andset_entity_picture.py
. - Add the following to
/config/secrets.yaml
:
ha_host: "http://{your_ha_ip}:8123"
ha_token: "{your-long-lived-token}"
- Insert the following code into
youtube_thumbnail.py
:
import yt_dlp
import json
URL = "https://www.youtube.com/feed/history"
ydl_opts = {
"cookiefile": "/config/python/.cookies.txt",
"skip_download": True,
"playlist_items": "1",
"quiet": True,
"no_warnings": True,
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(URL, download=False)
data = ydl.sanitize_info(info)
entry = data.get("entries", [data])[0]
print(
json.dumps(
{
"channel": entry.get("channel"),
"title": entry.get("fulltitle"),
"video_id": entry.get("id"),
"thumbnail": entry.get("thumbnail"),
"original_url": entry.get("original_url"),
},
indent=2,
)
)
- Insert the following code into
set_entity_picture.py
:
EDIT
from secrets import get_secret
did not work in the haos. It works successfully after loading thesecrets.yaml
file as shown below.
import argparse
import requests
import yaml
with open('/config/secrets.yaml') as f:
secrets = yaml.safe_load(f)
HOST = get_secret("ha_host")
TOKEN = get_secret("ha_token")
def update_entity_picture(entity_id, entity_picture):
url = f"{HOST}/api/states/{entity_id}"
headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
data = response.json()
data["attributes"]["entity_picture"] = entity_picture
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
print("ok")
else:
print("Error posting update: ", response.text)
else:
print("Error retrieving state: ", response.text)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="update entity_picture")
parser.add_argument("--entity_id", required=True, help="entity_id")
parser.add_argument("--entity_picture", required=True, help="entity_picture")
args = parser.parse_args()
update_entity_picture(args.entity_id, args.entity_picture)
- Add the following command_line sensor to
/config/configuration.yaml
:
command_line:
- sensor:
name: youtube_thumbnail
command: "python3 /config/python/youtube_thumbnail.py"
value_template: "{{ value_json.thumbnail }}"
json_attributes:
- channel
- title
- video_id
- thumbnail
- original_url
scan_interval: 86400
- Add the following shell_command to
/config/configuration.yaml
:
shell_command:
set_entity_picture: "python3 /config/python/set_entity_picture.py --entity_id '{{ entity_id }}' --entity_picture '{{ entity_picture }}'"
- Create an automation.
alias: Set youtube entity_picture
triggers:
- trigger: state
entity_id:
- media_player.sovrum
- media_player.vardagsrum
to:
- playing
- paused
conditions:
- condition: template
value_template: >
{% set entity_id = trigger.entity_id %}
{% set youtube = 'sensor.youtube_thumbnail' %}
{{ is_state_attr(entity_id, 'app_id', 'com.google.ios.youtube')
and (state_attr(entity_id, 'media_artist') != state_attr(youtube, 'channel'))
and (state_attr(entity_id, 'media_title') != state_attr(youtube, 'title')) }}
actions:
- action: homeassistant.update_entity
data:
entity_id:
- sensor.youtube_thumbnail
- action: shell_command.set_entity_picture
data:
entity_id: >
{{ trigger.entity_id }}
entity_picture: >
{{ states('sensor.youtube_thumbnail') }}
mode: single
- It’s done. Now, when you play or pause the Apple TV, the
media_player.apple_tv (used as a trigger in the automation)
will have anentity_picture
attribute.