Emby Live TV Channel Logo Updater
Automatically copy or clear Live TV channel logos in Emby Server.
What It Does
- Copy Mode (default): Copies the Primary logo (Logo Dark Version) to LogoLight (Logo Light Version) and LogoLightColor (Logo Light with Colour) for all TV channels
- Clear Mode (
--clear): Removes all logos (Primary, LogoLight, LogoLightColor) from channels
Quick Start (Docker - Recommended)
-
Copy the environment template:
cp .env.example .env -
Edit
.envand set your Emby credentials:EMBY_SERVER_URL=https://your-emby-server.com EMBY_API_KEY=your_api_key_here -
Test with dry run on first channel:
docker compose up -
When ready, enable execution: Edit
.envand set:DRY_RUN=false FIRST_ONLY=false -
Run in the background:
docker compose up -d
See the Docker Usage section for detailed configuration.
Requirements
- Docker (recommended): Docker and Docker Compose - uses pre-built image from GHCR
- Python (alternative): Python 3.6+
- Emby Server with API access
- API key from Emby Server
Getting Your API Key
- Log into Emby Server as an administrator
- Go to Settings → Advanced → API Keys
- Create a new API key or use an existing one
Docker Usage (Recommended)
Configuration
All configuration is done via the .env file. Copy .env.example to .env and customize:
cp .env.example .env
Required Settings
| Variable | Description |
|---|---|
EMBY_SERVER_URL |
Your Emby server URL (e.g., https://emby.example.com) |
EMBY_API_KEY |
Your Emby API key |
Optional Settings
| Variable | Default | Description |
|---|---|---|
MODE |
copy |
Operation mode: copy (copy logos) or clear (delete logos) |
DRY_RUN |
true |
true = simulate only, false = execute changes |
FIRST_ONLY |
false |
true = process first channel only (for testing) |
FORCE |
false |
true = overwrite existing logos (copy mode only) |
TAGS |
(empty) | Comma-separated list of tags to filter channels (e.g., sports,news) |
LIST_TAGS |
false |
true = list all available tags and exit |
CRON_SCHEDULE |
0 3 * * * |
Cron schedule (default: daily at 3 AM) |
RUN_ONCE |
false |
true = run once and exit, false = run on schedule |
TZ |
UTC |
Timezone for cron (e.g., America/New_York) |
Common Scenarios
Discover Available Tags
# In .env:
LIST_TAGS=true
RUN_ONCE=true
# Run:
docker compose up
Safe Testing (Recommended First Run)
# In .env:
MODE=copy
DRY_RUN=true
FIRST_ONLY=true
# Run:
docker compose up
Production - Daily Updates
# In .env:
MODE=copy
DRY_RUN=false
CRON_SCHEDULE=0 3 * * *
# Run in background:
docker compose up -d
One-Time Update Now
# In .env:
MODE=copy
DRY_RUN=false
RUN_ONCE=true
# Run:
docker compose up
Force Overwrite Existing Logos
# In .env:
MODE=copy
DRY_RUN=false
FORCE=true
# Run:
docker compose up -d
Clear All Logos (Use with Caution!)
# In .env:
MODE=clear
DRY_RUN=false
# Run:
docker compose up
Process Only Channels with Specific Tags
# In .env:
MODE=copy
DRY_RUN=false
TAGS=sports,news
# Run:
docker compose up -d
Force Update Sports Channels Only
# In .env:
MODE=copy
DRY_RUN=false
FORCE=true
TAGS=sports
# Run:
docker compose up
Docker Commands
# Build and start
docker compose up
# Start in background
docker compose up -d
# View logs
docker compose logs -f
# Stop
docker compose down
# Build locally (if modifying source)
# Uncomment "build: ." in docker-compose.yml, then:
docker compose up --build
Cron Schedule Examples
Format: minute hour day month weekday
| Schedule | Description |
|---|---|
0 3 * * * |
Daily at 3 AM (default) |
0 */6 * * * |
Every 6 hours |
0 0 * * 0 |
Weekly on Sunday at midnight |
0 2 1 * * |
Monthly on the 1st at 2 AM |
*/30 * * * * |
Every 30 minutes |
Python Usage (Alternative)
If you prefer to run the script directly with Python instead of Docker:
Copy Logos (Default Mode)
Dry run (see what would happen without making changes):
python update_channel_logos.py \
--server https://your-emby-server.com \
--api-key YOUR_API_KEY
Execute (actually make changes):
python update_channel_logos.py \
--server https://your-emby-server.com \
--api-key YOUR_API_KEY \
--execute
Test on first channel only:
python update_channel_logos.py \
--server https://your-emby-server.com \
--api-key YOUR_API_KEY \
--first-only \
--execute
Clear All Logos
Dry run:
python update_channel_logos.py \
--server https://your-emby-server.com \
--api-key YOUR_API_KEY \
--clear
Execute:
python update_channel_logos.py \
--server https://your-emby-server.com \
--api-key YOUR_API_KEY \
--clear \
--execute
Command-Line Options
| Option | Description |
|---|---|
--server |
Required. Emby server URL (e.g., https://emby.example.com) |
--api-key |
Required. Your Emby API key |
--execute |
Actually perform the changes (without this, runs in dry-run mode) |
--first-only |
Only process the first channel (useful for testing) |
--clear |
Clear all logos instead of copying them |
--force |
Overwrite existing LogoLight/LogoLightColor (copy mode only) |
--tags |
Comma-separated list of tags to filter channels (e.g., sports,news) |
--list-tags |
List all available tags and exit |
--non-interactive |
Skip confirmation prompts (for automated execution) |
Examples
Recommended workflow:
-
Discover available tags:
python update_channel_logos.py --server URL --api-key KEY --list-tags -
Test on first channel with dry run:
python update_channel_logos.py --server URL --api-key KEY --first-only -
Execute on first channel:
python update_channel_logos.py --server URL --api-key KEY --first-only --execute -
If successful, run on all channels:
python update_channel_logos.py --server URL --api-key KEY --execute -
Process only channels with specific tags:
python update_channel_logos.py --server URL --api-key KEY --tags sports,news --execute
How It Works
- Connects to your Emby server
- Fetches all Live TV channels
- Filters channels by tags (if specified)
- For each channel:
- Copy mode: Downloads the Primary logo and uploads it as LogoLight and LogoLightColor
- Clear mode: Deletes Primary, LogoLight, and LogoLightColor
- Skips channels that already have the logos (copy mode, unless
--forceis used) or have no logos (clear mode) - Shows a summary of results
Safety Features
- Dry run by default: Always runs in simulation mode unless
--executeis specified - Confirmation prompt: Asks for confirmation before executing changes
- First-only testing: Test on a single channel before processing all channels
- Skip existing: In copy mode, skips channels that already have both light logos (unless
--forceis used) - Force mode: Use
--forceto overwrite existing LogoLight/LogoLightColor images with the current Primary logo
Notes
- The script only affects Live TV channels, not other media
- Changes may take a few moments to appear in the Emby interface
- You may need to refresh your browser/app to see changes
- Use
--clearwith caution - it deletes logos from all channels