-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Attachments
Here, we'll design the oft-requested attachments feature (see #111).
Upon import of audio files into the Beets library, users may wish to...
- Move the accompanying .log file into the same directory as the imported audio files.
- Move the accompanying .CUE file into the same directory as the imported audio files.
- Move album artwork associated with the audio files There could be multiple image files.
- Have the ability to move arbitrary files associated with the audio files, by way of a prompt questioning the user whether or not to import 'file-x.x' or by way of user declaration in an optional command, "include files of .xx".
- Declare a white list of file extensions they wish to import with the audio files.
- Get files by recursivley searching sub-directories
- Enable copy/move of Artist level images to corresponding Artist in beets structure, that is if pinkfloyd.jpg is present in the pink floyd artist folder move it to the pink floyd root level in the beets output
- Track the attachments in the database
- Query the database to see all albums with attachments and those without. ie. Find all albums without a .log file (so a user can re-rip those albums, for example).
- Move the attachments (should attachments be allowed to be stored anywhere other than the album folder, or can we think of an example in which the user would want to associate an attachment with an album that would need to be stored elsewhere?)
- Rename the attachments
- A configuration option to convert auto-downloaded image formats to the preferred format of the user (jpg/png) would allow for easy standardization in filetypes. (Does this feature belong in the attachments section?)
- Incorporate a log checker function to be able to see a list of all "100% Accurate Rip" Logs and those that aren't 100%.
- This becomes a small issue when renaming files. The log files will look for certain filenames and will score less than 100% because beets has renamed them. During discussion, it seems that the renaming is and should be the desired effect, and that the log file will have to stay the way it is, at less than 100.
- Convert cue sheets / log files to UTF-8.
- If a log or cue file is found, rename the file to $artist - $album.cue/log or other given variables names.
- If several images are present in the original folder, put them in an "artwork" directory in the new library folder (front.jpg, back.jpg, cd.jpg). This however, may cause an issue with media players that rely on an artwork file in the same directory as the files being played.
- Possibility to use the CUE file to split large FLAC files
- Possibility to detect which attachments are meant to exist and those that are clutter
Beets would need new functionality to cover the above use cases, this is a list of what Beets would need to do.
- Upon import, Beets would need to be able to analyse a folder and prompt the user that additional attachments exist.
- Beets would need to be able to offer options to the user when importing, ie. beets import --attachments=log,cue ...
- Include functionality so that Beets reviews the library filesystem and if attachments exist in folders (for example, users have manually copied these attachments over - common amongst users who use log files), that haven't been logged in the database, it should "import" them and associate them with the album in question.
- Include functionality so that existing attachments can be modified (renamed, moved(?), and queried/searched).
Here's a general way that the CLI could be organized. Please feel free to edit this as necessary, as it's very much a work in progress.
beet import --attachments=jpg,cue,log
A slight modification to the existing import function would be necessary, and would be largely preferred to using an attach command and doing everything manually. When importing normally, beets will also be scanning for files with extensions meeting those specified with the --attachments
flag. If they are found, then they would be attached to the album exactly as if they were run through the beet attach
command that follows.
beet attach [-cpel] ATTACHMENT QUERY
If ATTACHMENT is a file attach it to all the albums matching the supplied query. If ATTACHMENT is a directory attach each file contained in the directory or its subdirectories to the albums matching the query.
If the -l, --local
option is given it resolves ATTACHMENT relative to the albums’ base directory. This means that for any album matching the query the file $albumpath/ATTACHMENT
is attached to the album. Here $albumpath
is the path to the directory containing all the album tracks. It is currently also used by the coverart path.
All non-image files will be attached normally. In the case of an image file (jpg/png), beets will assume that they are some kind of artwork (front cover or otherwise), and then prompt the user to enter what kind of artwork they're supplying. We should support all the different image types that are defined by ID3v2. All artwork other than the front cover should be stored in an 'artwork' subdirectory in the album folder. The exception to this is artist images. ID3v2 has an 'artist image' specification, and if the user, when prompted, selects the 'artist' option, the file will be placed in the artist directory, above the album directory as 'artist.jpg'.
For cases other than artwork, we can account for a few of them. Common files would be .log
files and .cue
files. Beets can be on the lookout for these and rename as necessary (or as specified by user in config.yaml
).
-
-m
, Moves the given attachment instead of copying it from its source location. -
-p
, Pretend to attach everything, but don't actually modify anything. -
-e
, If the user at any point is picking what kind of artwork is being attached, and they select the front cover, if this option is enabled, that front artwork will automatically be embedded into the media files of that album.
beet coverart [-f FORMAT] [-n] [-t TYPE] QUERY
List the cover art attachments for albums or items matching QUERY
.
-
-f FORMAT
specifies a template string for the output similar to the list command. -
-t TYPE
restrict the output to images with the given cover art type.TYPE
is one of the names for ID3v2 cover art types. -
-n
inverts the result. It lists all albums or items matchingQUERY
that do not have a cover art attachment. If the type option is present it only shows the items that do not have a cover art attachment of typeTYPE
.
beet coverart [-le] -a IMAGE [-i | -t TYPE] QUERY
Attach the file IMAGE
to each album matching QUERY
and move it to the correct location. If IMAGE
is a directory, import all image files in that directory as cover art.
-
If the
-l
flag is present interpretIMAGE
as a path relative to the each albums directory. This is the same as for the attach command. -
With the
-i, --interactive
flag, the command interactively asks the user whether a file should be attached an what its type should be. -
-e, --embed
Write added cover art to tags.
joe@computer:~$ beet coverart -e -i -a /artwork/directory humbug
Attaching /artwork/directory/front.jpg. Please pick the appropriate artwork type:
front, back, leaflet, media, artist, during_recording, during_performance, artist_logo, other
Pick one: front
Embedding artwork into tags... success. 10 files embedded.
Attaching /artwork/directory/back.jpg. Please pick the appropriate artwork type:
front, back, leaflet, media, artist, during_recording, during_performance, artist_logo, other
Pick one: back
Embedding artwork into tags... success. 10 files embedded.
The location to store cover art may be customized by the configuration:
coverart:
store:
front: $albumpath/cover
back: $albumpath/cover-back
We also might want to give heuristics for mapping file names to types using regular expressions.
types:
"(front|cover|folder)": front
"back": back
Some modification to the beet list
function would also be necessary. Here is a suggested modification:
beet list --attachments QUERY
The extra --attachments
flag would let the list command know that we're looking for associated files to albums, rather than singletons/albums themselves. This would print a list of all albums meeting the query.
joe@computer:~$ beet list --attachments "arctic monkeys"
Found 2 entries which match supplied query.
1) Arctic Monkeys - Favourite Worst Nightmare
2) Arctic Monkeys - Humbug
Please specify which entry you'd like to see attachment data on:
The user then specifies which number entry they'd like to view the data on. They enter the corresponding number, and all attachment data is printed. The only issue I'm seeing with this is that inherently, the beet list
command does nothing other than list items, as it should. We do need some way to edit the attachments, so in this instance I've suggested that the command, after listing attachments, asks the user if they'd like to edit any of it. This may be a bad idea, or may be the only convenient way to do it. Not quite sure at this point.
Please specify which entry you'd like to see attachment data on: 2
Found 5 attachments.
1) folder.jpg (Front cover art, stored as "~/music/Arctic Monkeys/Humbug/folder.jpg")
2) back.jpg (Back cover art, stored as "~/music/Arctic Monkeys/Humbug/artwork/back.jpg")
3) artist_logo.jpg (Artist logo, stored as "~/music/Arctic Monkeys/Humbug/artwork/logo.jpg")
4) artist.jpg (Artist/band image, stored as "~/music/Arctic Monkeys/artist.jpg")
5) Humbug.log (Ripping log, stored as "~/music/Arctic Monkeys/Humbug/Humbug.log")
Would you like to edit any attachment data? (y/N): y
Please specify an attachment number to edit (or q to quit): 1
Selected front cover art (folder.jpg, ~/music/Arctic Monkeys/Humbug/folder.jpg"). What would you like to do?
rename, move, convert, type, un-attach, delete
Pick one: rename
Pick a new name for "folder.jpg": artwork.jpg
Renamed "folder.jpg" to "artwork.jpg" (~/music/Arctic Monkeys/Humbug/artwork.jpg").
Would you like to return to the attachments list? (Y/n): Y
Found 5 attachments.
1) artwork.jpg (Front cover art, stored as "~/music/Arctic Monkeys/Humbug/artwork.jpg")
2) back.jpg (Back cover art, stored as "~/music/Arctic Monkeys/Humbug/artwork/back.jpg")
3) artist_logo.jpg (Artist logo, stored as "~/music/Arctic Monkeys/Humbug/artwork/logo.jpg")
4) artist.jpg (Artist/band image, stored as "~/music/Arctic Monkeys/artist.jpg")
5) Humbug.log (Ripping log, stored as "~/music/Arctic Monkeys/Humbug/Humbug.log")
Please specify an attachment number to edit (or q to quit): q
joe@computer:~$
Similar to tracks, each attachment has a default path. This path is configurable through templates depending on the attachment type.
The following configuration example introduces the main features for configuring the paths. They are explained in detail below.
attachments:
paths:
# Default if nothing else matches
- "${entity_prefix}${basename}"
# Different templates depending on entity type
- type: riplog
# Path is relative to ${album_dir}.
path: rip.log
- type: riplog
ref_type: track
path: "${track_base}.log"
# Use flexible attributes
- type: coverart
path: "cover-${covertype}.${ext}"
- type: coverart
covertype: front
path: "cover.${ext}"
# For albums: 'albumpath/Album Artist - Album Name.jpg'
# For tracks: 'track/path/without/ext.jpg'
- type: froncover
ext: .jpg
# Path relative to the `directory` configuration
- type: cuesheet
path: "${libdir}/cuesheets/${ref}.cue"
The attachments.paths
configuration is a list of path specifications.
Each path specification includes a path template in the path
or ext
values. The remaining key-value pairs give a query to match against the
attachment. We use the path template of the last query to match. Note
that the query requires an exact match, that is type: cover
does not
match an attachment with type coverart
.
If a path specification is just a string it is assumed to match all attachments and the string is treated as the template.
All attributes and flexible attributes of an attachment and its entity are available as template variables. If there is an attribute of the same name on both the attachment and its entity, the former takes precedence.
In addition we have the following useful variables.
-
$entity_prefix
. For album attachments this is the album directory ($entity_dir
). For tracks this is"${track_base} - "
. depending on the reference type. -
$entity_dir
. The album directory or the directory containing the singleton track. The directory includes a trailing slash. -
$ext_prefix
. For album attachments this is"${entity_dir}/${albumartist} - ${album}"
. For track attachments it is$track_base
. -
$track_base
. The track path without its extension. -
$libdir
. The value of thedirectory
configuration value.
If the template of the path
key evaluates to a relative path it is
prepended with entity_prefix
template variable. If the path template
is taken from the ext
key it is instead preprended to the
ext_prefix
variable. Note that paths that are inside the beets
directory are stored as relative to the beets directory.