z411 / trackma

Open multi-site list manager for Unix-like systems. (ex-wMAL)
https://z411.github.io/trackma
GNU General Public License v3.0
779 stars 81 forks source link

Timer still counts down even if paused + MPRIS #402

Closed Soitora closed 5 years ago

Soitora commented 5 years ago

I started an episode earlier but two minutes in I had to go brb so I paused and didn't resume watching for several hours, yet it proceeded to update the episode as watched even though it had recognized (using tracker command) that it was paused.

z411 commented 5 years ago

Hi, that's expected behavior. There's no way for Trackma to know if the video is paused or not since it works by checking if a file is open. The way to actually implement this would be to, for example, write an MPRIS tracker, but your player would need to support that as well.

Soitora commented 5 years ago

Hey this was an oversight on my part, I thought I remembered the tracker command showing my Plex tracking as paused when I paused but after re-checking it did not, maybe something that could be thrown in for the Plex users as it's very easy grabbing playing status?

Meybe you, @Hairo, could look into it if you ever got the spare time ? :)

z411 commented 5 years ago

I was actually thinking of throwing together an MPRIS tracker so I will eventually have to develop a pausing mechanism for the timer that could be used by the Plex tracker as well, yes.

Hairo commented 5 years ago

While getting the playing state from a plex session would be trivial, i'm not sure how the tracker/timer would handle that.

EDIT: oh, wrote this before z411 reply.

z411 commented 5 years ago

Just implemented a MPRIS tracker, and with that, a pause mechanism that can be used by any tracker. It works with MPRIS as I tested it, and @Hairo you should be able to use it too from the Plex tracker. Just call self.pause_timer() and self.resume_timer() respectively.

@Soitora Likewise, if your media player supports MPRIS you can try the MPRIS tracker now (you can choose it in the Qt settings dialog or setting tracker_type to mpris in the config file) and it should do what you want.

Soitora commented 5 years ago

Awesome! :smile: I'll try it out when available

FichteFoll commented 5 years ago

With the mpris tracker, couldn't you also check for a % completion threshold of the played file using its metadata? That sounds like a more solid approach for shows of different length and I believe is also the preferred practice for scrobbling music (to lastfm, for example). Should I open a separate issue for that?

z411 commented 5 years ago

As in using the playing position and total length or just the length?

Soitora commented 5 years ago

I think @FichteFoll means that if the show is 25 minutes long and you have it set to mark as complete at 80% then the program waits until it reaches 20 minutes and then marks as watched. This could be a replacement or an alternative to the timer and would technically be more accurate.

This is also how Tautulli (former PlexPy) does it, after a client has watched the show for 80% or more then it gets marked as seen.

z411 commented 5 years ago

Yes, but I see two ways to do this:

  1. Timer: Calculate the 80% (20 minutes) and then countdown, independently of what the user does. You are forced to watch at least 20 minutes of the media for it to update.
  2. Playing position: Update when the player reaches 80% of the video. This would mean that it would update if you seek the video to the end.

IIRC Last.fm does 1, and Trackma's Plex tracker too. Is it the same for Tautulli as well?

Hairo commented 5 years ago

Yeah, 80% is the ideal time for anime since you can skip the OP/ED and still get it marked as complete.

FichteFoll commented 5 years ago

The timer method is safer, yes. Depending on how long OP/ED are respectively, a lower threshold of 60-70% might be more appropriate, but that should be configurable regardless.

Soitora commented 5 years ago

You could even combine a timer and playing position (e.g. 20% video duration as timer then update if it manages to reach 80% to ensure it wasn't skipped through just to find a scene) but that would maybe be too complex.

EDIT: Or as written below with the Tautulli method, which is pretty similiar.

A big worry of mine right now, (haven't actually tried) is that with the current timer method is if the timer is 1000 seconds and the show 1250 seconds, what if I skip let's say, 300 seconds in total (long opening, flashbacks, long ending), that would bring the total possible watch time to 950 seconds, which is lower than the timer.

Checking Tautulli settings I'm pretty sure it works by following this pattern:

If: User has played the media for ≥120 seconds Then: Log to history.

If: User has played the media for ≥120 seconds and reached ≥85% on the playback position Then: Log to history & mark as watched.

If: User has played the media for <120 seconds Then: Ignore.

If: User has played the media for <120 seconds but reached ≥85% on the playback position Then: Ignore.

This feels true especially considering this image below, the episode was 25 minutes but my friend likes to skip through (ughh), the media was played for more than 120 seconds and he reached more than 85% on the playback position even though he technically only watched about ~50% of the episode. If it didn't track this way then he would never have his entries logged as a successful watch.

image

An example here too but of when my friend only reached 9 minutes in on the playback position (and total watched), which is not enough to trigger the 85% watch but enough to log it to history.

image

image

FichteFoll commented 5 years ago

Regarding the initial issue, playing/paused tracking doesn't actually seem to work when media is loaded as the tracker assumes "Playing" status when the player isn't actually playing back at the start. It's also kinda getting confused by multiple mpris servers (e.g. mpd) where any instance loaded later overrides the previous despite getting ignored due to not being a show on the list.

For the following, I have mpv running with the next episode of a show but with playback paused before starting trackma. Then I reload the file in mpv to trigger a change in the mpris protocol and then I start and stop playback once.

Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv
[D] Tracker (MPRIS): New video: [PAS] Carole & Tuesday - 03 (WEB 720p AAC) [958B95F8].mkv
Tracker (MPRIS): Will update Carole & Tuesday 3
Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpd
[D] Tracker (MPRIS): New video: 剣の刻む記憶
Tracker (MPRIS) warning: Found player but show not in list.
FichteFoll [anilist] (anime) watching >> tracker
- Tracker status -
State: Not found
Filename: 剣の刻む記憶
Timer: N/A [P]
Show: N/A
[D] Tracker (MPRIS): New video: [PAS] Carole & Tuesday - 03 (WEB 720p AAC) [958B95F8].mkv
Tracker (MPRIS): Will update Carole & Tuesday 3
FichteFoll [anilist] (anime) watching >> tracker
- Tracker status -
State: Playing
Filename: [PAS] Carole & Tuesday - 03 (WEB 720p AAC) [958B95F8].mkv
Timer: N/A [P]
Show: Carole & Tuesday
Episode: 3
[D] Tracker (MPRIS): New playback status: Playing
[D] Tracker (MPRIS): New playback status: Paused
z411 commented 5 years ago

Regarding the initial issue, playing/paused tracking doesn't actually seem to work when media is loaded as the tracker assumes "Playing" status when the player isn't actually playing back at the start.

That's weird since it's checking for the paused state at start

https://github.com/z411/trackma/blob/4fab93185a49cb6053ff667ba742ca534fa9691e/trackma/tracker/mpris.py#L43-L44

Maybe a status != "Playing" check would be better.

It's also kinda getting confused by multiple mpris servers (e.g. mpd) where any instance loaded later overrides the previous despite getting ignored due to not being a show on the list.

My idea to fix this would be to ignore what any other player is doing when a player is playing something. For example if I have mpv, mpd and VLC running, while I have a video running in mpv, only focus on what mpv is doing and ignore anything mpd and VLC do until mpv closes the video. What do you think?

Another option would be to use the tracker_process to make sure it's one of the players we use, like inotify does. (inotify ignores players if it doesn't match the regex)

FichteFoll commented 5 years ago

The paused thing irritated me as well since I did a check on an obvious bug in the source but couldn't spot anything.

So, the problem with multiple instances is that, technically, you could be playing multiple episodes at the same time, although you most likely aren't. Still, the easiest way to mirror this possibility and simultaneously resolve all the issues discussed would be to have a timer for each player recognized. At least from an internal standpoint. Idk how much the existing status reporting etc would need to be updated to accomodate for this. It's probably only relevant for mpris, too, due to the paused and playing states.

z411 commented 5 years ago

Doing that would require a few big internal changes in both trackers and UIs, which in turn we risk introducing some bugs and I don't think it's worth it since you don't really watch more than one episode at a time. I think it's better to wait for an episode to be finished or closed before attempting to react to anything else.

z411 commented 5 years ago

Some changes were made:

  1. MPRIS now only reacts to players in the tracker_process regex.
  2. MPRIS won't react to any other player if a player is playing a file.
  3. MPRIS will pause the timer if the status is anything other than Playing.

Let's see how it behaves; I tested it and it seems to work fine.

FichteFoll commented 5 years ago

Confirmed working as intended. I also just realized my mistake earlier in that I assumed State: Playing meant the video is playing, but it just means the player has a media file open and instead the timer is paused ([P]). Might be a bit misleading there, but at least everything works. The mpris tracker not getting distracted by other players playing completely irrelevant files (e.g. music via mpd) is a nice cleanup in that regard. (Also handling the "Stopped" state.)

Do we want to keep this issue open for the "played for % threshold of entire file lenght" or should we move that to a different issue?

FichteFoll commented 5 years ago

Something still isn't right about mpris recognition.

I started some youtube link which miraculously got regonized as a show? Anyway, the problem is that now, even when I pause that player, I can't get a different mpv instance with an actual show to update. It always says to ignore the new player.

Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance27320
[D] Tracker (MPRIS): New playback status: Stopped
[D] Tracker (MPRIS): New playback status: Playing
[D] Tracker (MPRIS): New video: watch?v=7lmWugBVqjM&feature=youtu.be&t=332
[D] Tracker (MPRIS): Guessing filename: watch?v=7lmWugBVqjM&feature=youtu.be&t=332
Tracker (MPRIS) warning: Found player but show not in list.
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New video: Nights of Azure 2: Bride of the New Moon - First 23 Minutes Gameplay Walkthrough Part 1
[D] Tracker (MPRIS): Guessing filename: Nights of Azure 2: Bride of the New Moon - First 23 Minutes Gameplay Walkthrough Part 1
…
Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance17815
[D] Tracker (MPRIS): New playback status: Stopped
[D] Tracker (MPRIS): Got signal from an inactive player, ignoring.
[D] Tracker (MPRIS): Got signal from an inactive player, ignoring.
[D] Tracker (MPRIS): Got signal from an inactive player, ignoring.
[D] Tracker (MPRIS): Got signal from an inactive player, ignoring.

Of course, just as I was deliberately reproducing it with a different video, it finally did end up working.

Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance19551
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New video: None
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New playback status: Playing
[D] Tracker (MPRIS): New video: [HorribleSubs] Kono Oto Tomare! - 02 [1080p].mkv
[D] Tracker (MPRIS): Guessing filename: [HorribleSubs] Kono Oto Tomare! - 02 [1080p].mkv
Tracker (MPRIS): Will update Kono Oto Tomare! 2
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New playback status: Playing

The file names of the previous episodes that didn't work were as follows:

Hitoribocchi no Marumaruseikatsu E05 [1080p][AAC][JapDub][GerEngSub][Web-DL].mkv
[Asakura] Isekai Quartet - 01 [1080p][333704BD].mkv
FichteFoll commented 5 years ago

Update: It might have something to do with a single mpv instance populating both the main and a .instance* sub…name?

I have 2 mpv instances running currently and as I started up trackma, this is what happened:

Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New video: Nights of Azure 2: Bride of the New Moon - First 23 Minutes Gameplay Walkthrough Part 1
[D] Tracker (MPRIS): Guessing filename: Nights of Azure 2: Bride of the New Moon - First 23 Minutes Gameplay Walkthrough Part 1
Tracker (MPRIS) warning: Found player but show not in list.
Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance19551
[D] Tracker (MPRIS): New playback status: Playing
[D] Tracker (MPRIS): New video: [Asakura] Isekai Quartet - 02 [1080p][0AAB8044].mkv
[D] Tracker (MPRIS): Guessing filename: [Asakura] Isekai Quartet - 02 [1080p][0AAB8044].mkv
Tracker (MPRIS): Will update Isekai Quartet 2
Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance27320
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New video: Nights of Azure 2: Bride of the New Moon - First 23 Minutes Gameplay Walkthrough Part 1
[D] Tracker (MPRIS): Guessing filename: Nights of Azure 2: Bride of the New Moon - First 23 Minutes Gameplay Walkthrough Part 1
Tracker (MPRIS) warning: Found player but show not in list.
Tracker (MPRIS): Unknown player: org.mpris.MediaPlayer2.mpd
z411 commented 5 years ago
Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance15620     
[D] Tracker (MPRIS): New playback status: Playing                                         
[D] Tracker (MPRIS): New video: watch?v=7lmWugBVqjM&feature=youtu.be&t=332                
[D] Tracker (MPRIS): Guessing filename: watch?v=7lmWugBVqjM&feature=youtu.be&t=332        
Tracker (MPRIS) warning: Found player but show not in list.                               
[D] Tracker (MPRIS): New playback status: Playing                                         
Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance15713     
[D] Tracker (MPRIS): New playback status: Playing                                         
[D] Tracker (MPRIS): New video: [HorribleSubs] Date A Live S3 - 10 [720p].mkv             
[D] Tracker (MPRIS): Guessing filename: [HorribleSubs] Date A Live S3 - 10 [720p].mkv     
Tracker (MPRIS): Will update Date A Live III 10

Can't seem to reproduce for now... that said, I just pushed a fix that potentially fixes your issue.

FichteFoll commented 5 years ago

I think for reproduction, the order in which the players are found is important. I'll continue monitoring how trackma behaves in these situation. Running the cli with debug mode has basically been my default for the past weeks.

FichteFoll commented 5 years ago
Tracker (MPRIS): Connecting to MPRIS player: org.mpris.MediaPlayer2.mpv.instance21325
[D] Tracker (MPRIS): Got signal from an inactive player, ignoring.
[D] Tracker (MPRIS): Got signal from an inactive player, ignoring.
[D] Tracker (MPRIS): New playback status: Playing
[D] Tracker (MPRIS): New video: Saki - 20 - Sisters
[D] Tracker (MPRIS): Guessing filename: Saki - 20 - Sisters
Tracker (MPRIS): Will update Saki 20
[D] Tracker (MPRIS): (1) Setting active player: :1.11688
[D] Data: No items in queue.
[D] Data: No items in queue.
Engine: Updating show Saki to episode 20...
[D] Data: Saving queue...
[D] Data: Saving cache...
Data: Queued update for Saki
[D] Data: Queued: my_progress -> 20
Data: Processing queue...
libanilist: Updating item Saki...
[D] Data: Saving cache...
[D] Data: Saving queue...
[D] Data: No items in queue.
[D] Data: No items in queue.
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New playback status: Playing
[D] Tracker (MPRIS): New video: Saki - 21 - Looking Back
[D] Tracker (MPRIS): Guessing filename: Saki - 21 - Looking Back
Tracker (MPRIS): Will update Saki 21
[D] Tracker (MPRIS): (1) Setting active player: :1.11688
[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New playback status: Playing
[D] Data: No items in queue.
Engine: Updating show Saki to episode 21...
[D] Data: Saving queue...
[D] Data: Saving cache...
Data: Queued update for Saki
[D] Data: Queued: my_progress -> 21
Data: Processing queue...
libanilist: Updating item Saki...
[D] Data: Saving cache...
[D] Data: Saving queue...
[D] Data: No items in queue.
[D] Data: No items in queue.
[D] Data: No items in queue.
[D] Data: No items in queue.
[D] Data: No items in queue.
[D] Data: No items in queue.
[D] Data: No items in queue.

[D] Tracker (MPRIS): New playback status: Paused
[D] Tracker (MPRIS): New video: Saki - 22 - Promise
[D] Tracker (MPRIS): Guessing filename: Saki - 22 - Promise
Tracker (MPRIS): Will update Saki 22
[D] Tracker (MPRIS): (1) Setting active player: :1.11688
[D] Tracker (MPRIS): New playback status: Playing
[D] Tracker (MPRIS): New video: Saki  - 23 - Serious
[D] Tracker (MPRIS): Guessing filename: Saki  - 23 - Serious
Tracker (MPRIS) warning: Not playing the next episode of Saki. Ignoring.

Another miss (at the end of the log). This time it was probably due to missing playback status updates. Or so I think? The process is just pausing, loading the next episode and playing again. Maybe timestamping the debug logs (relative to app start or datetime) could help with debugging these cases?

Soitora commented 5 years ago

That was one of my worries, hence I wanted the tracker to follow Tautullis (PlexPy) footsteps example:

If: User has played the media for ≥120 seconds (configurable) and reached ≥85% (configurable) on the playback position Then: Mark as watched.

I think 120 seconds and 80% playback sounds like a good balance for default configuration.

That would mean if a video is 25:00 long then it will check if the user has played to 02:00 (120 seconds) and then every update tick check if it has reached 20:00 (80%), if it has; mark as watched.

If you just check for 80% then simply skimming through to the end to check a scene would cause it to update when you haven't even watched it.

If you do the current timer method then skipping enough scenes (Intro, Long Flashback, Outro) will cause it to miss next playback, almost like what happened with @FichteFoll.

FichteFoll commented 5 years ago

That's not what happened to me, however. I was watching anormal 22min episode while skipping OP & ED, however that would have been more than enough to cause an update with a 5min timer. From the logs I posted, it rather seemed that trackma didn't catch the playback status changing to playing and the timer was never started. Interestingly, the following paused event was missed as well.

That said, the suggested method still sounds like a much more accurate and flexible approach (for long and short shows alike), but I believe we concluded that already and it just needs to be implemented at this point.

Edit: I added the log for the events happening before an episode was missed so you can better understand my reasoning through comparison.

z411 commented 5 years ago

Could it be that the timer is actually not advancing? There's an internal interval in the MPRIS tracker that lets the timer count down and if that is bugging out then I could imagine the timer getting stuck at 120 seconds (or the time you have configured).

P.S.: How are you running mpv? Do you close the player when an episode ends and then open up a new instance for the next episode, or are you using the same mpv instance with a playlist?

FichteFoll commented 5 years ago

I run mpv through syncplay, which manages it via a custom Lua script (instead of using IPC, weirdly enough). It manages an external Playlist and loads new videos explicitly into the same instance.

z411 commented 5 years ago

I see. I'll try to reproduce this, thanks. Let's move this discussion to #420 as there's where you also mentioned that issue, and the issue at hand in this issue has been resolved.

FichteFoll commented 5 years ago

I suspected that to be a different issue, but works for me. If you read the debug log closely, it might also seem that the timer just didn't start over there.