Tautulli Analytics Integration
This skill helps with Tautulli analytics features in homescreen-hero. Tautulli provides streaming metrics and watch history from Plex servers.
Key Files
- [tautulliclient.py](homescreenhero/core/integrations/tautulli_client.py) - Tautulli API client
- [tautullianalytics.py](homescreenhero/core/integrations/tautulli_analytics.py) - Analytics collection logic
- [analytics.py](homescreen_hero/core/db/analytics.py) - Database operations for analytics
- [analytics.py](homescreen_hero/web/routers/analytics.py) - API endpoints
Tautulli Client Overview
The TautulliClient wraps the Tautulli API v2. It handles:
- API authentication via API key in URL params
- Response parsing (Tautulli wraps responses in
{"response": {"result": "success", "data": ...}})
- Error handling for timeouts, auth failures, HTTP errors
Key Methods
| Method |
Purpose |
Returns |
ping() |
Health check |
(bool, Optional[str]) - success status and error message |
get_libraries() |
Get Plex libraries |
List of library dicts with section_id |
getcollectionstats(ratingkey, querydays) |
Watch stats for a collection |
Dict with totalplays, totalduration |
get_history(length, start) |
Watch history entries |
List of history dicts with timestamps |
getuserwatchtimestats(query_days) |
User watch stats |
List of user stats |
getplaysbydate(timerange, y_axis) |
Play counts by date |
Dict with categories (dates) and series (play data) |
getplaysbyhourofday(timerange, y_axis) |
Play counts by hour |
Dict with categories (hours) and series |
getplaysbystreamtype(timerange, yaxis) |
Plays by stream type with concurrent streams |
Dict with stream type data including max concurrent |
Configuration
Tautulli requires:
HSHTAUTULLIAPI_KEY environment variable (or in config.yaml)
HSHTAUTULLIBASE_URL environment variable (default: http://localhost:8181)
enabled: true in config.yaml under tautulli section
Analytics Module
The tautulli_analytics.py module collects watch statistics and stores them in SQLite:
Main Functions
collectanalyticsforcollections(config, collectionnames, rotation_id)
- Collects watch stats for specified collections
- Finds collections in Plex libraries using rating_key
- Aggregates stats from all items in each collection
- Stores snapshots in the database via
recordcollectionanalytics()
- Returns summary dict with
collected, failed, and total_collections
collectanalyticsforallactive(config)
- Collects analytics for all currently promoted collections
- Queries Plex for collections with visibility > 0
- Uses
collectanalyticsfor_collections() internally
Data Flow
- Find collection in Plex - Search enabled libraries for collection by name
- Get rating_key - Extract Plex's internal ID for the collection
- Query Tautulli - Use rating_key to get watch stats from Tautulli API
- Aggregate - Sum stats across all items in the collection
- Store - Save snapshot to
collection_analytics table in SQLite
Common Tasks
Adding a New Chart
When adding a new chart to the frontend:
- Check if the Tautulli API endpoint exists in
tautulli_client.py
- Add method to client if needed (follow pattern of existing methods)
- Create API endpoint in
homescreen_hero/web/routers/analytics.py
- Fetch data in React component using the new endpoint
- Use Recharts components to visualize
Testing Tautulli Connection
from homescreen_hero.core.integrations.tautulli_client import get_tautulli_client
from homescreen_hero.core.config.loader import load_config
config = load_config()
client = get_tautulli_client(config)
if client:
success, error = client.ping()
print(f"Tautulli connection: {'OK' if success else f'Failed - {error}'}")
Fetching Watch Stats
# Get stats for a specific collection (by rating_key)
stats = client.get_collection_stats(rating_key=12345, query_days=30)
print(f"Total plays: {stats['total_plays']}")
# Get play history
history = client.get_history(length=100)
for entry in history:
print(f"{entry['user']}: {entry['title']} at {entry['date']}")
API Response Formats
getcollectionstats
{
"total_plays": 42,
"total_duration": 7200,
"total_time": "2h 0m"
}
getplaysby_date
{
"categories": ["2024-01-01", "2024-01-02", ...],
"series": {
"Movies": [5, 8, 3, ...],
"TV": [12, 15, 10, ...]
}
}
getplaysbystreamtype
{
"categories": ["2024-01-01", "2024-01-02", ...],
"series": {
"Direct Play": [5, 8, ...],
"Direct Stream": [3, 2, ...],
"Transcode": [1, 4, ...],
"Concurrent Streams": [8, 12, ...] // Max concurrent per day
}
}
Database Schema
Analytics are stored in collection_analytics table:
collection_name - Name of the collection
plex_library - Library name (Movies, TV Shows, etc.)
rating_key - Plex rating key
total_plays - Total play count
totaldurationseconds - Total watch time in seconds
unique_users - Count of unique users (nullable)
rotation_id - FK to rotation that triggered collection (nullable)
collected_at - Timestamp of collection
extra_data - JSON field for additional metadata
Notes
- Tautulli tracks stats per-item, not per-collection
- Analytics module aggregates item-level stats to collection-level
- Concurrent streams calculation requires analyzing overlapping watch history timestamps
- All API methods include error handling and logging
- Use
logger.debug() for API requests, logger.info() for successful operations, logger.error() for failures