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

Missing tracks from spotify when you play part of a song, pause, and come back later #124

Closed
kellya opened this issue Jan 5, 2024 · 5 comments

Comments

@kellya
Copy link

kellya commented Jan 5, 2024

Please check the FAQ before submitting a bug report.

Describe the bug
If you play a song 50%, pause it, do something else for a period of time and then come back to play the rest of it, Spotify will pick up playing the song where it left off, but Multi-Scrobble starts the play time over again. My typical use pattern is play spotify on my phone in the car, come home/disconnect from the car, do things, and then eventually pick up listening again on my computer. It doesn't have anything to do with changing devices, I'm just demonstrating that in my usage, the trigger is very common.

Here is a screenshot of what I'm talking about. It picked up where I left off, almost 3 minutes in, but is showing 20s listened when I started playing it again. That may technically be true for this portion of the play, but this means that if you play a song beyond 50%, pause it, and then come back later; that track will never get scrobbled because it can never hit the played threshold.

image

To Reproduce
Steps to reproduce the behavior:

  1. In Spotify, play a song to over 50% of the time
  2. Pause the song after playing at least 50% (so that the next time you start, it's impossible to play the threshold that would scrobble)
  3. Wait for the player to go idle (15 minutes)
  4. Begin playing the song again
  5. Let the song complete
  6. The track will not be scrobbled because this second part play doesn't cross the 50% threshold

Expected behavior
It is expected that once a track completes, it will get posted as a listen. Even though it was paused for a period of time, the track was actually completed.

Logs
The logs show that it "wanted 50%" and the tracked time didn't match that.

2024-01-04T22:42:55-05:00 verbose : [Sources] [Spotify - unnamed] [Player e5b95f80c8-salticus.franklin.edu-SingleUser] (5n9o0Z4Is58SMhpX3WWTLi) Cassius / Owlle - Don't Let Me Be not added because did not meet thresholds with tracked time of 51.31s (wanted 240s) and tracked percent of 23.00% (wanted 50%).
2024-01-04T22:42:55-05:00 debug   : [Sources] [Spotify - unnamed] [Player e5b95f80c8-salticus.franklin.edu-SingleUser] Started new Player listen range.
2024-01-04T22:42:55-05:00 debug   : [Sources] [Spotify - unnamed] [Player e5b95f80c8-salticus.franklin.edu-SingleUser] New Play: (3NlAkVIhq67sFHkBkc0qZc) The Knife - You Take My Breath Away
2024-01-04T22:42:55-05:00 debug   : [Sources] [Spotify - unnamed] [Player e5b95f80c8-salticus.franklin.edu-SingleUser] Ended current Player listen range.
2024-01-04T22:42:55-05:00 debug   : [Sources] [Spotify - unnamed] [Player e5b95f80c8-salticus.franklin.edu-SingleUser] Incoming play state ((3NlAkVIhq67sFHkBkc0qZc) The Knife - You Take My Breath Away) does not match existing state, removing existing: (5n9o0Z4Is58SMhpX3WWTLi) Cassius / Owlle - Don't Let Me Be

Versions (please complete the following information):
Provide version information for any related sources/clients.

  • multi-scrobbler: 0.4.6 (docker)
  • Spotify - ios 8.8.96 + linux desktop flathub version 1.2.26.1187.g36b715a1

Additional context
I don't think the Spotify clients have anything to do with the issue, but I've specified for completeness.

I have also used Multi-Scrobble for a whole 2 days at this point, so I'm pretty new to it but I did look at the FAQ, Docs, and through the bug reports to see if anyone else had reported this or if I was missing some configuration nuance.

I know about the

    "scrobbleThresholds": {
      "duration": 30,
      "percent": 50
    },

settings in the config.json, and that might be tweakable as a work-around that would make it trigger less often, but this case would still be triggerable unless you set the percent to something ridiculously low; which could then cause false positives as you start a song and hit next to skip it.

@FoxxMD
Copy link
Owner

FoxxMD commented Jan 5, 2024

Thanks for the thorough writeup.

The behavior you are seeing is (mostly) by design though it would be fair to call it opinionated. From the last.fm scrobbling FAQ and api docs (with emphasis by me):

Scrobbles are not quite the same thing as plays -- a scrobble implies that you actually listened to the track all the way through, and didn't stop or skip it...a scrobble is more than just a count of how many times you've listened to a track, but also a record of when.
...
A track should only be scrobbled when the following conditions have been met:

  • The track must be longer than 30 seconds.
  • And the track has been played for at least half its duration, or for 4 minutes (whichever occurs earlier.)

As soon as these conditions have been met, the scrobble request may be sent at any time. It is often most convenient to send a scrobble request when a track has finished playing.

My interpretation of this is that, contextually, your listening session is more important for scrobbling than just counting the track currently on the player.

As a contrived example, let's say you are listening to a track that is 15 minutes long (some classical symphony). You are sitting in your living room and listen to the first 5 minutes before the timer on your oven goes off because you are in the middle of cooking dinner. You pause the track, go prep dinner for 30 minutes, then come back to finish the track (listening for another 10 minutes). Physically (mentally? emotionally?) you have experienced two listening sessions for the same track but only listened to the track once. In my mind that is two scrobbles. That is, of course, my subjective interpretation :) but its how I built multi-scrobbler to handle those kind of situations.

HOWEVER...

My typical use pattern is play spotify on my phone in the car, come home/disconnect from the car, do things, and then eventually pick up listening again on my computer. It doesn't have anything to do with changing devices, I'm just demonstrating that in my usage, the trigger is very common.

multi-scrobbler initiating a new listening session due to spotify device change IS a bug 😅 and one that I coincidentally fixed yesterday before you created this issue! Please try switching your docker image to multi-scrobbler:experimental and see if this resolves your usage issue to your satisfaction.

If it doesn't or or you'd like to present an argument against listening sessions for scrobbles I could be convinced to add a config option for changing this behavior :)

@kellya
Copy link
Author

kellya commented Jan 6, 2024

Thank you for your quick response, and for your thoughts on this issue.

I have been using the experimental docker version today. I have noticed that I'm not seeing two separate player sessions in multi-scrobbler after that change. So I do think that I was additionally seeing the device change issue, and now that does seem fixed.

As for the scrobbling/% played portion; I understand the intent to capture actual plays and not simply track changes. From your example as written you said if you play the first 5 minutes of 15 minute track, prep dinner for 30 minutes and finish the remaining 10 minutes of the track that was started "you have experienced two listening sessions for the same track but only listened to the track once. In my mind that is two scrobbles". I do agree with that logic, you have effectively listened twice, but the 50% play threshold is at odds with that.

In this example, it would only actually get scrobbled once. The first 5 minutes are effectively ignored, and on the second listen, the track would be listened to for more than 30 seconds and will complete 50% of the track when you hit the end of the track.

If the scenario is inverted, and the first listen is 10 minutes, after coming back later and playing the remaining 5 there will be zero scrobbles, even though you listened to more than 30 seconds (technically more than 4 minutes too, which I didn't realize was also a threshold) and greater than 50% on the first listen.

Essentially in any of these cases, it's only what happens on the last play that matters (since the status is being checked on track change). So if you play more then 50% of a song and come back, you get no scrobbles. It's certainly not the end of the world, but I would definitely appreciate an option that somehow made it so scrobbles weren't missed :)

So I think either an option to ignore sessions, and just assume that if a play starts at a non-zero time, then all that time counts to the percentage played, or if it submitted as soon as a threshold was crossed (rather than the end of a track) would work. Of course I say that having zero knowledge of what it takes to implement that ;)

Thanks again for your consideration, and thank you for making this as awesome as it is already.

@FoxxMD
Copy link
Owner

FoxxMD commented Jan 10, 2024

The original issue where MS didn't carry sessions between devices has been fixed in 0.6.3

@FoxxMD
Copy link
Owner

FoxxMD commented Feb 5, 2024

So I've gone back through the code and reviewed this a little more thoroughly. I think we agree on how scrobbling behavior should work but were missing each others' intentions when trying to communicate it.

MS has two ways of "discovering" scrobbles from a source:

  • The source provides "recently played" data -- a list of track/artist/album data (a Play) that include a timestamp of when it was listened to and (optionally) for how long it was listened to.
  • The source provides real-time "player" data about what a user is listening to. Track/artist/album data (play) along with (optionally) position of player in current track, when the track started, the current player state (stopped, paused, playing), etc...

The former is only used for a few sources that either do not provide a player or have more authoritative recently played data -- lastfm, listenbrainz, webscrobbler, and deezer.

The latter is used for all other sources. Either because they do not provide recently played or because their player data is more widely available (tracks listened on spotify connect devices do not appear in recently played but are presented to player endpoint) or more accurate (spotify presents player position and status).

The player is what we are discussing here. MS builds its own representation of a Source's player in order to more reliably model scrobbling behavior. It detects things like seeking and allows for network hiccups, etc... An overview of the behavior may clarify what we are trying to hash out:

  • MS checks if a Play should be scrobbled when the player detects a play's session ends. A play is scrobbled if:
    • MS knows how long the play's track is and it has been listened to for more than 50% of its length (scrobbleThresholds.percent) or
    • The play was listened to for longer than 4 minutes (scrobbleThresholds.duration)
  • During a play session MS tracks all interrupted durations of listening (listened to)
    • This can be multiple durations if the normal "flow" of listening is interrupted. For example:
      • (first duration) -- From start of track for 45 seconds, then the player is paused for 2 minutes. => 45 seconds
      • (second duration) -- Player is unpaused, listened for another 15 seconds, then paused for another minute. => 15 seconds
      • (third duration) -- Player is seeked 20 seconds ahead, then played till end of track which is another 60 seconds. => 60 seconds
      • At the end of the play session there were 120 seconds of continuous listening -- this is how long the play was listened to.
  • MS player detects a play session is ended under any of these conditions:
    • The Source player reports a new Play
    • The Source player reports it is stopped IE queue has been cleared, no song is playing, it is in idle state, etc...
      • MS differentiates between stopped and paused, if the Source player reports it. MS will not end a session as long as the player continues to report paused and does not become stale.
    • The Source player becomes Stale
      • if the Source stops providing data for the unique player (determined by MS) and X amount of time has passed it become Stale.
    • The Play in the current session has not ended but Source player position indicates it is being repeated:
      • new player position is within 10 seconds or 10% of start of track and
        • session has at least 2 minutes or 50% of track already listened to or
        • last position is within 10 seconds (or 10%) of end of track

I believe that in the example you gave MS should behave as you desire. There would be only one play session, assuming the Source player stays paused and reporting paused, between the separate listens.

You may find that in the real world this is not the case, though. Specifically for Spotify (though im sure for other Sources) if you close the desktop player or let the ios/android app idle in the background on paused for too long Spotify will stop reporting the player data which MS will detect as a play session end if the player does not reappear after a certain amount of time (becomes stale). Usually about 3 minutes.

For this scenario I do not plan to add any additional "smartness" to MS -- it would be very hard to determine the user's intention when the player resumed...if it resumed 4 hours later would it be the same session? Or count as a different session? What if it never resumed, should MS not scrobble the paused session for days while it waits for the next time the user opens Spotify? I would prefer to leave this up to the user and their own behavior...if you do not want the session to end between a 10 minute break then leave the app open but paused. This generally reflects the desired behavior better than MS trying to be clever about it.

@FoxxMD
Copy link
Owner

FoxxMD commented Feb 14, 2024

If this is something you/someone else wants to discuss further I'll convert this issue to a discussion!

@FoxxMD FoxxMD closed this as completed Feb 14, 2024
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

No branches or pull requests

2 participants