Production-readiness pass: security hardening, performance improvements, new services (send_message, set_repeat, refresh_library), diagnostics, reauth flow, image proxy, per-instance device IDs, exponential WS reconnect backoff, ID validation, stale device cleanup, and supporting integration plumbing. Three rounds of independent code review applied. See RELEASE_NOTES.md for the full changelog.
Emby Media Player
A Home Assistant custom integration that exposes Emby Server clients as media players with full playback control, real-time WebSocket updates, library browsing, repeat-mode control, and on-screen messaging.
Features
Playback & metadata
- Full media-player control: play, pause, stop, seek, volume, mute, next/previous track, repeat mode.
- Real-time updates over WebSocket with a slow REST poll as a safety net —
PlaybackStart,PlaybackProgress, andPlaybackStoppedevents update the entity in place. - Now-playing metadata: title, artist, album, series / season / episode, artwork, duration, position, play method (DirectPlay / DirectStream / Transcode).
- Per-client device class inferred from the Emby client (AndroidTV / Kodi / Roku → TV, music clients → speaker, others → generic).
- Enqueue semantics mapped to Emby commands: HA's
play/replace→PlayNow,next→PlayNext,add→PlayLast.
Library
- Browse the Emby library from Home Assistant's media browser — Movies, TV Shows, Music, Playlists, user views.
- Server-side image proxy — artwork is fetched with the API key in an HTTP header and never leaks into URLs in the browser.
Security & reliability
- API key never appears in URLs (no query-string leakage to proxy logs or browser history).
- Per-instance device IDs derived from the Home Assistant UUID — multiple HA installs no longer collide on the same Emby server.
- Self-signed HTTPS support via a
verify_ssltoggle. - Reauth flow prompts for a fresh API key when the server rejects the current one.
- Exponential backoff with jitter for WebSocket reconnects; auth failures stop the retry loop.
- ID validation on all session / item / user identifiers (defense in depth against path traversal in REST paths).
- Stale device cleanup removes media-player devices for sessions that disappear for over 30 minutes (with a 10-minute grace period after startup).
Integration plumbing
- Diagnostics — Settings → Integrations → "..." → Download diagnostics for a redacted JSON dump (API key and session IDs are hashed/redacted).
- Hub device linked to per-session devices via
via_device— easier to clean up. - Zeroconf + SSDP discovery hints so Emby servers can be found by HA.
- Three services:
send_message,set_repeat,refresh_library.
Installation
HACS (Recommended)
- Open HACS in Home Assistant.
- Click on Integrations.
- Click the three-dots menu and select Custom repositories.
- Add this repository URL and select Integration as the category.
- Click Install.
- Restart Home Assistant.
Manual Installation
- Download the
custom_components/emby_playerfolder. - Copy it to your Home Assistant
custom_componentsdirectory. - Restart Home Assistant.
Configuration
- Go to Settings → Devices & Services.
- Click Add Integration and search for Emby Media Player.
- Enter your Emby server details:
- Host — Emby server hostname or IP address.
- Port — default
8096(HTTP) or8920(HTTPS). - API Key — created in Emby Dashboard → Extended → API Keys.
- Use SSL — enable if your server uses HTTPS.
- Verify SSL certificate — disable only when using a self-signed certificate that HA's CA bundle doesn't trust.
- Select the Emby user account to use for browsing & playback.
- Click Submit.
Getting an API key
- Open your Emby Server Dashboard.
- Navigate to Extended → API Keys.
- Click New API Key (+ button).
- Give it a name (e.g.,
Home Assistant). - Copy the generated key.
Admin keys list all users automatically. Non-admin keys fall back to the public users endpoint — the integration handles both.
Reauthentication
If you regenerate the API key on the Emby server, Home Assistant will flag the integration as needing attention and walk you through entering the new key — no need to remove and re-add the integration.
Options
After configuration, open Configure on the integration to adjust:
- Scan Interval (5–60 s, default
10). Used as the polling cadence while the WebSocket is unavailable. When the WebSocket is connected, the integration drops to a 5-minute REST safety-net poll automatically.
Supported Features
| Feature | Support |
|---|---|
| Play / Pause | Yes |
| Stop | Yes |
| Volume Control | Yes |
| Volume Mute | Yes |
| Seek | Yes |
| Next Track | Yes |
| Previous Track | Yes |
| Repeat Mode | Yes |
| Media Browser | Yes |
| Play Media | Yes |
| Enqueue / Play Next | Yes |
Entity Attributes
Each media player entity exposes the following attributes:
| Attribute | Description |
|---|---|
session_id |
Emby session identifier |
device_id |
Device identifier |
device_name |
Name of the playback device |
client_name |
Emby client application name |
user_name |
Emby user currently signed in on the client (when available) |
item_id |
Currently playing item ID (only while playing) |
item_type |
Type of media (Movie, Episode, Audio, …) |
play_method |
DirectPlay, DirectStream, or Transcode (only while playing) |
Services
emby_player.send_message
Display a banner notification on an Emby client. Great for doorbells, alarms, laundry timers, etc.
| Field | Required | Description |
|---|---|---|
entity_id |
Yes | One or more Emby media-player entities. |
message |
Yes | Text to display. |
header |
No | Optional header / title. |
timeout_ms |
No | How long to show the message (100–60000 ms). |
service: emby_player.send_message
target:
entity_id: media_player.emby_living_room_tv
data:
header: "Doorbell"
message: "Someone's at the front door"
timeout_ms: 5000
emby_player.set_repeat
Set the repeat mode on the current playback.
| Field | Required | Description |
|---|---|---|
entity_id |
Yes | One or more Emby media-player entities. |
repeat_mode |
Yes | One of RepeatNone, RepeatOne, or RepeatAll. |
service: emby_player.set_repeat
target:
entity_id: media_player.emby_living_room_tv
data:
repeat_mode: RepeatAll
The standard HA media-player repeat control is also wired up —
media_player.repeat_setwill work without using this service.
emby_player.refresh_library
Trigger a server-side library scan. If entity_id is omitted, all configured
Emby servers are refreshed.
service: emby_player.refresh_library
Diagnostics
Open Settings → Integrations → Emby Media Player → "..." → Download diagnostics to get a redacted JSON dump containing the entry, the current sessions, server id, and WebSocket connection status. Useful when filing bug reports.
The dump redacts the API key and replaces real session / device / user IDs with stable hashes so it's safe to share.
Automation Examples
Dim lights when a movie starts
automation:
- alias: "Dim lights for movie"
trigger:
- platform: state
entity_id: media_player.emby_living_room_tv
to: "playing"
condition:
- condition: template
value_template: "{{ state_attr('media_player.emby_living_room_tv', 'item_type') == 'Movie' }}"
action:
- service: light.turn_on
target:
entity_id: light.living_room
data:
brightness_pct: 20
Pause playback when the doorbell rings, then notify the screen
automation:
- alias: "Pause Emby on doorbell"
trigger:
- platform: state
entity_id: binary_sensor.doorbell
to: "on"
action:
- service: media_player.media_pause
target:
entity_id: media_player.emby_living_room_tv
- service: emby_player.send_message
target:
entity_id: media_player.emby_living_room_tv
data:
header: "Doorbell"
message: "Someone is at the door"
timeout_ms: 8000
Toggle shuffle/repeat from a script
script:
emby_repeat_all:
sequence:
- service: media_player.repeat_set
target:
entity_id: media_player.emby_living_room_tv
data:
repeat: all
Troubleshooting
Connection issues
- Verify the Emby server is reachable from the Home Assistant host (try
ping/curl http://<host>:8096/emby/System/Infofrom a terminal on the HA box). - Check that the API key is valid and not revoked in Emby Dashboard → Extended → API Keys.
- For HTTPS with a self-signed certificate, toggle Verify SSL certificate off in the integration config.
- If reauth keeps failing, regenerate the API key on the server and try again.
No media players appearing
- Media-player entities are only created for active sessions that support remote control. Start playback on an Emby client first.
- Browser-based Emby Web sessions usually do not support remote control and won't appear as entities.
- Check Settings → System → Logs in Home Assistant for messages from
custom_components.emby_player.
WebSocket connection failed
If the WebSocket can't connect, the integration falls back to REST polling at the configured Scan Interval. To restore real-time updates:
- Allow WebSocket traffic to TCP
8096/8920from the HA host. - If you run Emby behind a reverse proxy, make sure
Upgrade/Connectionheaders are forwarded for/embywebsocket. - For HTTPS proxies (Caddy / Traefik / nginx), confirm the WebSocket path is included in the proxy config.
Stale devices in the registry
Devices for sessions that haven't been seen for 30 minutes are removed automatically (after a 10-minute startup grace). You can also manually delete a device from Settings → Devices & Services → Emby Media Player → Device → Delete.
Versioning
See RELEASE_NOTES.md for the full changelog.
Contributing
Contributions are welcome. Please open an issue or submit a pull request.
License
This project is licensed under the MIT License.