Intégration externe - Plex

Salut tout le monde ! :waving_hand:

Je vous partage une nouvelle intégration externe que je viens de publier : Plex, pour connecter votre serveur Plex à Gladys. Si comme moi vous avez un NAS qui tourne avec Plex et que vous rêviez de brancher vos lectures sur vos automatisations, c’est fait :slightly_smiling_face:

Ce que ça fait

Un appareil « serveur » avec des capteurs de supervision :

  • :bar_chart: nombre de flux actifs et de sessions en transcodage
  • :satellite_antenna: bande passante de streaming (kbps)
  • :television: un texte « en cours de lecture » qui résume qui regarde quoi
  • :card_index_dividers: un compteur par bibliothèque : films, séries (+ épisodes), musique (+ pistes) — désactivable si vous n’en voulez pas

Un appareil par lecteur Plex (app TV, téléphone, etc.) :

  • :play_button: les commandes : lecture, pause, stop, précédent, suivant, avance/retour rapide, volume, sourdine
  • :musical_note: l’état de lecture, compatible avec le widget Musique du tableau de bord
  • :label: le titre en cours (Série S01E02 - Épisode, Artiste - Titre, Film (année)) et le temps restant
  • :sparkles: mes préférés : deux capteurs binaires « dans l’intro » et « dans le générique de fin », basés sur les marqueurs détectés par Plex !

Ce dernier point ouvre des scénarios sympas :

Quand le générique démarre dans le salon → rallumer les lumières :light_bulb:
Quand une lecture démarre après 22 h → tamiser à 20 %
Un bouton « pause générale » à l’heure du repas :spaghetti:

Les états se mettent à jour en quelques secondes : l’intégration écoute le flux temps réel du serveur Plex (WebSocket), avec un polling de secours configurable. Les lecteurs sont découverts automatiquement — y compris à la volée dès qu’un appareil lance une lecture.

Installation

  1. Dans Gladys : Intégrations → catégorie Multimédia → Plex (le temps que l’indexeur du store passe, vous pouvez aussi installer via l’URL du dépôt)
  2. Renseignez l’URL de votre serveur (http://ip-du-nas:32400) et votre X-Plex-Token (comment le trouver)
  3. Bouton « Tester la connexion », puis onglet Découverte → ajoutez vos appareils, c’est tout :white_check_mark:

Petit détail qui a son importance : pour contrôler un téléphone/une tablette, pensez à activer « S’annoncer comme lecteur » dans l’app Plex concernée. Sans ça, seul le bouton Stop fonctionne (il coupe la session côté serveur).

Sous le capot

C’est une v1.0.0 : testée chez moi (NAS + SHIELD + mobiles), mais je compte sur vous pour la pousser dans ses retranchements :grinning_face_with_smiling_eyes: Les retours, idées et PR sont les bienvenus — dites-moi ce qui vous manque (lancement d’un média précis ? capteurs supplémentaires ?).

Bonne lecture… de films ! :popcorn:

Salut !

Merci pour cette intégration ! Tu as été plus rapide que moi pour la release, j’avais une version en test mais je n’en étais pas encore satisfait :zany_face:

J’ai bien un retour d’info mais je n’arrive pas à contrôler la musique de plexamp sur l’iPad (rien du tout). Rien d’explicite dans les logs :

[2026-08-16T05:26:02.094Z] [INFO] onConfigUpdated -> new configuration received
[2026-08-16T05:26:02.103Z] [INFO] [plex-monitor] Connected to Plex server "gladys" (v1.43.3.10861-07dfddaeb)
[2026-08-16T05:26:02.411Z] [INFO] [plex-notifications] Connected to the Plex notification socket
[2026-08-16T05:26:04.920Z] [INFO] [plex-monitor] Connected to Plex server "gladys" (v1.43.3.10861-07dfddaeb)
[2026-08-16T05:26:18.383Z] [INFO] onDeviceCreated <- ext:ext-guim31-gladys-plex:server:2b588884a92967f7f95cb7f55784f2dd5468ac73
[2026-08-16T05:32:58.442Z] [INFO] [plex-monitor] New Plex player discovered: iPad
[2026-08-16T05:33:54.106Z] [INFO] onScanRequest -> publishing 2 devices
[2026-08-16T05:33:57.652Z] [INFO] onDeviceCreated <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd
[2026-08-16T05:35:44.327Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:pause = 1
[2026-08-16T05:36:05.254Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:play = 1
[2026-08-16T05:36:06.530Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:previous = 1
[2026-08-16T05:36:21.819Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:next = 1
[2026-08-16T05:36:36.768Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:stop = 1
[2026-08-16T05:36:47.420Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:forward = 1
[2026-08-16T05:36:50.634Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:mute = 1
[2026-08-16T05:36:52.369Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:b8474c9e-6b33-454e-8594-14ba25f9babd:rewind = 1

Je veux bien que tu demandes à ton ‹ nouvel ami › d’ajouter l’utilisation des webhooks (j’ai un Plex pass et GladysPlus) car ça permet de ne pas attendre le poll de 10s.

Édit : j’utilise Plexamp pour la musique. Peut-être que le suivi vient de là ?

Je ne la voit pas sur le store malheureusement :man_shrugging:
Mais j’attends son intégration

Ah ben mince ! On a pas bien communiqué… :sweat_smile:
Peut être que ta version serait plus aboutie ?

Je vais regarder côté plexamp, je suis bête je l’ai sur mon téléphone mais j’ai oublié de le tester car je ne l’utilise plus !

Je fais ton retour à mon ouvrier et je te dis ça :+1:

Oups je ne l’avais pas indexé ! C’est fait, ça apparaîtra max dans 1h

A mon tour d’être content :slight_smile:

C’est une intégration que j’attendais :slight_smile:

J’ai actuellement un soucis avec plex client chrome (pas encore test la TV) :

je ne sais pas pk j’ai pas de valeur récente à la place de push button.

Les push button ne réagisse pas a l’exception du stop le volume pareil ne semble pas agir non plus :slight_smile:

Et on ne juge pas le media c’est pour ma fille :eyes: :stuck_out_tongue:

log :

[2026-08-16T10:04:00.117Z] [INFO] Starting the Plex integration...
[2026-08-16T10:04:00.307Z] [INFO] [gladys-sdk] connected to Gladys (http://172.30.0.1:8455)
[2026-08-16T10:04:00.322Z] [INFO] Waiting for the Plex configuration (URL + token)
[2026-08-16T10:10:22.832Z] [INFO] onConfigUpdated -> new configuration received
[2026-08-16T10:10:22.832Z] [INFO] Waiting for the Plex configuration (URL + token)
[2026-08-16T10:11:13.870Z] [INFO] onConfigUpdated -> new configuration received
[2026-08-16T10:11:13.907Z] [INFO] [plex-monitor] Connected to Plex server "DiskStation" (v1.43.2.10687-563d026ea)
[2026-08-16T10:11:14.437Z] [INFO] [plex-notifications] Connected to the Plex notification socket
[2026-08-16T10:11:20.384Z] [INFO] onConfigUpdated -> new configuration received
[2026-08-16T10:11:20.391Z] [INFO] [plex-monitor] Connected to Plex server "DiskStation" (v1.43.2.10687-563d026ea)
[2026-08-16T10:11:20.566Z] [INFO] [plex-notifications] Connected to the Plex notification socket
[2026-08-16T10:11:21.853Z] [INFO] [plex-monitor] Connected to Plex server "DiskStation" (v1.43.2.10687-563d026ea)
[2026-08-16T10:11:41.734Z] [INFO] onDeviceCreated <- ext:ext-guim31-gladys-plex:server:a8058595a4bb5a3537614ec74ebdf3c644e8d14e
[2026-08-16T11:39:01.060Z] [INFO] [plex-monitor] New Plex player discovered: Chrome
[2026-08-16T11:40:14.880Z] [INFO] onDeviceCreated <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo
[2026-08-16T11:41:30.401Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:volume = 22
[2026-08-16T11:41:31.140Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:volume = 11
[2026-08-16T11:41:41.139Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:volume = 0
[2026-08-16T11:41:42.369Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:volume = 7
[2026-08-16T11:41:43.282Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:volume = 0
[2026-08-16T11:41:54.712Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:mute = 1
[2026-08-16T11:41:57.426Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:mute = 1
[2026-08-16T11:42:11.046Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:stop = 1
[2026-08-16T11:42:11.066Z] [INFO] [plex-monitor] Session of ed9ht57db2wn25la3vfyjnpo terminated server-side (stop fallback)
[2026-08-16T11:42:33.547Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:ed9ht57db2wn25la3vfyjnpo:mute = 1

ps : Testé sur android via l’application même soucis :frowning:

Merci à vous deux pour les retours ultra détaillés, et surtout pour les logs :folded_hands: Ils ont permis de trouver le coupable en deux minutes. La v1.0.1 est dispo, elle corrige tout ça.

Ce qui clochait

Pour savoir si un lecteur est pilotable, je me fiais à l’endpoint /clients du serveur. Erreur de débutant : c’est l’ancien mécanisme de découverte (GDM), et il est vide sur la plupart des serveurs modernes — les applis Plex ne s’y annoncent plus. Résultat : Plexamp sur iPad, Plex Web sur Chrome et compagnie étaient rejetés avant même qu’une commande soit tentée. D’où « aucun bouton ne réagit ».

Et si Stop marchait, c’est un hasard heureux : c’était le seul à avoir un plan B (couper la session côté serveur), qui lui fonctionne toujours :sweat_smile:

Ce qui change en 1.0.1

  • :video_game: Les commandes sont maintenant réellement envoyées, et c’est la réponse du serveur qui tranche. Si Plex refuse, vous avez une erreur explicite dans Gladys au lieu d’un bouton mort — et Stop garde son plan B.
  • :muted_speaker: Le bouton Muet fonctionne enfin en bascule. Gladys l’affiche en bouton poussoir (il envoie toujours « 1 »), donc mon code ne savait que couper le son, jamais le remettre. @spenceur ça explique tes mute = 1 en boucle dans les logs !
  • :repeat_button: Plus de double initialisation. Vos deux logs montraient « Connected to Plex server » deux fois : enregistrer la config pendant que la connexion démarrait lançait une deuxième boucle de polling et un deuxième WebSocket. Corrigé.
  • :clipboard: Les logs indiquent maintenant le résultat de chaque commande, et préviennent quand un lecteur n’annonce pas la capacité playback.

@GBoulvin — pour les webhooks : bonne nouvelle, pas besoin de Plex Pass ici ! L’intégration écoute déjà le WebSocket temps réel du serveur (/:/websockets/notifications), donc les changements play/pause/stop remontent en moins d’une seconde. Le polling de 10 s n’est qu’un filet de sécurité si le socket tombe. Si tu vois quand même de la latence sur Plexamp, redis-le moi avec un log en LOG_LEVEL=debug, ça m’intéresse. Et curieux de savoir si le contrôle de Plexamp répond en 1.0.1 :crossed_fingers:

@spenceur — dis-moi si tes boutons répondent maintenant. Si Plex refuse toujours certaines commandes, l’erreur affichée dans Gladys me dira exactement quoi creuser. Et si tu peux préciser ce qui s’affichait « à la place du push button », je regarde .

Pas de changement pour moi :slight_smile:

[2026-08-16T14:13:24.558Z] [INFO] Starting the Plex integration...
[2026-08-16T14:13:24.870Z] [INFO] [gladys-sdk] connected to Gladys (http://172.30.0.1:8455)
[2026-08-16T14:13:24.898Z] [INFO] [plex-monitor] Connected to Plex server "DiskStation" (v1.43.2.10687-563d026ea)
[2026-08-16T14:13:25.353Z] [INFO] [plex-notifications] Connected to the Plex notification socket
[2026-08-16T16:27:40.274Z] [INFO] [plex-monitor] New Plex player discovered: S26 Ultra de 
[2026-08-16T16:27:59.153Z] [INFO] onDeviceCreated <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b
[2026-08-16T16:30:35.319Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:mute = 1
[2026-08-16T16:30:35.320Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:30:42.329Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:volume = 21
[2026-08-16T16:30:42.329Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:30:45.383Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:volume = 76
[2026-08-16T16:30:45.383Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:30:50.571Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:volume = 37
[2026-08-16T16:30:50.571Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:30:51.264Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:volume = 5
[2026-08-16T16:30:51.264Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:30:57.906Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:rewind = 1
[2026-08-16T16:30:57.907Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:31:00.900Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:forward = 1
[2026-08-16T16:31:00.900Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:31:04.059Z] [INFO] onSetValue <- ext:ext-guim31-gladys-plex:player:cxus6yubstmxb3mw0sr8if7b:stop = 1
[2026-08-16T16:31:04.060Z] [WARN] [plex-monitor] Player cxus6yubstmxb3mw0sr8if7b does not advertise the "playback" capability; trying anyway (enable "Advertise as player" in its Plex app if nothing happens)
[2026-08-16T16:31:04.100Z] [INFO] [plex-monitor] Session of cxus6yubstmxb3mw0sr8if7b terminated server-side (stop fallback)

Si je comprend bien il faut jactive l’option mais sur mon app l’option nest plus présente
https://www.reddit.com/r/PleX/s/cr6JZf9XlE

Plex v1.0.3 — merci pour les logs, ça a beaucoup bougé :rocket:

Salut à tous :waving_hand:

Grosse session de corrections depuis la sortie de l’intégration Plex, presque entièrement grâce à @GBoulvin et @spenceur qui m’ont envoyé des logs en or :folded_hands: On est passés de la 1.0.0 à la 1.0.3. Petit récap’ de ce qui a changé.

Le gros morceau : le contrôle des lecteurs

Le symptôme que vous aviez tous les deux : aucun bouton ne réagissait, sauf Stop.

Deux erreurs empilées de mon côté :

  1. Pour savoir si un lecteur était pilotable, je me fiais à l’endpoint /clients du serveur Plex. C’est l’ancien mécanisme de découverte (GDM), et il est vide sur la plupart des serveurs modernes. Résultat : Plexamp, Plex Web et les applis mobiles étaient recalés avant même qu’une commande parte.
  2. Une fois ce blocage retiré, les commandes partaient enfin… mais le serveur Plex refusait lui-même de les relayer vers ces lecteurs. C’est un log de @spenceur qui l’a prouvé : 41 ms entre la commande et le repli de Stop, donc échec immédiat. Je frappais toujours à la seule porte fermée :person_facepalming:

Ce que fait la 1.0.3 : l’intégration essaie maintenant deux chemins avant d’abandonner — via le serveur (ce qui marche pour les applis TV, box et consoles), puis directement vers le lecteur sur son adresse locale, le chemin qu’utilise Plex quand vous « castez ». Le chemin qui répond est mémorisé, donc les commandes suivantes partent au bon endroit du premier coup.

Les autres corrections

  • :muted_speaker: Le bouton Muet fonctionne enfin en bascule. Gladys l’affiche en bouton poussoir (qui envoie toujours « 1 ») : mon code ne savait que couper le son, jamais le remettre.
  • :bar_chart: Les capteurs se remplissent dès l’ajout d’un appareil. Avant, les valeurs publiées avant le clic sur « Ajouter à Gladys » étaient perdues, et ma déduplication ne les renvoyait jamais. D’où les « Pas de valeur récente » persistants.
  • :repeat_button: Plus de double initialisation. Enregistrer la config pendant que la connexion démarrait lançait une deuxième boucle de polling et un deuxième WebSocket (visible dans vos logs avec le « Connected to Plex server » en double).
  • :stethoscope: Les logs sont beaucoup plus bavards en cas d’échec : ils listent l’erreur de chaque chemin tenté.

Un mot sur la méthode :robot:

Pour ceux que ça intéresse : l’intégration a été écrite avec Claude Opus 5, puis j’ai fait repasser Claude Fable 5 sur tout le code en lui donnant vos retours comme contexte. Et honnêtement, ça valait le coup — il a trouvé quatre trucs que la première passe avait laissés filer :

  • la route directe utilisait le port par défaut (32500) alors que /clients fournit le port exact du lecteur, et que les applis TV écoutent souvent sur 3005 ;
  • pour un stream regardé hors du domicile, on tentait de joindre une adresse publique — requête inutile et 2 secondes perdues sur le budget de la commande ;
  • dans le pire cas, la chaîne « essai serveur → essai direct → repli Stop » pouvait dépasser les 5 secondes que Gladys accorde à l’acquittement d’une commande : le Stop marchait mais s’affichait en échec ;
  • la route mémorisée n’était jamais oubliée en cas d’échec.

Deux IA, deux angles de vue, et un code plus solide. Le tout couvert par 53 tests unitaires maintenant :grinning_face_with_smiling_eyes:

:warning: La limite qu’on ne peut pas contourner

Soyons honnêtes : une appli Plex n’accepte le contrôle à distance que si elle s’annonce comme lecteur. Sans ce réglage, elle n’écoute littéralement aucune commande — même l’appli Plex officielle ne peut pas la piloter.

  • :white_check_mark: TV / box / console : activé par défaut, tout marche.
  • :warning: Mobile, Plexamp, Plex Web : à activer à la main, généralement dans Réglages → Contrôle à distance → « S’annoncer comme lecteur ».

Les capteurs (titre en cours, état de lecture, temps restant, intro/générique), eux, fonctionnent sur tous les lecteurs quoi qu’il arrive.

Et maintenant ?

Gladys devrait vous proposer la 1.0.3 directement. Si le contrôle résiste encore chez vous, envoyez-moi la ligne Command ... failed on every route -> ... de vos logs : elle me dira exactement où ça coince (refus du serveur, lecteur injoignable, port fermé…).

Merci encore, continuez de casser mon intégration, ça la rend meilleure :popcorn:

:backhand_index_pointing_right: GitHub - guim31/gladys-plex · GitHub

Je m’en occupe demain sur ma tv pour check :slight_smile:
Beau travail

Moi j’ai plus ou moins rien fait hein ^^ :wink: