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

Album merging/completion #112

Closed
ghost opened this issue Feb 28, 2013 · 38 comments
Closed

Album merging/completion #112

ghost opened this issue Feb 28, 2013 · 38 comments
Labels
feature features we would like to implement migrated Issue migrated from Google Code

Comments

@ghost
Copy link

ghost commented Feb 28, 2013

This issue was automatically migrated from Google Code.
Original author: zent...@gmail.com (April 29, 2012 18:26:17)
Original issue: google-code-export/beets#380

sampsyo referenced this issue May 11, 2013
Since both albums and items have an itime field, I'm putting itime into
ALBUM_KEYS_ITEM. This simplifies a lot of handling code. It also will make the
item and album itimes synchronize at some points, which is probably fine -- I
can't see a major use case for maintaining separate added dates for an album
and its tracks.
@adius
Copy link

adius commented Mar 25, 2014

+1
Probably the most important missing feature!

@udiboy1209
Copy link
Contributor

This feature could be included as an option in the "duplicate album" prompt, alongside "Skip New","Keep Both" and "Remove Old" - a new option called "Merge".

The merge can be done by setting the album_id for each of the tracks being imported to the id of the existing album, putting those tracks in the database, and not adding another album entry. One would have to provide a way to resolve conflicts such as duplicate tracks, conflicting mb_albumid value, etc. but I think this is possible.

@sampsyo are there any obvious problems with this approach? If not I can start making this...:exclamation:

@sampsyo
Copy link
Member

sampsyo commented May 20, 2014

Yes, this sounds exactly right! Good plan, @udiboy1209. ✨

Just to be clear: the combined album should probably be re-tagged as a unit. That will (hopefully) resolve all the problems with conflicting information using the autotagger. The "as tracks" and "as albums" options show how this sort of thing can be done by creating a temporary pipeline.

@udiboy1209
Copy link
Contributor

This seems more complicated than I thought. Maybe because I am new to beets' internals.

Re-tagging the whole album altogether again is a good idea! But what would you do if autotagging is disabled?

@sampsyo
Copy link
Member

sampsyo commented May 21, 2014

Yep, it is a bit of a large project... let me know if you have questions about the architecture.

Fortunately, in non-autotagged mode, we don't do duplicate detection either, so this will never come up.

@udiboy1209
Copy link
Contributor

Sorry to be replying after such a long time! I was busy with something else!

So I have a few questions.

I added two functions to ImportTask class, one is

    def merge_with_duplicate(self,lib):
        existing_album = self.find_duplicates(lib)[0]
        if self.merge_conflicts(existing_album):
            # Add existing album's items to current task to retag again
            # and remove the existing album
            self.items += existing_album.items()
            existing_album.remove()
        else:
            for item in self.items:
                item.album_id = existing_album.id
            self.set_choice(action.ASIS)

and the other is merge_conflicts which basically returns true if any conflicts arise with mb_albumid or duplicate tracks exist.

The question is that is is safe to put existing_albums.remove() here? Is it even the right way to do something like this?

this function will be called from a pipeline.stage function called merge_with_duplicate defined in importer.py

@sampsyo
Copy link
Member

sampsyo commented Jun 5, 2014

Awesome! This definitely looks like the right direction.

Your suspicion was correct, though: we need to avoid doing the remove() call in this stage (presumably this is called as soon as the user decides to merge, right?). The goal is to have all the database manipulation stuff performed atomically in the apply_changes stage. This way, if something goes wrong, we don't end up with a database containing zero of the parts of the albums: it should only be possible to end up in the "before" or "after" state, not in the middle.

As a template, you can see that the call to task.add() here:
https://github.com/sampsyo/beets/blob/master/beets/importer.py#L1039
atomically (inside a transaction) both removes old duplicate items, for re-imports, and adds the new items:
https://github.com/sampsyo/beets/blob/master/beets/importer.py#L536
I think this new feature could also work by just making sure that remove_replaced finds all the old pieces of the album. Note that by removing all the items from the old album, we automatically remove the album itself.

Thanks again for looking into this, @udiboy1209!

@udiboy1209
Copy link
Contributor

Hmm.. Letting remove_replaced remove the old items might work just by adding the old items to the current task. The duplicate paths will be detected automatically. But will it also remove the old album entry in the library? How is this handled when re-importing albums?

@sampsyo
Copy link
Member

sampsyo commented Jun 6, 2014

Yeah, hopefully we can reuse this existing functionality!

Fortunately, the library takes care of cleaning up "empty" albums when the last constituent item is removed. Here: https://github.com/sampsyo/beets/blob/master/beets/library.py#L464

So this should mostly happen automatically. The only exception I can think of is this edge case:

  • The library contains an album with tracks A, B, and C.
  • The user imports items D and E and wants to merge the album.
  • The auto-tagged recognizes this as a different album, but track A is not present on the new matched album (a partial match). The album only has B, C, D, and E.
  • Then we will remove tracks B and C as duplicates and add back B, C, D, and E as a new album.
    This results in track A being left alone in its own album with the remaining tracks getting a new album alongside it.

I think this case is edge-y enough to ignore. In any case, it is probably a good idea to leave A in the library to prevent unintentional data loss!

@sgoranson
Copy link

awesome software guys...greatly looking forward to this merge feature!

@vlsd
Copy link

vlsd commented Jun 16, 2014

I run into this quite a bit! It would also cool if the duplicates plugin offered a merge option as well.

@ghost
Copy link
Author

ghost commented Aug 18, 2014

+1 to this enhancement for beets

I have made quite a few mistakes using the ('Skip new', 'Keep both', 'Remove old') options at import time with mixed up albums and some files already in my library. It hasn't always been clear to me what is the best option to choose - perhaps just my stupidity or perhaps something other beets users have also found. In addition, I think I have deleted some files by mistake when doing import / clean up of existing files using "beet import -L" when using the 'Remove old' option.

I would like to see a new 'Details' option added. I think this could sit alongside the merge functions being described above? So the options would now be

('Skip new', 'Keep both', 'Remove old', 'Details')
Pushing 'D' for details would show the following output.

Skip will

  • ignore the 7 tracks in folder /Users/someuser/Downloads/Awesomesingers/First\ Album\ 320kbs
  • will retain the 4 tracks in folder /Users/someuser/beetMUSIC/Awesomesinger/DebutAlbum

and so on for 'Keep Both', 'Remove Old',

The user query would then be repeated at the end but would this time have a 'More Details' option which would give the user the option of repeating the above schema but this time with each individual /path/track listed.

Sorry if that seems overkill but would be good for import and clean up of some fragmented albums that i have following recovery of part of a hard disk.

@giodamelio
Copy link

👍 In the meantime, is there any work around to allow us to import a song to an existing album?

@sampsyo
Copy link
Member

sampsyo commented Aug 30, 2014

You can always remove and re-import!

@giodamelio
Copy link

Cool, Thanks.

@arthurlutz
Copy link

This feature would be awesome. Hope it ends up in beets at some point.

@dashed
Copy link
Contributor

dashed commented Nov 17, 2014

+1000. I think this is absolutely needed for the move configuration to be any useful.

@pedros
Copy link
Contributor

pedros commented May 25, 2015

Just came across this issue. This is addressed in 3be5936, at the duplicates plugin level (so, not within the importer). Might still be of use, though.

@bartkl
Copy link
Contributor

bartkl commented May 19, 2016

From what I'm reading I can imagine the `edit' plugin might come in handy in the process of (optionally?) applying some final tidying edits after the merge (if chosen) since this might have undesired consequences as far as the consistency of tags is concerned.

If that sounds useful to you guys it should probably become a new issue, but for now it's only a thought.

@nomadturk
Copy link

Any news on this?

I'ld like to see this feature on beets. This is a must-have kinda feature I think.
For example I have this partial album with tracks 1, 3, 7 and 8 but the rest are missing.
And let's say I have another partial album on an different directory with tracks 1, 2, 3, 4, 9, 10, 11.
Whilst importing if beets were to pickup the missing tracks (and maybe check for quality and replace the better one) then I'ld end up with 1, 2, 3, 4, 7, 8, 9, 10, 11.
Now tracks 5 and 6 seem to be still missing but that would be OK. This still is better than having less.

Currently if I have even 1 track beets skip it saying I already have the album. So maybe adding an Import Missing tracks feature would be wise as well.

@sampsyo
Copy link
Member

sampsyo commented Jun 8, 2016

If you're interested in a feature, please consider helping implement it!

@sean-abbott
Copy link

Also, with regard to @nomadturk's comment:

Let's say that an album is supposed to have 6 tracks.
If I have 1, 3, and 5 currently, and I import 4, 5, and 6, then a resolution needs to do two things.

First, it has to merge the tracks that only exist in one or the other sets, so 1, 3, 4, and 6, I DEFINITELY want to keep.

After that, though, I'd want to compare 5. Are they different bit rates? Is one a better musicbrainz match? Different lengths?

So I'd want merge resolution to be two stage: union the album as a whole, and then deal with duplicate tracks individually.

@sampsyo
Copy link
Member

sampsyo commented Feb 2, 2017

The way this would work according to the current proposal is to reuse the existing importer logic. That means both sets of tracks would get thrown together into one big basket, and that would then be re-tagged as the same album.

If you have duplicate tracks, then the "best" one will be picked according to match similarity. Interactively resolving track duplicates would be the purview of something like #154.

@sean-abbott
Copy link

Personally, I'd rather NOT automate the "best" pick...

And edit, a la #154 is not the goal...being able to make a track-by-track-non edit comparison and choose one, the other, or both is preferable.

@sampsyo
Copy link
Member

sampsyo commented Feb 2, 2017

Right. I'm just saying that manually choosing resolutions like this is actually orthogonal: it can come up in ordinary imports too if you happen to have too many tracks in a folder.

We actually have the "edit option" for editing metadata. (See the edit plugin.) The reason I bring up #154 is because the original intention there was changing the order (i.e., the matching) of tracks, which would also require dealing with unmatched/duplicate tracks.

@sean-abbott
Copy link

Gotcha, ok.

@0xE0-rng
Copy link

0xE0-rng commented Apr 3, 2017

Hi, has any progess been made on this feature? I would be willing to help/implement it, but i dont want to do duplicate work or step on any toes. Thanks in advance

@udiboy1209
Copy link
Contributor

I had tried a few things, but none were particularly useful. Also it was three years ago and the codebase may have changed a lot since then... So you start afresh for this feature.

@intelfx
Copy link
Contributor

intelfx commented Nov 11, 2017

Incredible! Looks like I can get back to using beets (something I'm very glad to be able to).

@dosoe
Copy link
Contributor

dosoe commented Mar 8, 2018

I'm wondering: how about release groups? They also appear in MusicBrainz and group albums that are basically reissues of one another (stuff like Harmonia Mundi Gold). Could it be possible to extend what has just been implemented with releases to release groups? In many cases you do not want to have a duplicate of the music just because one is the original version of 1987 and the other one is the reissue of 2010 because now it is a legendary recording or because one wants to make money again with it (I'm throwing numbers at random, but there are countless examples). Some people might prefer to keep them separate for the sake of completeness, but I believe this is a minority. So far what I did was to use beet dup and set the mb_releasegroupid as a key but it is not very satisfying because the album gets sometimes cut into two complementary folders. I don't know if it is a problem many people experience, but it seems to be quite similar to merging albums.

@dosoe
Copy link
Contributor

dosoe commented Mar 8, 2018

And thanks for the awesome work!

@mkirkland4874
Copy link

With “merge all”, it appears that if you attempt to import a song that is already in the album you are merging, beets will rename the song to a totally different song randomly and incorrectly. You will think you have a song when in fact it is a duplicate of another song.

For example:

Step 1: Import Track 01 and 02 of Album A (which has 5 songs total). Beets imports the two songs into one album correctly.
Step 2: Import Track 03 of Album A. Beets offers you the “merge all” option to combine with the 2 songs imported in Step 1. Beets correctly imports Track 03 and combines it into Album A created in Step 1. There are now 3 of 5 songs of Album A in the library.
Step 3: Import Tracks 03 and 04 (note 03 is already in the library and 04 is new). Beets offers you the “merge all” option. You select “merge all” and beets renames the Track 03 you are importing to Track 05 incorrectly and imports track 04 correctly. Now beets thinks you have a complete Album of all 5 songs in Album A, when in fact songs 03 and 05 are the same song.

@sampsyo
Copy link
Member

sampsyo commented Sep 18, 2018

Indeed; the current feature combines the tracks; it does not try to deduplicate them.

@laker-93
Copy link

Is this issue really closed? I still don't see a way to merge albums in to a single directory. beet duplicates --merge won't work unless there are duplicates but you can end up in a following scenario where there are no duplicates but beets has decided to put tracks in to different directories (due to importing the album piecemeal)

root@4787cef4963b:/# beet ls Skee -p
/music/Skee Mask/C [111]/07 - Minitx.mp3
/music/Skee Mask/C [112]/09 - Blok.mp3
/music/Skee Mask/C [110]/10 - Pitchacid.mp3
/music/Skee Mask/C [111]/11 - thnk u.mp3

Is there a command to merge these all in to the same album?

@JOJ0
Copy link
Member

JOJ0 commented Dec 18, 2024

@laker-93 You can try reimporting by passing the paths to the files to the import command, then select the same album each time and select the appropriate merge option.

merge has to be enabled in the config of course

https://beets.readthedocs.io/en/latest/reference/config.html#id112

might also be useful: https://beets.readthedocs.io/en/latest/reference/config.html#id113

I think your particular case can be solved but situations with duplicates still can't be solved with the current implementation. Eg: #112 (comment)

Is there no issue open for it yet? We could create one out of the referenced post.

@laker-93
Copy link

@JOJ0 - thanks for the information. I think that would indeed work for my use case. Another thought is that this could be solvable as a one liner using the duplicates plugin. If I execute beet duplicates -a in my above situation, it would print out Skee Mask - C as it has detected the duplicate at the album level. If one could put the duplicates plugin in 'album mode' and then instruct it to merge, with for example beet duplicates -a --merge, then that would solve my use case without having to fiddle around with reconfiguring duplicate_action. Does this sound reasonable? If so, I'd be willing to look at implementing such a feature.

@laker-93
Copy link

What I'm trying to achieve here is to import the tracks piecemeal and end up with all tracks being placed in a common directory:
/music/Skee Mask/C/

An alternative perhaps simpler solution is to set the album id of all tracks to the same with something like:

beet mod album_id=<album-id>

however doing so would then change the path of all tracks to:

/music/Skee Mask/C [album-id]/

which is still not ideal!

@laker-93
Copy link

I've just removed the aunique disambiguator from the path format which seems to have solved my use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature features we would like to implement migrated Issue migrated from Google Code
Projects
None yet
Development

No branches or pull requests