# Emby Media Player [![hacs_badge](https://img.shields.io/badge/HACS-Custom-orange.svg)](https://github.com/hacs/integration) [![version](https://img.shields.io/badge/version-0.2.0-blue.svg)](RELEASE_NOTES.md) [![Home Assistant](https://img.shields.io/badge/Home%20Assistant-2024.10%2B-blue.svg)](https://www.home-assistant.io/) 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`, and `PlaybackStopped` events 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_ssl` toggle. - **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) 1. Open HACS in Home Assistant. 2. Click on **Integrations**. 3. Click the three-dots menu and select **Custom repositories**. 4. Add this repository URL and select **Integration** as the category. 5. Click **Install**. 6. Restart Home Assistant. ### Manual Installation 1. Download the `custom_components/emby_player` folder. 2. Copy it to your Home Assistant `custom_components` directory. 3. Restart Home Assistant. ## Configuration 1. Go to **Settings → Devices & Services**. 2. Click **Add Integration** and search for **Emby Media Player**. 3. Enter your Emby server details: - **Host** — Emby server hostname or IP address. - **Port** — default `8096` (HTTP) or `8920` (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. 4. Select the Emby user account to use for browsing & playback. 5. Click **Submit**. ### Getting an API key 1. Open your Emby Server Dashboard. 2. Navigate to **Extended → API Keys**. 3. Click **New API Key** (+ button). 4. Give it a name (e.g., `Home Assistant`). 5. 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). | ```yaml 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`. | ```yaml 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_set` will 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. ```yaml 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 ```yaml 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 ```yaml 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 ```yaml 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://:8096/emby/System/Info` from 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` / `8920` from the HA host. - If you run Emby behind a reverse proxy, make sure `Upgrade` / `Connection` headers 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](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.