Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Sync playback offset #47

Closed
JChris246 opened this issue Mar 8, 2023 · 16 comments · Fixed by #173
Closed

[Feature Request] Sync playback offset #47

JChris246 opened this issue Mar 8, 2023 · 16 comments · Fixed by #173

Comments

@JChris246
Copy link
Contributor

It would be nice to also, in addition to syncing whether an item has been watched, have the playback state of an item synced. For example, if I start a movie in plex and complete an hour (1:00:00) out of the hour and forty five mins (1:45:00) total duration, that state could be sync to jellyfin and I can resume the movie there.

It may not be possible to mutate the viewOffset plex uses to keep track of watch position for an item, due to the closed source nature of plex. A workaround could be to use a PlexClient to seekTo the position. Similarly for jellyfin, using the Playstate endpoints could be helpful.

@luigi311
Copy link
Owner

luigi311 commented Mar 9, 2023

This would be a great feature. We would need to extend the dictionaries that hold the watch status to include the watch time and we would need to change the search functions from only unwatched=False so it would have to do a full library search since i dont think partial watches remove the unwatched tag. We can definitely take a look at this after we close up the other two tickets and create a release since im expecting it this to be pretty stable at that point.

@luigi311
Copy link
Owner

luigi311 commented Mar 23, 2023

I started working on this and have the gathering mostly completed so it will fetch watched and in progress movies/shows for plex and jellyfin without any issues and storing it in a way that i think makes sense. I still need to adjust the comparison functions so it will keep the most watched entry instead of keeping them both. Also need to research on how to actually change it on the accounts, for jellyfin i found this ticket but it says it doesnt work jellyfin/jellyfin#7259 for plex we might need to go with your option of starting a client and seeking to it.

@JChris246
Copy link
Contributor Author

I also stumbled on the that issue while doing some research on it, it seems hitting the /Users/{userId}/PlayingItems/{itemId}?positionTicks={positionTicks} works fine to mark progress on an item for a given user (I tested it). It is a DELETE endpoint. Reference: Jellyfin API - OnPlaybackStopped

As for plex, I found that either the timeline or progress endpoints should work, however I'm not sure that they are user specific and would obviously require that you hit them directly instead of by the plex api package you have😅🤷‍♂️.

Timeline endpoint:

GET - http://{plex-host}/:/timeline?ratingKey={ratingKey}&key={key}&state=stopped&time={time-in-milliseconds}&duration={duration-in-milliseconds}&X-Plex-Client-Identifier={plex-client-id}

where:

  • ratingKey - is the video rating key e.g. 58792
  • key - is the video key path e.g. /library/metadata/58792
  • time-in-milliseconds - is the amount of time played on the item so far that you want to mark
  • duration-in-milliseconds - is the total duration of the item
  • plex-client-id - just a unique id to have plex identify you

Progress endpoint:

PUT - http://{plex-host}/:/progress?key={key}&identifier=com.plexapp.plugins.library&time={time-in-milliseconds}&state=stopped&X-Plex-Token={plex-token}

where:

  • key - is the video ratingKey key e.g. 58792
  • time-in-milliseconds - is the amount of time played on the item so far that you want to mark
  • plex-token - plex token

Plex progress endpoint

@luigi311
Copy link
Owner

Great finds!

I am playing around with the jellyfin api using your query and it doesnt seem to be doing anything on my end.

Ive never used a delete query so i went ahead and created what i would assume would be a correct delete call and added in a if response status of 204 return None since there is nothing to return. It seems to execute successfully and does seem to be doing something because i did a post /Users/{userId}/PlayingItems/{itemId}/Progress?positionTicks={positionTicks} and when i looked in the dashboard there was a session playing with the user in question with the correct media file and at the correct timestamp. I then executing the delete /Users/{userId}/PlayingItems/{itemId}?positionTicks={positionTicks} it did in fact terminate the session but when i check the users resume media it still has the old progress on it and another media file didnt have progress on it.

Maybe there is something im missing, can you take a look at my test branch https://github.com/luigi311/JellyPlex-Watched/tree/partial_watch_test you should be able to just start something on plex and set it to say 15 mins and then run that branch and it should attempt to sync the 15 min playtime to jellyfin.

As for plex since it does look like there is some APIs we can use i wonder if it would be better to just submit a feature request to the plex api package i am using to add in a method such as SeekTo(timestamp) or something similar to the markWatched() function I am using currently and inform them of the api endpoints they can use that way we can keep it consistent and use the python package api for everything plex related and not bring in http requests there too.

@JChris246
Copy link
Contributor Author

My bad, it seems I forgot that I had set an extra header value in my http client from a previous request when making the /Users/{userId}/PlayingItems/{itemId}?positionTicks={positionTicks} 😅 and that's probably why it wasn't working on your side.

Basically I had the X-Emby-Authorization header set similar to your code with an additional param; Token=. I am actually not sure how to obtain the value I used there programmatically, as I got it manually from looking at the network requests made when running jellyfin in the browser.

Yes, should definitely submit a feature request to the plex api package repo for consistency👍

@luigi311
Copy link
Owner

Looks like your right. I pulled the token that is generated from the web client for jellyfin when im logged into the account and that makes the query work instantly. Going to need to figure out how to get that token. Ill see if i can find anything in the other jellyfin clients.

@luigi311
Copy link
Owner

Looks like the plex api already had what we wanted lol. I went ahead and implemented it now in the partial_watch branch and it seems to be syncing partial progress for episodes and movies now.

Still need to see what we can do on the jellyfin side since it looks like that Token is a user access token which makes sense and i cant seem to find a way to generate that token for users without having to use the authenticate endpoints that require a username/user_id and a password unlike in the plex api where you can get a token for other users via the api_key/server host token. I asked the question in the jellyfin discord if there is a way to generate that token for other users via the api_key or if there is another way to update the watch status via a api_key only.

@luigi311
Copy link
Owner

Can't seem to find anything for being able to do this on the jellyfin side without using a users token and there doesn't seem to be a way to grab a users token via an api key. I think I'm going to put this on hold for now and release what I have so far on the Plex side so people can at least use that.

@luigi311
Copy link
Owner

I opened up a bug ticket on the jellyfin repo about not being able to update the position tick via an api_key so we will see if anything happens with that. Might need to just do a release with just the plex partial sync implemented for now until something comes up for this for jellyfin and/or emby. I added a feature list that shows what features are implemented in which servers

jellyfin/jellyfin#9614

@Inrego
Copy link

Inrego commented May 4, 2023

If necessary, I could probably make a plugin for Jellyfin that will allow it. With that said, my knowledge about Jellyfin plugins is quite limited, so I might be wrong. I'm basing this off my experience of making a plugin for Emby 5 years ago. But if it's still somewhat similar, I guess it should be doable.

@luigi311
Copy link
Owner

luigi311 commented May 4, 2023

I would ideally like to not require an external plugin for this to work but im not sure how long we would have to wait for the jellyfin ticket to be answered so we might not have a choice.

If we do go down the plugin method we would hopefully be able to do a check to see if the plugin exists so it will only enable the partial sync feature for jellyfin servers and if not it will skip that entire section so people can run it without worrying about that.

@Inrego
Copy link

Inrego commented May 4, 2023

I totally understand that.

And yes, that would of course be doable.

@arabcoders
Copy link

@luigi311 my PR to jellyfin to support updating userData via apikey has been merged jellyfin/jellyfin#10573

It will be available in 10.9.x version you should be able to target it i have a code in watchstate ready to go if you want to take look

@luigi311
Copy link
Owner

luigi311 commented Jan 3, 2024

Thank you so much for doing that, its so good to know that it wasnt something we were missing and instead was a jellyfin api limitation. Ill go ahead and see if i can get that implemented that way its ready for when 10.9.0+ releases

@arabcoders
Copy link

arabcoders commented Jan 3, 2024

No worries, be aware that jellyfin PlaybackPositionTicks Uses higher precision value then plex milliseconds, so from jellyfin to plex it's (jellyfin.PlaybackPositionTicks/ 10_000) from plex to jellyfin (plex.offset * 10_000) roughly

@luigi311
Copy link
Owner

luigi311 commented Jun 3, 2024

This has finally been completely implemented for both jellyfin and emby! Thank you @arabcoders for bringing in the API for it in jellyfin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants