Chaphasilor / jellyfin-rewind

Review Your Music of 2023. A "Spotify Wrapped"-like app made for people who use Jellyfin for listening to music!
https://jellyfin-rewind.chaphasilor.xyz
105 stars 0 forks source link

Option to Filter by library when multiple present #9

Open BrennanAyers opened 8 months ago

BrennanAyers commented 8 months ago

Expected: When viewing the Rewind, either at the beginning or in the pop up settings, an option to filter out results from non-primary libraries. Most people don't/won't have multiple Music libraries, but in the instance where they do, the other ones might bring in bad data/noise. Actual: Some song I don't even think I intentionally listened to showed up in the "Most Skips" section. I know this is a niche situation, and I'm not actually sure how the Playback Reporting plugin labels songs in different libraries, if at all. Further information: This is comparison of two tracks from different libraries (first song is the wrong one, second one is the right one), from the report:

"mostSkipped": [
        {
          "name": "Not Afraid (remix)",
          "id": "8e7084650762e0c47909e46e8965538c",
          "artistsBaseInfo": [
            {
              "id": "23a2a8f858a14ff5814b77e0e8372128",
              "name": "The League of Extraordinary G'"
            }
          ],
          "albumBaseInfo": {
            "id": "048149f048a5cf314afcc7f4d168b14a",
            "name": "Concealed Weapons 2",
            "albumArtistBaseInfo": {
              "id": "23a2a8f858a14ff5814b77e0e8372128",
              "name": "The League of Extraordinary G'"
            }
          },
          "genreBaseInfo": [],
          "image": {
            "parentItemId": "048149f048a5cf314afcc7f4d168b14a",
            "primaryTag": "674b59bc4bc7486c02887ac45541f366"
          },
          "year": null,
          "duration": 262,
          "skips": {
            "partial": 0,
            "full": 2,
            "total": 2,
            "score": {
              "jellyfin": 1.2,
              "playbackReport": 6,
              "average": 2
            }
          },
          "playCount": {
            "jellyfin": 5,
            "playbackReport": 1,
            "average": 3
          },
          "plays": [
            {
              "date": "2023-10-24T15:03:09.942Z",
              "duration": 33,
              "wasFullSkip": true,
              "wasPartialSkip": false,
              "client": "Android",
              "device": "asus ASUS-AI2202",
              "method": "directStream"
            },
            {
              "date": "2023-10-25T07:27:49.874Z",
              "duration": 0,
              "wasFullSkip": true,
              "wasPartialSkip": false,
              "client": "Android",
              "device": "asus ASUS-AI2202",
              "method": "directStream"
            }
          ],
          "mostSuccessivePlays": {
            "playCount": 1,
            "totalDuration": 0
          },
          "lastPlayed": "2023-10-25T13:27:29.264Z",
          "totalPlayDuration": {
            "jellyfin": 21.8078912,
            "playbackReport": 0.55,
            "average": 12
          },
          "isFavorite": false
        },
        {
          "name": "Co-Star",
          "id": "a7117d08a6d3260baddeddecfb212015",
          "artistsBaseInfo": [
            {
              "id": "3899c089ac98a1fb036d49a0620840d8",
              "name": "amaarae"
            }
          ],
          "albumBaseInfo": {
            "id": "6e3f0a5e180ddb70a32fd6513e42759d",
            "name": "Fountain Baby",
            "albumArtistBaseInfo": {
              "id": "3899c089ac98a1fb036d49a0620840d8",
              "name": "amaarae"
            }
          },
          "genreBaseInfo": [
            {
              "id": "f1f202f389018ad2c0766af4b0fcb155",
              "name": "Pop"
            }
          ],
          "image": {
            "parentItemId": "a7117d08a6d3260baddeddecfb212015",
            "primaryTag": "52c004042781323ed9b3043a1da48b28",
            "blurhash": "eUFhbeo#0et7WB9ERj-qo0kBJCxaxCNGoLx]slRjX9NG9ZjZozayt7"
          },
          "year": 2023,
          "duration": 167,
          "skips": {
            "partial": 0,
            "full": 2,
            "total": 2,
            "score": {
              "jellyfin": 0.2857142857142857,
              "playbackReport": 0.35294117647058826,
              "average": 0.3157894736842105
            }
          },
          "playCount": {
            "jellyfin": 21,
            "playbackReport": 17,
            "average": 19
          },
          "plays": [
            {
              "date": "2023-08-02T01:39:08.560Z",
              "duration": 165,
              "client": "Finamp",
              "device": "ASUS_AI2202",
              "method": "directPlay"
            },
            {
              "date": "2023-08-02T10:39:57.077Z",
              "duration": 165,
              "client": "Finamp",
              "device": "ASUS_AI2202",
              "method": "directPlay"
            },
            {
              "date": "2023-08-02T13:16:02.120Z",
              "duration": 144,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-02T17:00:11.030Z",
              "duration": 167,
              "wasFullSkip": false,
              "wasPartialSkip": false,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-03T09:53:44.121Z",
              "duration": 145,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-03T17:10:16.627Z",
              "duration": 165,
              "client": "Finamp",
              "device": "ASUS_AI2202",
              "method": "directPlay"
            },
            {
              "date": "2023-08-04T12:49:24.900Z",
              "duration": 144,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-04T16:03:35.282Z",
              "duration": 167,
              "wasFullSkip": false,
              "wasPartialSkip": false,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-04T16:24:20.415Z",
              "duration": 145,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-04T19:34:21.443Z",
              "duration": 145,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-06T14:26:25.358Z",
              "duration": 145,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-16T10:13:03.146Z",
              "duration": 145,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-08-31T08:59:13.632Z",
              "duration": 144,
              "client": "Sonixd",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-09-11T10:03:27.491Z",
              "duration": 0,
              "wasFullSkip": true,
              "wasPartialSkip": false,
              "client": "Feishin",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-09-11T10:03:31.142Z",
              "duration": 0,
              "wasFullSkip": true,
              "wasPartialSkip": false,
              "client": "Feishin",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-09-11T10:03:39.993Z",
              "duration": 164,
              "client": "Feishin",
              "device": "PC",
              "method": "directPlay"
            },
            {
              "date": "2023-10-12T19:32:15.295Z",
              "duration": 164,
              "client": "Finamp",
              "device": "ASUS_AI2202",
              "method": "directPlay"
            },
            {
              "date": "2023-12-06T18:49:05.156Z",
              "duration": 166,
              "client": "Finamp",
              "device": "ASUS_AI2202",
              "method": "directPlay"
            },
            {
              "date": "2023-12-30T14:38:19.527Z",
              "duration": 165,
              "client": "Finamp",
              "device": "ASUS_AI2202",
              "method": "directPlay"
            }
          ],
          "mostSuccessivePlays": {
            "playCount": 1,
            "totalDuration": 165
          },
          "lastPlayed": "2023-12-30T21:37:58.399Z",
          "totalPlayDuration": {
            "jellyfin": 58.30400128,
            "playbackReport": 44.083333333333336,
            "average": 52
          },
          "isFavorite": false
        },
Chaphasilor commented 8 months ago

Filtering libraries seems like a good idea, but I'm not sure how easy it will be to add that. I'm just fetching all items the user has access to right now, so I'll probably have to touch the fundamentals to change it. What you could to as a workaround for now is going into the dashboard and removing access to the libraries in question for your account temporarily, and then re-adding after you generated the report. Would love to know if that fixes the issue!

PS: That's a Zenfone 9, correct? ^^

BrennanAyers commented 8 months ago

That's true, that would work. As I said, it's not a particularly major problem, since really it just reinforces I need to move all the things I actually want out of that old library anyways. But maybe other people have more elaborate ways of splitting things up.

And yes, Zenfone9, Zenfone10 looks like it solves all the problems but the 9 is still great, probably best phone I've had since the MotoX 🥲 I was rocking a OnePlus 3T prior so the upgrade was measurable 😅

Chaphasilor commented 8 months ago

I'm planning to refactor the code anyway, maybe I can fit it in there :)

Haha I upgraded from the OnePlus 5 to the Zenfone 10 ^^
Still can't unlock the bootloader though, so I'll probably have to sell it again in a year or so :(

BrennanAyers commented 8 months ago

Ah, yeah, I can see the Zenfone not getting as much aftermarket support since it's definitely a bit less popular. For what I need it's been great though, I've managed to go entirely Google-free (well, still use Services and Youtube 😅 but with no account! ) which has felt pretty good.

Unrelated @Chaphasilor , if there are things I'd like to test and confirm in regards to 2023 stats, but didn't have the time to do it last year, is there any easy way for me to trick it (I guess Jellyfin) into recording that information as a December date? I'm thinking specifically in regards to the skips and repeats tracking.

Chaphasilor commented 8 months ago

Hmm, not really. Jellyfin not being able to accept playback history from the past is actually a very annoying problem, because it prevents all offline listening from being recorded on the server. So fingers crossed that this will change this year!

What I could do is build you a version either for 2024, or one that supports a custom date range (in case you want to include the data from 2023 as well)

BrennanAyers commented 8 months ago

Alright. I just swear I listened to other songs on repeat more than the ones I saw in my final results. also I definitely know I skipped one every time I listened to it (part of an album, don't like the back half of the song) but I don't know how those get reported when using Sonixd or Finamp. Figure it would be easy enough to test out if you go with either of those options, but I guess we've got 12 months to try it out so no rush 😉

Chaphasilor commented 8 months ago

Yeah that's quite possible. In your case, the song you skipped probably registered as a "partial skip" because you listened to the first half, and therefore isn't ranked as high (because you don't actually hate all of it).
But the biggest problem for these features is getting a baseline of how the playback reporting data looks like for certain scenarios. It's really hard to predict how other people listen to music, and I also have a lot of test playback because I've also develop been developing features for Finamp this year.

If you are willing to provide some sample data for this song, I could take a closer look. You'd need to use the Playback Reporting plugin's Query page and filter to only the track in question (e.g. by using the ID). Having the Jellyfin BaseItemDto for the track would also be nice.

BrennanAyers commented 8 months ago

Song info pulled from network record:

{
    "10": {
        "Name": "Your Worth",
        "ServerId": "0bd39ce86afa45a3aad165afd7ab78fb",
        "Id": "cee7a2d94c7e584c1431fd5c122b6297",
        "CanDelete": true,
        "PremiereDate": "2020-09-11T00:00:00.0000000Z",
        "ChannelId": null,
        "RunTimeTicks": 1426546944,
        "ProductionYear": 2020,
        "IndexNumber": 11,
        "ParentIndexNumber": 1,
        "IsFolder": false,
        "Type": "Audio",
        "UserData": {
            "PlaybackPositionTicks": 0,
            "PlayCount": 22,
            "IsFavorite": false,
            "LastPlayedDate": "2023-12-04T14:33:57.7332489Z",
            "Played": true,
            "Key": "Knucks-London Class-0001-0011Your Worth"
        },
        "PrimaryImageAspectRatio": 1,
        "Artists": [
            "Knucks"
        ],
        "ArtistItems": [
            {
                "Name": "Knucks",
                "Id": "7360e1554a3178a1fead0822e14bff42"
            }
        ],
        "Album": "London Class",
        "AlbumId": "cab21bbfa94c1d1e6dfe6bca39365571",
        "AlbumPrimaryImageTag": "11f1d93fd7bf1dd1dca6a0eb8de29b40",
        "AlbumArtist": "Knucks",
        "AlbumArtists": [
            {
                "Name": "Knucks",
                "Id": "7360e1554a3178a1fead0822e14bff42"
            }
        ],
        "ImageTags": {
            "Primary": "3756eaf0dc30bd99aa0155996caf4637"
        },
        "BackdropImageTags": [],
        "ImageBlurHashes": {
            "Primary": {
                "3756eaf0dc30bd99aa0155996caf4637": "eNGlIyD%-;-:%2~qoyxut7of_2RjM{WBNG-;IURjt7WBj[WBRjayof",
                "11f1d93fd7bf1dd1dca6a0eb8de29b40": "eKGSAU4o_3t7-;_3WVoej@js~pM{M{WBNG%ME1M{t7Rjs:j]RjWBof"
            }
        },
        "LocationType": "FileSystem",
        "MediaType": "Audio"
    }
}

Results from Playback Reporting DB:

DateCreated UserId ItemId ItemType ItemName PlaybackMethod ClientName DeviceName PlayDuration
2023-08-11 15:53:07.4438999 2686ade92e724ea892e9bcb36e32c1d3 cee7a2d94c7e584c1431fd5c122b6297 Audio Knucks - Your Worth (London Class) DirectPlay Finamp ASUS_AI2202 65
2023-11-27 20:32:32.5676971 2686ade92e724ea892e9bcb36e32c1d3 cee7a2d94c7e584c1431fd5c122b6297 Audio Knucks - Your Worth (London Class) DirectPlay Finamp ASUS_AI2202 40
2023-12-04 07:34:18.1468263 2686ade92e724ea892e9bcb36e32c1d3 cee7a2d94c7e584c1431fd5c122b6297 Audio Knucks - Your Worth (London Class) DirectPlay Finamp ASUS_AI2202 54

Surprised I only listened to it 3 times this year, but I guess I got it out of my system otherwise the year prior...

BrennanAyers commented 8 months ago

I got an example for the repeats one as well, from the Rewind Report:

            {
              "name": "Não dá pra Explicar",
              "id": "a8eedb5e0817ad9c51fff342756098b4",
              "artistsBaseInfo": [
                {
                  "id": "4c1f8c3f2391b54ae9962b94eda17391",
                  "name": "FBC"
                },
                {
                  "id": "e178218b59cb92ce533ac00fece1e66a",
                  "name": "Vhoor"
                },
                {
                  "id": "0321d1fe03a1e739d40de9271029cbe3",
                  "name": "Mariana Cavanellas"
                }
              ],
              "albumBaseInfo": {
                "id": "10d19fa2013706ae981dd82679209d90",
                "name": "BAILE",
                "albumArtistBaseInfo": {
                  "id": "e178218b59cb92ce533ac00fece1e66a",
                  "name": "Vhoor"
                }
              },
              "genreBaseInfo": [
                {
                  "id": "76e2da7a09c2d58a10116d7ab66d9798",
                  "name": "Rap"
                },
                {
                  "id": "9bd725454d408359f2eb4ee71fd31123",
                  "name": "Hip Hop"
                }
              ],
              "image": {
                "parentItemId": "a8eedb5e0817ad9c51fff342756098b4",
                "primaryTag": "17a17fded3ecd2284c0f95bd5932b3df",
                "blurhash": "eMJ7?t?HRQ-:t9~B-og5-pV@-YtQn%ozbv?JWBnNaLxCNPV^xWa$NG"
              },
              "year": 2021,
              "duration": 195,
              "skips": {
                "partial": 0,
                "full": 0,
                "total": 0,
                "score": {
                  "jellyfin": 0.16666666666666666,
                  "playbackReport": 0.16666666666666666,
                  "average": 0.16666666666666666
                }
              },
              "playCount": {
                "jellyfin": 12,
                "playbackReport": 12,
                "average": 12
              },
              "plays": [
                {
                  "date": "2023-01-20T08:45:35.635Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-01-20T11:31:36.921Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-01-20T14:17:36.186Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-01-20T16:18:38.207Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-01-26T14:58:49.820Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-02-22T13:10:35.485Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-02-22T20:14:20.549Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-03-23T15:20:59.106Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-03-31T17:24:02.873Z",
                  "duration": 193,
                  "client": "Finamp",
                  "device": "ASUS_AI2202",
                  "method": "directPlay"
                },
                {
                  "date": "2023-05-09T22:58:58.899Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                },
                {
                  "date": "2023-06-08T20:39:10.297Z",
                  "duration": 193,
                  "client": "Finamp",
                  "device": "ASUS_AI2202",
                  "method": "directPlay"
                },
                {
                  "date": "2023-07-06T13:45:26.482Z",
                  "duration": 170,
                  "client": "Sonixd",
                  "device": "PC",
                  "method": "directPlay"
                }
              ],
              "mostSuccessivePlays": {
                "playCount": 1,
                "totalDuration": 170
              },
              "lastPlayed": "2023-07-06T19:45:06.044Z",
              "totalPlayDuration": {
                "jellyfin": 38.93812224,
                "playbackReport": 34.766666666666666,
                "average": 37
              },
              "isFavorite": false
            },
And from the Playback DB: DateCreated UserId ItemId ItemType ItemName PlaybackMethod ClientName DeviceName PlayDuration
2023-01-20 15:10:15.3533775 2686ade92e724ea892e9bcb36e32c1d3 88a423f8d387e15962e9d880e98efbb4 Audio Lucky Daye - Ego (Candydrip) DirectPlay Sonixd PC 234
2023-01-20 14:17:36.1867765 2686ade92e724ea892e9bcb36e32c1d3 a8eedb5e0817ad9c51fff342756098b4 Audio Vhoor - Não dá pra Explicar (BAILE) DirectPlay Sonixd PC 170
2023-01-20 11:31:36.9218709 2686ade92e724ea892e9bcb36e32c1d3 a8eedb5e0817ad9c51fff342756098b4 Audio Vhoor - Não dá pra Explicar (BAILE) DirectPlay Sonixd PC 170
2023-01-20 08:51:21.4398234 2686ade92e724ea892e9bcb36e32c1d3 7ca0378940f56e34c588e0fefeb17850 Audio Vhoor - De Kenner (BAILE) DirectPlay Sonixd PC 131

Well, and now looking at it, the timestamps are quite far apart... I feel like I remember sitting there hitting Play over and over, but apparently not. Definitely did with some other songs outside of Jellyfin, maybe I'm just conflating the two 😶