I have created a new pyscript / tool for Assist. This allows it to use the YouTube API to search for videos and then play them on media players.
PyScript
import aiohttp
import os
async def _search_youtube_videos(query: str, api_key: str, max_results: int = 1):
"""Helper function to search for YouTube videos using the YouTube Data API.
Args:
query: The search query string
api_key: YouTube Data API key
max_results: Maximum number of results to return (default: 1)
"""
base_url = "https://www.googleapis.com/youtube/v3/search"
params = {
"part": "snippet",
"q": query,
"type": "video",
"maxResults": max_results,
"key": api_key
}
# --- Fetch from YouTube Data API using aiohttp (fully async) ---
try:
async with aiohttp.ClientSession() as session:
async with session.get(base_url, params=params, timeout=10) as response:
if response.status != 200:
error_text = await response.text()
log.error(f"YouTube API error {response.status}: {error_text}")
response.raise_for_status()
data = await response.json()
except aiohttp.ClientResponseError as e:
log.error(f"YouTube API request failed: {e}")
raise
except Exception as e:
log.error(f"Unexpected error during YouTube API request: {e}")
raise
items = data.get("items", [])
return items
@service(supports_response="only")
async def search_youtube_video(query: str, api_key: str | None = None):
"""This service searches YouTube for videos matching the query and returns the top result.
Args:
query: The search query string
api_key: YouTube Data API key (if not provided, will try to get from environment variable YOUTUBE_API_KEY)
"""
if not api_key:
api_key = os.getenv("YOUTUBE_API_KEY")
if not api_key:
return { "error": "YouTube API key is required. Provide it as a parameter or set YOUTUBE_API_KEY environment variable." }
# Search for videos
try:
results = await _search_youtube_videos(query, api_key, max_results=1)
except Exception as e:
log.error(f"Failed to search YouTube: {e}")
return { "error": "Failed to search YouTube. Please check API key configuration and ensure YouTube Data API v3 is enabled." }
if not results:
return { "video": "No videos found for the given query" }
# Extract the top result
top_result = results[0]
video_id = top_result.get("id", {}).get("videoId")
snippet = top_result.get("snippet", {})
video_data = {
"videoId": video_id,
"title": snippet.get("title"),
"channelTitle": snippet.get("channelTitle"),
"publishedAt": snippet.get("publishedAt"),
"description": snippet.get("description"),
"thumbnail": snippet.get("thumbnails", {}).get("default", {}).get("url"),
"url": f"https://www.youtube.com/watch?v={video_id}" if video_id else None
}
return { "video": video_data }
HA Script
sequence:
- action: pyscript.search_youtube_video
data:
query: "{{ query }}"
response_variable: video
- action: media_player.play_media
data:
media:
media_content_id: "{{ video.video.url }}"
media_content_type: url
metadata: {}
target:
entity_id: "{{ player }}"
alias: YouTube Video Search
description: >-
Searches YouTube for videos matching the query and plays the top result on the
selected media player. Returns video information including title, channel,
description, and URL.
fields:
query:
selector:
text: null
name: Search Query
description: The search query to find YouTube videos.
required: true
player:
selector:
select:
options:
- media_player.xyz
- media_player.abc
name: Media Player
description: The media player device where the YouTube video will be played.
required: true
icon: mdi:movie-open-play