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

Incorrect, Mismatching Tracks Played #883

Open
1 task done
sagie-d opened this issue Nov 16, 2023 · 15 comments
Open
1 task done

Incorrect, Mismatching Tracks Played #883

sagie-d opened this issue Nov 16, 2023 · 15 comments
Labels
bug Something isn't working

Comments

@sagie-d
Copy link

sagie-d commented Nov 16, 2023

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I've been playing several chill/ambient playlists by Spotify. These are usually made from non-popular tracks, sometimes even downright esoteric, which aren't available on YouTube.

It seems like spotube will happily play a track even if there's a clear mismatch between the desired track and the found track. When playing chill/ambient music this is especially bothersome as the mismatching tracks are often upbeat, causing an inconsistent listening experience.

Examples:

  1. In "Jazz for Sleep" playlist, track #⁠11 in the playlist "Hoy Como Ayer?" (duration 2:48) by Tim Walker-Price isn't found on YouTube. Spotube plays instead "Ayer (Cover Audio)" (duration 3:53) by Matisse.
  2. The last track (#⁠338) in the same playlist, "I Left My Heart in San Francisco" (duration 4:33) by Jim Jensen, also isn't found in YouTube. Spotube plays instead "San Francisco" (duration 3:59) by Ge & Luke,

These are only two examples -- there are many more like these.

Clearly there's no relation between the desired tracks and the actual tracks played.

Expected Behavior

Play only tracks with title and artist exactly matching. If none are found, skip to next track.

Steps to reproduce

  1. Start spotube
  2. Search for "Jazz for Sleep" playlist.
  3. Try to play the aforementioned tracks.
  4. Notice how other tracks are played instead.

Operating System

Windows

Spotube version

v3.2.0

Installation source

GitHub Releases (Binary)

Additional information

No response

@sagie-d sagie-d added the bug Something isn't working label Nov 16, 2023
@ghost
Copy link

ghost commented Nov 17, 2023

Same problem here

Screenshot_20231117-073835~2.png

The first track, by artist Pushpa Paghdharey, is supposed to be the FEMALE VERSION of the track.
But on playing, you'll realise it's the male.

The second track is supposed to be the MALE VERSION.
On playing, it's the female.

One more thing, the length of the track displayed is incorrect, too.

Screenshot_20231117-074412.png

(The female version)

@vortexal
Copy link

I'm not sure why my issue was labeled a duplicate of this issue as this is completely different from my issues (#889). The issue I'm having is that when I select the song I specified nothing plays and it locks up the playlist. I'll edit my issue since I apparently wasn't clear about that.

@KRTirtho
Copy link
Owner

The underlying reason is same and in your case it just doesn't had any results at all. That's why

@skyisthela
Copy link

The underlying reason is same and in your case it just doesn't had any results at all. That's why

just asking but how does the client work? since it doesn't utilize spotify's api but rather youtube piped and jiosaavn wouldn't it be possible and just make the searches more accurate?

@sagie-d
Copy link
Author

sagie-d commented Nov 30, 2023

just asking but how does the client work? since it doesn't utilize spotify's api but rather youtube piped and jiosaavn wouldn't it be possible and just make the searches more accurate?

That's the beauty of open source, you can have a look for yourself and offer a concrete fix for a problem, instead of a vague advice like "just make the searches more accurate".

@skyisthela
Copy link

just asking but how does the client work? since it doesn't utilize spotify's api but rather youtube piped and jiosaavn wouldn't it be possible and just make the searches more accurate?

That's the beauty of open source, you can have a look for yourself and offer a concrete fix for a problem, instead of a vague advice like "just make the searches more accurate".

i gave that "advice" because i don't know how code works. if i knew i wouldn't be making my initial comment and neither would you. your issue is basically about the same as mine, a track with the similar name but different audio plays, the conclusion i came to was that searches just wasn't accurate

@petyy
Copy link

petyy commented Dec 6, 2023

Probably the same problem here. I tried to play Jaroslav Nohavica's album "Divné století" and the very first song "Divocí koně" and instead of album version I got some live version non present on the album at all. The same happens on Okean Elzy's album Без меж with a track Мить. Instead of album track it plays this reaction on the song: https://www.youtube.com/watch?v=OMI-lhTl7HA

Hope it will help with the debugging...

@Simon-L
Copy link

Simon-L commented Dec 12, 2023

@skyisthela said:

i gave that "advice" because i don't know how code works. if i knew i wouldn't be making my initial comment and neither would you. your issue is basically about the same as mine, a track with the similar name but different audio plays, the conclusion i came to was that searches just wasn't accurate

Completely agree with this.
To be frank, I wished more that once that I could contribute to Spotube, sadly Dart is a very uncommon language and Flutter is a big dependency. This makes it much less likely that developers encountering bugs will go through the process of installing the tools, SDK etc.

As for the song mismatch problem, I have the same issue with this one https://open.spotify.com/track/5OT2JR7Lf4g4dCJyZ8Xu0f
My guess is that when searching the Youtube Music/Piped backend for the track, the wrong one has a better match/hit score in the results, though here the first one is a correct match: https://piped.video/results?search_query=nurse+and+protect+-+the+mandalorian+-+ludwig+g%C3%B6ransson Spotube plays this one https://piped.video/watch?v=Db_A2D2TKmc

OTOH what I can think of is to make the search and match make sure that tracks from the same album are preferably taken from the same source and same uploader, copyright info, possibly even exist in the same playlist.

@zed-wong
Copy link

I think the current method is search the song name on YouTube, but maybe it's better to search the Name + Singer. Not sure if it's gonna be better just a possibility.

@KRTirtho
Copy link
Owner

For anyone who wants to know how the track is matched for YouTube/Piped (YouTube)

static List<YoutubeVideoInfo> rankResults(
List<YoutubeVideoInfo> results, Track track) {
final artists = (track.artists ?? [])
.map((ar) => ar.name)
.toList()
.whereNotNull()
.toList();
return results
.sorted((a, b) => b.views.compareTo(a.views))
.map((sibling) {
int score = 0;
for (final artist in artists) {
final isSameChannelArtist =
sibling.channelName.toLowerCase() == artist.toLowerCase();
final channelContainsArtist = sibling.channelName
.toLowerCase()
.contains(artist.toLowerCase());
if (isSameChannelArtist || channelContainsArtist) {
score += 1;
}
final titleContainsArtist =
sibling.title.toLowerCase().contains(artist.toLowerCase());
if (titleContainsArtist) {
score += 1;
}
}
final titleContainsTrackName =
sibling.title.toLowerCase().contains(track.name!.toLowerCase());
final hasOfficialFlag =
officialMusicRegex.hasMatch(sibling.title.toLowerCase());
if (titleContainsTrackName) {
score += 3;
}
if (hasOfficialFlag) {
score += 1;
}
if (hasOfficialFlag && titleContainsTrackName) {
score += 2;
}
return (sibling: sibling, score: score);
})
.sorted((a, b) => b.score.compareTo(a.score))
.map((e) => e.sibling)
.toList();
}
static Future<List<SiblingType>> fetchSiblings({
required Track track,
required Ref ref,
}) async {
final query = SourcedTrack.getSearchTerm(track);
final searchResults = await youtubeClient.search.search(
query,
filter: TypeFilters.video,
);
if (ServiceUtils.onlyContainsEnglish(query)) {
return await Future.wait(searchResults
.map(YoutubeVideoInfo.fromVideo)
.mapIndexed(toSiblingType));
}
final rankedSiblings = rankResults(
searchResults.map(YoutubeVideoInfo.fromVideo).toList(),
track,
);
return await Future.wait(rankedSiblings.mapIndexed(toSiblingType));
}

Code Summary for non-coders

It's basically a ranking system that ranks the best matching track. It just assigns points on different kind of matches.

Pointing table

  1. video title contains title of the song => +3
  2. video title contains artists => +1
  3. one of artist and channel name is same => +1
  4. Title has suffix like Official Audio/Video/Lyric Video etc => +1
  5. has both 1 & 3 => +2

Finally, it just sorts the matched tracks by highest point and the first one of them gets played.

@will2022
Copy link

will2022 commented Jan 27, 2024

This video title doesn't contain the artist or title of the song, but it still gets picked instead of this video, which both has the artist names and the correct song title?

@ghost
Copy link

ghost commented Feb 3, 2024

i currently have the same Problem
image

The version made from marz is only on Spotify and the version made from nightmares only on Youtube(music). Both of them are different but Spotube plays the same music for both (waste.mp3 from nightmares).
(its not just on search queue, i had this song on my Liked paylist before logging into Spotube)

Notice: I logged in with my Spotify account using my sp_dc Cookie and installed from aur (Arch x86_64) (yay -S spotube-bin).
Last time updated: 04.02.2024 (today installed)

@will2022
Copy link

will2022 commented Feb 5, 2024

Plex has a function for fixing mismatches when identifying movies etc. Something similar would be great.

Edit: I just found the "Alternative track sources"-button. I hope it saves the selected source

@KaceCottam
Copy link

Hi, I also wanted to make a report of a mismatched song being chosen.
With the song: "There's Fear in Letting Go" by "I Prevail"

It seems like there is a problem with the search results, because "I Prevail - There's Fear in Letting Go (Official Music Video)" by "IPrevailBand" exists, but it does not even show up in the alternative sources list. Is there a log to see what videos it matched and what search terms it used?

It instead chooses I Prevail - Scars by the same youtube channel. Interestingly, I Prevail- There's Fear in Letting Go does show up in the alternative sources but it has a lower score (I am assuming according to this comment, the score adds up to 4 (pointing table: 1 & 2) whereas Scars' score adds up to 5 (pointing table: 1 & 2 & 4)). On initial look into the code in the linked comment, notably whitespace is not ignored in the band name, which would lead to less score (@IPrevailBand possibly not being matched for the artist "I Prevail").

Might I instead propose a scoring system using a list of ordering criteria similar to your code in the vein of this code block?
https://github.com/mythz/dart-linq-examples/blob/065fd087f11f25f3d6ebfad1ff29ce4b5cb35d5d/bin/linq-ordering.dart#L149C1-L169C3

Perhaps reordering your code to be something more akin to C# OrderBy(...).ThenBy(...) syntax might be preferable to a score. The way that I see it, the main problem lies in the fact that something can be mis-scored easily when there are important indicators that the right video is present. Here is some sample code of what I mean:

// Want to say sorry if this isn't valid dart code b/c I have never coded in dart, anyways I hope my point gets across

// stolen from https://github.com/mythz/dart-linq-examples/blob/master/bin/linq-ordering.dart
wrap(value, fn(x)) => fn(value);
// modified from https://github.com/mythz/dart-linq-examples/blob/master/bin/linq-ordering.dart
// see: C# OrderBy(...).ThenBy(...) syntax. The main difference is that I am using `onto` functions to see what to compare instead of directly comparing
List<T> order<T>(List<T> seq, { required List<Function> onAll }) {
    return seq..sort((a,b) =>
        wrap(onAll.firstWhere((_on) => _on(a).compareTo(_on(b)) != 0, orElse:() => (x) => 0),
            (_on) => _on(a).compareTo(_on(b))));
}

List<YoutubeVideoInfo> rankResults(List<YoutubeVideoInfo> results, Track track) { 
    final notWhitespace = (c) => c != ' '; // or something similar from the standard library, I haven't worked with dart before
    final artists = (track.artists ?? []) 
       .map((ar) => ar.name) 
       .toList() 
       .whereNotNull() 
       .toList();

    // we do not care about whitespace, and we want the case to be the same.
    // we may also want to ignore stuff like hyphens, quotes, parenthesis, various other symbols here for the best matching
    final compareIdeally = (s) => s.toLowerCase().where(notWhitespace);

    final byViews = (sibling) => -sibling.views; // negative to sort by descending
    final isSameChannelArtist = (sibling) =>
        artists.sumBy((artist) {
            final isSameChannelArtist = sibling.channelName.toLowerCase() == artist.toLowerCase(); 
            final channelContainsArtist = compareIdeally(sibling.channelName)
               .contains(compareIdeally(artist)); 
            return (isSameChannelArtist || channelContainsArtist) ? 1 : 0;
        });
    final titleContainsArtist = (sibling) => 
        artists.sumBy((artist){
            final titleContainsArtist = compareIdeally(sibling.title)
                .contains(compareIdeally(artist)); 
            return titleContainsArtist ? 1 : 0;
        });
    final titleContainsTrackName = (sibling) =>
        compareIdeally(sibling.title).contains(compareIdeally(track.name)); 
    final hasOfficialFlag = (sibling) => officialMusicRegex.hasMatch(sibling.title.toLowerCase()); 
    final hasTitleAndFlag = (sibling) => titleContainsTrackName(sibling) && hasOfficialFlag(sibling);

    // will sort by the value of each of the functions in order. 
    // not scoring, but continuously fine-tuning the order of the results.
    return order(results, onAll: [
        isSameChannelArtist, // order first by tracks where the channel contains the artist(s) \ _ considering swapping these two
        hasTitleAndFlag, // then by tracks containing the song title and official flag         /
        titleContainsTrackName, // then by tracks containing track name,
        titleContainsArtist,  // then by artist in the video title
        hasOfficialFlag, // then by (official music video) or whatever the regex is
        byViews, // finally by views, in case the same channel uploaded the exact same video twice for some reason
        ]);
 } 

I also wonder if it would be possible to have users opt in to an external service (by logging in and using our own accounts/api keys) like http://song.link for getting more reliably matching results, although I understand that is a large undertaking.

@adam110902
Copy link

Similar problem
sometimes instead of the correct song a completly unrelated song/video plays
Screenshot_20240609_002706_Spotube
Alternative track finds multiple correct versions of the song but something else is played anyway, always with that green symbol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

10 participants