The Plex integration doesn’t update and reflect media that is playing when I use the media_player.play_media
service. Has anyone else experienced this? It just remains in the idle
state
Misread your comment at first. Please make sure you’re on the latest version of HA and provide debug logs for the Plex component as follows:
logger:
logs:
homeassistant.components.plex: debug
Nothing shows up in the logs. Media is playing, but Plex is showing idle
If you’re running in debug then something will show. It’s quite verbose.
Is this an Android TV based Plex client, such as a Shield or Fire TV?
Opps I only checked the UI Logs. In the actual logs themselves, I got the following
2020-06-22 20:42:30 DEBUG (SyncWorker_8) [homeassistant.components.plex.media_player] Attempting to play <Movie:2317:Snatch> on Plex (Plex for Android (TV) - AFTN)
But the movie is never reflected on the plex component, even though the movie is playing.
Also, do you know how Plex handles special character’s ( . , : - etc). Anything with a special character in it always results in an error, even if its the actual name (ex. Wreck-It-Ralph)
Ok, so looks like a Fire TV device. This might be related to an existing Plex client issue on Android devices which don’t reflect activity when started over the API. I assume the active session doesn’t show up on Plex Web activity either?
Correct. So is this a Plex issue or a Hass issue? Also, did you see my prior addition about the special characters?
It’s a Plex-side issue for now.
As for the special characters there’s currently no special handling for those. Perhaps there needs to be. Would you be able to open an issue in the HA Github repo? It’ll go to me.
Sorry, not being snarky here, but where do I log it. Core, Supervised, fronted? I’ve never logged an issue, so I’m not familiar with the procedure (again sorry if that is dumb)
Not dumb at all. It would be core.
@tc23 I’ve tested the media_player.play_media
service with media names that contain a handful of special characters such as “-”, “:”, and “/” without any issues. What is the error you’re running into?
Nevermind, it was user error and I didn’t have the naming convention exactly right. I have made the correction.
But I have another question. When I play media via the API call, it will start the movie, but after 20 minutes, it will just stop playing and the screen goes black. Is this because of that aforementioned API issue?
No, I’m not sure what that would be. Sounds like a different Plex client issue unfortunately.
Sorry to resurrect an old thread, but I’m having this issue with several Plex clients:
- Tizen Samsung TV - session appears when playing from TV, session does not appear when playing via API
- LG WebOS TV - session appears when playing from TV, session does not appear when playing via API
- Apple TV - session appears both when playing from TV and playing via API - everything works correctly, leading me to believe that it’s a client bug on Samsung/LG TVs
When playing through the TV itself (meaning, select media via TV remote control and start playback through the client app) - I see regular session updates arrive over the network, and I see the session on the server. Plex integration sees it too and everything shows up correctly (does not affect Apple TV).
When playing through API (be it via python or through HA Plex integration) - the session never shows up on the server, and session updates don’t get sent; nevertheless, the media is playing on the client.
I opened an issue on Plex forums but that has gone nowhere.
Seeking workarounds, I found that the Plex integration is not interrogating the client at all to find any activity - and instead seems to rely largely on session updates (please correct me if I’m wrong).
In both cases above (Samsung and LG TVs) - I found that I am able to interrogate the client to find active timelines, which accurately represent similar data to that of a session. The main drawback is that it requires polling the Plex client.
Question: Is there any intention of implementing such resiliency mechanisms to overcome issues with the (evidently) neglected Plex clients?
I considered writing a PR for this but the async polling is really getting in the way, and I’m hesitant to learn it.
Example client interrogation would look like this in python:
#!/usr/bin/env python3
from time import sleep
from plexapi.server import PlexServer
def main():
server_url = 'http://<REPLACE_WITH_SERVER_URL>:32400'
token = '<REPLACE_WITH_TOKEN>'
server = PlexServer(baseurl, token)
while server:
for client in server.clients():
if not client.isPlayingMedia():
continue
if not client.timeline:
client.timelines() # this does some magic checks and sets client.timeline if it's missing
if client.timeline:
printTimeline(client.timeline)
sleep(5)
def printTimeline(t):
print(' t.address: %s'%t.address)
print(' t.audioStreamId: %s'%t.audioStreamId)
print(' t.autoPlay: %s'%t.autoPlay)
print(' t.containerKey: %s'%t.containerKey)
print(' t.controllable: %s'%t.controllable)
print(' t.duration: %s'%t.duration)
print(' t.itemType: %s'%t.itemType)
print(' t.key: %s'%t.key)
print(' t.location: %s'%t.location)
print(' t.machineIdentifier: %s'%t.machineIdentifier)
print(' t.partCount: %s'%t.partCount)
print(' t.partIndex: %s'%t.partIndex)
print(' t.playQueueID: %s'%t.playQueueID)
print(' t.playQueueItemID: %s'%t.playQueueItemID)
print(' t.playQueueVersion: %s'%t.playQueueVersion)
print(' t.port: %s'%t.port)
print(' t.protocol: %s'%t.protocol)
print(' t.providerIdentifier: %s'%t.providerIdentifier)
print(' t.ratingKey: %s'%t.ratingKey)
print(' t.repeat: %s'%t.repeat)
print(' t.seekRange: %s'%t.seekRange)
print(' t.shuffle: %s'%t.shuffle)
print(' t.state: %s'%t.state)
print(' t.subtitleColor: %s'%t.subtitleColor)
print(' t.subtitlePosition: %s'%t.subtitlePosition)
print(' t.subtitleSize: %s'%t.subtitleSize)
print(' t.time: %s'%t.time)
print(' t.type: %s'%t.type)
print(' t.volume: %s'%t.volume)
A timeline can equate to a session almost 1-1, the only exception being that a timeline doesn’t have a sessionKey (which seems to be just a session index). It does seem to have its own unique identifier though: timeline.machineIdentifier
, which is an alpha-numeric string, notably different from client.machineIdentifier
.
A timeline can be converted to a session-update-equivalent object as such (code may be buggy but the idea is sound):
def client_timeline_to_session(client, timeline):
if not client or not timeline:
return None
return {
'type': timeline.state,
'size': 1,
'PlaySessionStateNotification': [
{
'sessionKey': timeline.machineIdentifier,
'clientIdentifier': client.machineIdentifier,
'guid': '',
'ratingKey': timeline.ratingKey,
'url': '',
'key': timeline.key,
'viewOffset': int(timeline.time),
'playQueueItemID': timeline.playQueueItemID,
'playQueueID': timeline.playQueueID,
'state': timeline.state
}
]
}
Again the only inconsistency is the sessionKey.
I tried simulating session updates by polling the client from within the Plex integration, and then trying to inject these fake session updates - but had trouble with polling, and with the sessionKey indexing.
Wanted to present these thoughts to someone who may already be skilled enough to consider such a polling mechanism.
@jjlawren sorry to call you out and dumping all this info - just curious if you have any thoughts about it
Just to be clear about the earlier comment - I am convinced that improper session updates are Plex client problems, and not Plex integration problems.
I’d just like to see if the Plex integration can be made more resilient against buggy Plex client implementations.
Yes, it’s been on my list of feature ideas for quite a long time.
Unfortunately there are a few issues here to work around first. Since we don’t know when playback begins (no websocket update from the Plex server) and there are potentially many known idle clients, we’d need to continuously poll all to see which ones may have recently become active. The bigger problem is that the client timeline calls themselves are not always reliable and they’ll sometimes just return an empty payload.
This may be feasible with some work and testing many different client types, but there are quite a few edge cases and optimization issues to deal with along the way.
There is a way to subscribe to updates from individual clients, but the library doesn’t yet support it. Maybe that’s the best path forward.
Concerning knowing when playback begins - I think it would be fair to consider anything that’s invoked through the home assistant integration as a prompt to consider polling. This constraint doesn’t sound unreasonable to me.
In other words, what would you think about the following set of conditions:
- If HA begins playback on Plex client (or HA just started) - add the client to a list of polling candidates.
The list of polling candidates is a list of clients which get polled for timeline data at regular intervals.
-
If a session exists with machineIdentifier matching client’s machineIdentifier - demote client from list of polling candidates (polling is not necessary since client already reports session data).
-
If no meaningful timeline results are fetched for X amount of time - demote client from list of polling candidates (it either isn’t playing or is not responding).
Truthfully I’m a bit frustrated with Plex clients, and also don’t want to push for any over-engineering in the HA integration side - but I would really love to find some way to influence a solution on a more tangible timeline
Curious to hear your thoughts.
I ran a few tests over the weekend and have some POC code that subscribes to timeline callbacks directly from the clients so the data is delivered on a push basis. I do not know if this will end up working for all clients, but it seems to work on my Shield.
It will take some time to get something good enough to put into the plexapi
library and then make the HA-side adjustments, but it at least looks possible now.
Once the library part is done, would you be interested in testing your clients and see if they provide the subscription callback data we need?