alexei.dolgolyov 6ae0ed1787
Release / release (push) Successful in 2s
chore: release v0.2.0
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.
2026-05-26 13:16:36 +03:00
2026-05-26 13:16:36 +03:00
2026-05-26 13:16:36 +03:00
2026-05-26 13:16:36 +03:00
2026-05-26 13:16:36 +03:00

Emby Media Player

hacs_badge version Home Assistant

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 / replacePlayNow, nextPlayNext, addPlayLast.

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

  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 (560 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 (10060000 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_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.

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/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 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.

S
Description
Home Assistant custom integration (HACS) that exposes Emby sessions as media_player entities with full playback control, now-playing metadata, and artwork.
Readme 100 KiB
0.2.0 Latest
2026-05-26 13:16:36 +03:00
Languages
Python 100%