SongKong Jaikoz

SongKong and Jaikoz Music Tagger Community Forum

Featured and "co-artist" handling

Hi Paul,

I’ve spent several hours thinking about this now, writing, rewriting, reading and exploring (rediscovering!) the existing capabilities of Jaikoz and SongKong, and, I’m getting tired or trying to make this post really coherent and brief. :slight_smile:

That said, the TLDR is:
I’m not sure… I think it may be a better feature for the ‘Scripter’ mentioned in https://jthink.atlassian.net/jira/software/c/projects/SONGKONG/issues/SONGKONG-2625?jql=project%20%3D%20"SONGKONG"%20ORDER%20BY%20created%20DESC

I think the find-replace metaphor may not be ideal because I’d need to update TWO different fields (title and artist) based on relationship of two fields (artist and albumartist)


Here’s my more detailed/roundabout way of coming to that conclusion.

I had forgotten about the Auto Edit feature’s existence, having never used it.

I see the point you’re making in the first paragraph. And yes, you’re right; the real problem is that the [Track] Artist field is inconsistent for the album. This is only a problem when dealing with a UI that doesn’t know to pay attention to Album Artist. Actually, I think the subtleties regarding how a UI should treat Album Artist vs Artist in various scenarios probably warrants a small essay, so I’ll leave it at that, but acknowledge it’s really not quite that simple.

For purposes of this discussion, to work around brain dead UIs, the search and replace operation you’re suggesting would fix that part of the problem.

But it doesn’t update the title to include the co-artist info. (Or ‘other’ artist.). I would like to preserve their involvement in some way, even though that is of secondary concern.

I’m not sure the find/replace metaphor would work for this unless you could build up complex operations:

if (AlbumArtist != "Various Artists") {
  set title = title + " ({ListOfContributors(AlbumArtist, TrackArtists)})"
  set TrackArtist = AlbumArtist
}

This snippet assumes that there is a concept of a multi-valued “TrackArtists” (seems a fair guess) which includes all artists who worked on the track, including an indication of whether they were ‘featured’ or should receive “co-artist” billing. The “ListOfContributors” function would be responsible for figuring that all out. It could be defined by the user, or built-in.

So, my first thought is that this example may be more than you had in mind for the find/replace macro capability. (Actually, I think “find/replace” stops being a good name for it at this point. It’s just a script. (Note from Future Jason: It was shortly after I wrote this last bit, as part of a ‘go back and re-write that part’ that I went back and re-read your JIRAs and noticed you had made mention of a possible “Scripter”) It basically requires what amounts to a domain specific language. But I guess you kind of have that already in the file/folder renaming masks.

Assuming “artists” contains the required data, if you built this, I think that would satisfy my desire.

A few thoughts on that, however.

  1. I’d prefer not to have to run a separate find/replace operation after I’ve done fix songs (I may not even know that it’s required until later)
  2. If it was run as a separate operation, I be concerned about making sure the operation was defined in a way that makes it idempotent so that accidental multiple runs wouldn’t ‘corrupt’ the data. (imagine I have to run it on one album, and then later I run it for the artist, or my whole collection, etc.)
  3. If the operations could be chained to an existing Fix Songs or Monitor Watch Folder profile, that might help address both of the above concerns.

Is that what you had in mind? Or did I just make it way more complicated?


So, that’s where I was when I saw that you had mentioned a Scripter which I guess is on the roadmap, and I thought, crap, I don’t want to re-write all of this AGAIN :).
I think the Scripter (if it resembles what I described above) could do this. Find and replace? Meh, that might be hard (thinking about how that would apply to the title field).
I don’t know for sure that “Artists” is structured the way I’m assuming it is, but I’m guessing that whatever info you used to do the current “featuring” process could be made available, and that a user could write code that could tell the difference between a co-artist and a featured artist.
It would be good if Scripts could be added to Fix Songs and Monitor Watch Folder as post-operations (maybe pre-operations, too? Not sure. I don’t have a use case for that at this moment, and can’t really imagine what the point would be, before the data was Fixed. I guess that depends on what operations are in scope for Scripting.)

The checkbox with multiple options seems a lot simpler, but if you see another solution available that’s more general, flexible, and powerful, but needs your focus to deliver, I get it. I’m not sure how many users would be into that kind of tool. Maybe a lot. (I just realized recently that the community of people who own a swimming pool and maintain it themselves has a much higher proportion of nerds than the general public - maybe this is another such population!)

Okay I forgot about the title thing, yes you are right if you want to do that then find and replace wouldn’t work, and even it did would gave issue if rerun if using title += title idea.

Scripter would be powerful enough for this but may still have the rerun issue.

Your original solution would work (in most cases). But I’m not that keen to add an option that essentially adds wrong data just to compensate for a bad car ui that only you may use.

Will muse further.

Okay I am making good progress with Scripter task, (it works I just need to build web UI and a few other things). Scripter task will not only let you set metadata fields to combinations of other metadata fields, if the song is linked to a MusicBrainz or Discogs album then you can use the native values from the matched mb or discogs release. So I think it will possible to create a script that can be rerun on the same files more than once and get same result - https://jthink.atlassian.net/browse/SONGKONG-2639

Also note, that although this means you currently will have to run Fix Songs and Scripter this gives the best flexibility, and in future will be able to chain together tasks.

Very Exciting!

Few thoughts I’ve had (some a while back, some just now).

So I think it will possible to create a script that can be rerun on the same fies more than once and get same result

It occurred to me later after writing the bit about idempotence that that is really the script writer’s responsibility - and as long as I run it as part of an Fix Songs operation (an ‘after’ step) I can assume that while the update may not be idempotent, the total operation would be (because the Fix would reinitialize the title.).

However, if there are other authoritative versions of that same info (MB, Discogs) - that’s even better - that can be treated as a read only source.

Out of curiosity, how are those stored? In the file? Or in the SK database? For that matter, are those (and other similar fields) already documented somewhere?

Two other thoughts, brought about by the Jiras you linked:

  • For https://jthink.atlassian.net/browse/SONGKONG-2627, I don’t know what you’re thinking, but one approach could be to create a ‘macro’ feature that allows you to orchestrate other operations - that way the other operations don’t have to grow any extra brains about that concept - keeps it modular. Not sure that’s the best way, just popped in my head.
  • For https://jthink.atlassian.net/browse/SONGKONG-2639, I note that you refer to it as a ‘task’. I was assuming the Scripter would allow you(me) to write arbitrary JavaScript similar to what I think I’ve seen in the other areas, which would just allow you to read/write values - is that not what you had in mind? Or is it what you meant, but you intend to write a function so that I don’t have to do it myself?

Are you thinking the Scripter will be able to operate beyond the context of songs? I realize I don’t know what your vision for that is.

Have a good weekend, and thanks for the update
Jason

The mb, discogs values are taken from the MusicBrainz or Discogs release/Track just like when we run Fix Songs.

If you consider the rename files mask part of the Rename Files script that lets you write javascript to modify the filename.

Scripter simply extends this so that can modify multiple metdata fields to other metadata fields using javascript.

We will provide some useful scripts similar to how we provide some rename masks and you can use these, combine these or write your own scripts from scratch. But the end result of any script is simply that you can use it to modify metadata fields, not anything else.

And I have extended both Scripter and Rename Files so if your song is matched to MusicBrainz or Discogs then you can also use certain info directly from these rather from your metdata fields i.e MusicBrainz release title rather than the album metadata field. This is a new concept, so not currently part of SongKong.

Your macro idea is essentially how I’m going to do it, the chained tasks are not aware they are part of a larger workflow.

Cool - makes sense, and sounds awesome. :slight_smile:

The mb, discogs values are taken from the MusicBrainz or Discogs release/Track just like when we run Fix Songs.

I understand that, I think. What I meant was… When we run one of these scripts, and it refers to (for example) “MusicBrainz release title”, will it make an API call every time? Or will it pull it from the file? Or a local cached value in a DB? Etc.
And if that value doesn’t exist already (or, assuming an API call is to be made), it hasn’t been matched to MB yet, would it just use an empty string?

We have a cache that we add MusicBrainz releases to so usually just have to get from api once. If no match yes would be empty string.

So I have written this for Scripter, seems to work but might need finessing.

   if(albumartist!='Various Artists')
{
   artist=albumartist;
   var ft='';

   for (var index = 0; index < artists_index.length; index++) 
   {
      if(!artist.contains(artists_index[index]))
      {
         ft+=artists_index[index] + '; ';
      }
   } 
   if(ft.length>0)
   {
      ft=ft.substring(0, ft.length-2);
      if(mb_track_title.length()>0)
      {
         title=mb_track_title +' (Ft.' + ft +')';
     }
     else if(discogs_title.length()>0)
      {
         title=discogs_title +' (Ft.' + ft +')';
     }
   }

So for any song with albumartist not credited to ‘Various Artists’ the (track) artist is set to albumartist . If song has been matched then we should have also an artists field containing each track artist as a separate value. So we loop around these and if we cannot find the artist in the new artist field then we add the artist to a ft variable plus a '; ’ seperator. At the end of the looping if ft has a value and we have a MusicBrainz match we then set title to mb_track_title + value of ft variable. Because we are using mb_track_title we are always using the original value, alternatively if only Discogs match we use discogs_title If neither then we cannot modify the title so maybe cannot capture extrack artists but we can still ensure artist is now the same as albumartist.

That’s great!

That script looks like it would do the trick. I take it that the variable “artist_index” is a actually a list of the artists? (The name threw me off at first; I thought you’d made a typo.)

My other question: Is there a way to tell the difference between a “Featuring” and a “with”?

I’ll draw your attention back to the songs on the album I’d highlighted at the beginning of this.
Album release: https://musicbrainz.org/release/b2f15f37-aaea-4dd4-bf12-820da0999cd8
Track 2 (Immortal Queen; Sia feat. Chakha Khan): https://musicbrainz.org/recording/03502caf-336f-4f0a-a1cc-bf0b5bbd4394
Track 3 (Dance Alone Sia & Kylie Minogue): https://musicbrainz.org/recording/25278947-ab81-427e-b58d-1518e0492b67

I can’t tell from the MB UI how they distinguish, but I guess from the UI treatment (“feat.”" vs “and”/"&") that there is some difference in how it’s stored (or in other metadata).
Is that distinction available in the SK context?

It is artists_index. So the artists field stores the artists as a list of values whereas artist field stores as one value. When you access any metadata field with the scripting if it has multiple values then they are returned in the form artist1;artist2;artists…. But you can also access an array of values by adding _index to the end of the script field name as we have done.

Your second question confuses me. MusicBrainz actually returns an artist credit which consists of a list of artists and the join phrase between them, and within Fix Songs we use the join phrase to decide whether the artist is a featured artist or Co artist. But your request was to ignore this logic and move all artists apart from those matching the album artist(s) to the track title as if they were featured artists.

“artsits_index”, yes… That was my typo :slight_smile:

The _index bit makes sense, thanks for explaining that.

Sorry for the confusion - it wasn’t my intent to disregard the distinction between a featured artist and a co-artist; my intention was just to get that info out of the Artist field, and into the Title field.

As I wrote in the first post:

Dance Alone (ft Kylie Minogue) is ok, (though inaccurate in this case, so, no)
Dance Alone (co-performed with Kylie Minogue) seems a bit too wordy.
Dance Alone (with Kylie Minogue) sounds too much like it’s a ‘featuring’ relationship, minimizing her involvement. But maybe that’s ok, since it’s not default behavior, and the tagger (me) is choosing to do it…

I would prefer to preserve the distinction if I can.

If the data is available, I’d probably write something that would produce output options such as the following (assuming the data led to these outcomes):

  • Immortal Queen (ft. Chaka Khan)
  • Dance Alone (with Kylie Minogue)
  • Fake Song (with Kylie Minogue; ft. Chaka Khan)
  • Other Fake Song (with Kylie Minogue and Madonna; ft. Chaka Khan and Chris Martin)
  • SuperGroup Song (with Kylie Minogue, Jewel, and Madonna; ft. Chaka Khan, Kid Rock, and Chris Martin)

Getting really crazy there, but I think that would handle all cases that are possible - I’d probably opt for the serial comma even though it seems to be out of vogue, because it is more clear than omitting it (IMO) when faced with Artists like “Simon and Garfunkel”.

In one of the other posts above, I’d written:

This snippet assumes that there is a concept of a multi-valued “TrackArtists” (seems a fair guess) which includes all artists who worked on the track, including an indication of whether they were ‘featured’ or should receive “co-artist” billing. The “ListOfContributors” function would be responsible for figuring that all out. It could be defined by the user, or built-in.

So, all that said to say, yeah, I think this basically nails it. Where do I find the MusicBrainz artist credit field? is it already exposed as mb_artist_credits_index? And how is the join phrase presented? Is it embedded in the string containing the artist name? Or is it a separate value? (please, please, please let it be a separate value, like a 2d array, or another attribute, or something like that :smiley:)

I hope I’m not being a pain in the rear, here - not trying to be. I’m happy to write the JavaScript portion myself, too, if that’s any use. I just need to know where/how to find the data.

Are the fields available in the Scripter’s context documented anywhere yet? Or too soon?
Failing that, is there a mechanism by which you can log (to something - console? log file? etc) so that you can inspect the values found?

Is there a version of this I can play with, yet?

I just spent a few minutes digging into the MB API - I didn’t realize it was freely available. It looks like the way the joinphrase is handled may make my suggestion above non-trivial. It appears that each artist-credit gets a joinphrase that tells you how to connect to the next artist-credit rather than how the current artist should be connected to the entity (track, in this case).
https://musicbrainz.org/ws/2/release/b2f15f37-aaea-4dd4-bf12-820da0999cd8?inc=artist-credits+labels+discids+recordings&fmt=json

That offers some flexibility (they can add new joinphrases trivially) and it makes it easy to string them together like a sentence, but it makes it more difficult if you wanted to do things like, say, highlight featured artists in the UI with yellow, while highlighting primary and co-artists in green. It also explains why it has seemed somewhat random with regard to the choice between “&” and “and”.

Interesting.

TTFN

In my script im getting the track artists value from the artists field rather then the mb_artists, i.e using the artists field that was populated when the song was matched to MusicBrainz rather than just using the mb track artists directly. Now this is not neccessarily the same as the track artists linked to the track on MusicBrainz because affected by all these options:

  • When Tracks contain Featured Artists
  • Romanize non Latin Artist script artist names whenever possible
  • Use standard Artist name rather than name on cover
  • Use Recording Artist instead of Track Artist

And also some additional cleverness for classical albums that recognizes Track Artist and Recording Artist are intended for different things (composer/performers) on Classical and have to be treated specially.

Now we could use mb_tracks_artists instead but that would then mean we lose that logic, this maybe fine or you may need to code into the function. If you want to process the join phrases that is not stored in your songs fields seperately so you would have to use the mb variables. Please realize our mb variables are a different MB api to what you are looking at, only the original data is the same.

So my gut feeling is you are possibly making this too complex considering the problem you are trying to solve is playing whole albums on a limited car audio system. None of this is availble is yet, but it will be in the next release and then you then experiment yourself, hopefully be released within a couple of weeks.

I have extended script a little

if(albumartist!='' && albumartist!='Various Artists')
{
   artist=albumartist;
   var ft='';

   for (var index = 0; index < artists_index.length; index++) 
   {
      if(!artist.contains(artists_index[index]))
      {
         ft+=artists_index[index] + '; ';
      }
   } 
   if(ft.length>0)
   {
      ft=ft.substring(0, ft.length-2);
      if(mb_track_title.length()>0)
      {
         title=mb_track_title +' (Ft. ' + ft +')';
      }
      else if(discogs_title.length()>0)
      {
         title=discogs_title +' (Ft. ' + ft +')';
      }
   }

   artists=albumartists;
   artistsort=albumartistsort;
   artistssort=albumartistssort;
}

Script is now available as part of SongKong 11.0 Humbug released 11th October 2024

Sweet! I’ll be checking that out today!

Thanks

Hi Paul,
I went to test it on the album I mentioned at the start of this thread (Reasonable Woman, by Sia), and… I can’t duplicate the original behavior :slight_smile:

It appears that the data in MB still shows Kylie as a co-artist on track 3, but SK didn’t put it in the artist field.

After a little testing, it seems like maybe the “When tracks contains featured artists” drop down is affecting co-artists as well as featured artists. I’m pretty sure it didn’t before, in v 10.10 (hence the reason for this whole thread), but I haven’t figured out how to go back to the old version in my Docker software to test it.

With version 11.0, and the dropdown set to “Add all contributing artists to the artist field”, I see (using Jaikoz to view it):

With the dropdown set to “Only use main artist in the artist field and add others to the title field”, I see:

I’m not complaining; it seems to be doing exactly what I asked for (yay!), but I’m a bit confused how… I thought you were going to leave that drop down alone, and that I’d have to run the Scripter manually (at first, at least). I may just be confused - will reread the last few posts.

So, yeah… I said I couldn’t duplicate the original behavior… Of course, I can, if I change the dropdown. Once I do that, I can test the Scripter with the script you provided, and I get:

That is, it looks perfect. And same as the “new” behavior of the dropdown - as far as I’ve looked.

I’m gonna check another album - if I see anything odd, I’ll reply again.

Thanks!

Just ran a test on another album, and I did see something odd. There was a co-artist situation where the connecting word was “&” instead of “and”, and the selected dropdown value (#1 or #3) made no difference in the output of SK, but the Scripter script did move the the "&"ed artist to the title field.

It feels like there’s been a change to the behavior of the third dropdown option, but that it depends on the connector word being “and”. I’m assuming you’ll know what’s really going on :slight_smile:

Hi, okay the featured Artists functionality has not changed, but if you look at your chosen release on MusicBrainz

You can see the Track Artist is credit to Sia & Kylie Minogue, but the Recording Artist is credited to Sia and Kylie. The Featured Artist code treats artists as featured artists if the join phrase is not any of the following:

  • &
  • /
  • ,

so it would consider artist seperated by & to be co-artist, but if seperated by and it would be considered a featured artist (this maybe wrong but is how it worked before new version and how it still works)

So I think what has happed with your retest is either you enabled the Use Recording Artist instead of Track Artist option when before it was disabled. From the example above you might think that would then mean it would display Sia and Kylie rather than Sia and Kylie Minogue , but if you have the Use standard Artist name instead of name displayed on cover then SongKong will use Kylie Minogue rather than just Kylie.

image

Or you are now matching to a different version of the release that has the track artist as Sia and Kylie Minogue such as this one.

If you run Create Support Files I can clear this up for you definitively.

I have raised an issue so that and join phrase is treated the same as &, this will not help you particularly but is the correct way to go https://jthink.atlassian.net/browse/SONGKONG-2647

I did some testing, and confirmed that what you’ve written is exactly correct. I had been messing with the “Use Recording Artist instead of Track Artist” toggle.

When I first tested, I was looking at the wrong track (#2, “featuring Chaka Khan”, instead of #3, “and Kylie Minogue” - of course, as a “featuring” relationship, the Featured Artist dropdown selection I’d made was moving it from artist to Title), and I think that was when I tried changing the “Use Recording Artist instead of Track Artist” toggle, because I was confused as to why the behavior had changed (it hadn’t changed; I was looking at the wrong track!), and I guess once I figured out the track issue, I didn’t change the toggle back, and hence saw another “change” in behavior (which you’ve explained above.)

I just ran through some very methodical testing, and it’s clear now.

I’ve provided the support files in case you want to dig into this to satisfy your own curiosity, but the testing I’ve already done today satisfies my own.

Thanks!

1 Like