Improve active player artwork detection

This commit is contained in:
ltadeu6 2026-04-15 17:00:53 -03:00
parent 9b07740b53
commit d7af92f6b1
No known key found for this signature in database
GPG key ID: FB9FDAB6B6F3418D
3 changed files with 146 additions and 14 deletions

View file

@ -5,14 +5,14 @@ import colorsys
import subprocess
import time
from io import BytesIO
from typing import Optional
from urllib.parse import parse_qs, urlparse
import requests
from PIL import Image
HA_URL = "http://192.168.1.105:8123"
HA_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkZjM1MmRhNjg1ZWM0MGJiYTc4YTZlNWY3ZmQ0YTA1YSIsImlhdCI6MTc3NjI4MTI0MiwiZXhwIjoyMDkxNjQxMjQyfQ.rR0Kfwk5Smr06_9KJSDn3YPXiRlokEZZFiAa_naNs78"
LIGHT_ENTITY = "light.luz_sala"
LIGHT_ENTITY = "light.luzsala_luz_sala"
# Ajustes visuais
BRIGHTNESS_PCT = 70
@ -22,9 +22,14 @@ MIN_VALUE = 0.18
REQUEST_TIMEOUT = 10
def run_playerctl(field: str) -> str:
def run_playerctl(field: str, player: str | None = None) -> str:
command = ["playerctl"]
if player:
command.extend(["--player", player])
command.extend(["metadata", field])
result = subprocess.run(
["playerctl", "metadata", field],
command,
capture_output=True,
text=True,
)
@ -33,15 +38,103 @@ def run_playerctl(field: str) -> str:
return result.stdout.strip()
def get_current_track_id() -> str:
title = run_playerctl("title")
artist = run_playerctl("artist")
art = run_playerctl("mpris:artUrl")
return f"{artist}::{title}::{art}"
def list_players() -> list[str]:
result = subprocess.run(
["playerctl", "-l"],
capture_output=True,
text=True,
)
if result.returncode != 0:
return []
return [line.strip() for line in result.stdout.splitlines() if line.strip()]
def get_album_art_url() -> str:
return run_playerctl("mpris:artUrl")
def player_status(player: str) -> str:
result = subprocess.run(
["playerctl", "--player", player, "status"],
capture_output=True,
text=True,
)
if result.returncode != 0:
return ""
return result.stdout.strip()
def choose_active_player() -> str:
for player in list_players():
if player_status(player) == "Playing":
return player
return ""
def get_track_url(player: str) -> str:
return run_playerctl("xesam:url", player)
def get_player_name(player: str) -> str:
result = subprocess.run(
["playerctl", "--player", player, "metadata", "--format", "{{playerName}}"],
capture_output=True,
text=True,
)
if result.returncode != 0:
return player
return result.stdout.strip() or player
def youtube_video_id(url: str) -> str:
if not url:
return ""
parsed = urlparse(url)
host = parsed.netloc.lower()
path = parsed.path.strip("/")
if host in {"youtu.be", "www.youtu.be"}:
return path.split("/", 1)[0]
if "youtube.com" not in host:
return ""
if path == "watch":
return parse_qs(parsed.query).get("v", [""])[0]
parts = path.split("/")
if len(parts) >= 2 and parts[0] in {"shorts", "live", "embed", "v"}:
return parts[1]
return ""
def youtube_thumbnail_url(player: str) -> str:
video_id = youtube_video_id(get_track_url(player))
if not video_id:
return ""
return f"https://i.ytimg.com/vi/{video_id}/hqdefault.jpg"
def get_current_track_id(player: str) -> str:
title = run_playerctl("title", player)
artist = run_playerctl("artist", player)
art = run_playerctl("mpris:artUrl", player)
url = get_track_url(player)
player_name = get_player_name(player)
return f"{player_name}::{artist}::{title}::{art or url}"
def get_album_art_url(player: str) -> str:
art_url = run_playerctl("mpris:artUrl", player)
if art_url:
return art_url
track_url = get_track_url(player)
if youtube_video_id(track_url):
thumb_url = youtube_thumbnail_url(player)
if thumb_url:
print(f"Usando thumbnail do YouTube: {thumb_url}")
return thumb_url
return ""
def load_image_from_url(url: str) -> Image.Image:
@ -54,9 +147,15 @@ def load_image_from_url(url: str) -> Image.Image:
return Image.open(BytesIO(resp.content)).convert("RGB")
def image_pixels(img: Image.Image) -> list[tuple[int, int, int]]:
if hasattr(img, "get_flattened_data"):
return list(img.get_flattened_data())
return list(img.getdata())
def good_pixels(img: Image.Image) -> list[tuple[int, int, int]]:
img = img.resize((80, 80))
pixels = list(img.getdata())
pixels = image_pixels(img)
filtered: list[tuple[int, int, int]] = []
for r, g, b in pixels:
@ -130,14 +229,19 @@ def main() -> None:
while True:
try:
track_id = get_current_track_id()
player = choose_active_player()
if not player:
time.sleep(2)
continue
track_id = get_current_track_id(player)
if not track_id or track_id == "::":
time.sleep(2)
continue
if track_id != last_track:
art_url = get_album_art_url()
art_url = get_album_art_url(player)
if not art_url:
print("Sem capa disponível para a faixa atual.")
last_track = track_id