Alice ( - Song feat. Bob)
directory: /library
id3v23: no
# --------------- Main ---------------
library: /config/library.db
original_date: yes
# --------------- Paths ---------------
path_sep_replace: "⧸"
# --------------- Tagging ---------------
per_disc_numbering: yes
# --------------- Performance ---------------
threaded: yes
# --------------- Plugins ---------------
plugins:
- albumtypes
- beatport4
- bucket
- chroma
- discogs
- embedart
- fetchart
- filetote
- fromfilename
- ftintitle
- importadded
- importreplace
- info
- inline
- lastgenre
- lyrics
- musicbrainz
- permissions
- replaygain
- rewrite
- scrub
- tidal
- the
- web
- zero
album_fields:
is_music: "token = None\nvalid_libs = ['Christmas', 'Comedy', 'Field', 'Halloween', 'Kids', 'Music']\ntry:\n token = 1 if library.title() == 'Music' else 0\nexcept NameError:\n raise Exception(f\"You must specify a library using --set library=<library>\\nAvailable libraries: {valid_libs}\")\nreturn token\n"
cat_token: "token = ''\nblacklist = ['none', '[none]', 'n/a', '-']\ncatnum = catalognum if catalognum.lower() not in blacklist else ''\nif len(catnum) > 0:\n token += ' {' + catnum + '}'\nreturn token\n"
label_token: "token = ''\nblacklist = ['none', '[none]', 'n/a', '-']\nlbl = label if label.lower() not in blacklist else ''\ncatnum = catalognum if catalognum.lower() not in blacklist else ''\nif len(lbl) + len(catnum) > 0:\n token += ' {'\n if len(lbl) > 0:\n token += lbl\n if len(catnum) > 0:\n token += ', '\n if len(catnum) > 0:\n token += catnum\n token += '}'\nreturn token\n"
library_token: "token = None\nvalid_libs = ['Christmas', 'Comedy', 'Field', 'Halloween', 'Kids', 'Music']\ntry:\n if library.title() in valid_libs:\n token = library.title()\nexcept NameError:\n raise Exception(f\"You must specify a library using --set library=<library>\\nAvailable libraries: {valid_libs}\")\nreturn token\n"
media_token: "media_map = {\n 'Cassette': 'CAS',\n 'Vinyl': 'VNL',\n 'Blu-ray': 'BR',\n 'DVD-Audio': 'DVD',\n 'DVD-Video': 'DVD',\n 'Digital Media': 'WEB',\n 'Digital': 'WEB',\n 'File': 'WEB',\n}\n\nmedias_unsorted = []\nfor item in items:\n m = media_map.get(item.media, item.media)\n if m is None or len(m.strip()) < 1:\n m = 'WEB'\n if m not in medias_unsorted:\n medias_unsorted.append(m)\n\nmedia_sort_order = ['SACD', 'CD', 'CAS', 'VNL', 'BR', 'DVD', 'USB', 'WEB']\nmedias = []\nfor value in media_sort_order:\n if value in medias_unsorted:\n medias.append(medias_unsorted.pop(medias_unsorted.index(value)))\n\nif len(medias) > 0:\n return '+'.join(medias)\n\nif len(medias_unsorted) > 0:\n return '+'.join(medias_unsorted)\n\nreturn 'WEB'\n"
format_token: "formats_unsorted = []\nfor item in items:\n if item.format not in formats_unsorted:\n formats_unsorted.append(item.format)\nformat_sort_order = ['TRUEHD', 'DTS', 'FLAC', 'ALAC', 'APE', 'WAVPACK', 'WAV', 'OGG', 'AAC', 'MP3', 'WMA']\nformat_codecs = []\nfor fso in format_sort_order:\n if fso in formats_unsorted:\n format_codecs.append(fso)\nlossless_formats = ['TRUEHD', 'FLAC', 'ALAC', 'APE', 'WAVPACK', 'WAV']\nformats = []\nfor format in format_codecs:\n if format in lossless_formats:\n fmt_bitdepth = 0\n fmt_samplerate = 0\n item_count = 0\n fmt_maxchannels = 0\n for item in list(filter(lambda i: i.format == format, items)):\n item_count += 1\n fmt_maxchannels = max(fmt_maxchannels, item.channels)\n fmt_bitdepth += item.bitdepth\n fmt_samplerate += item.samplerate\n if item_count > 0:\n fmt_bitdepth = round(fmt_bitdepth / item_count)\n fmt_samplerate = round(fmt_samplerate / item_count / 1000)\n channel_token = ''\n if fmt_maxchannels > 2:\n channel_value = f'{fmt_maxchannels}.0';\n if fmt_maxchannels == 6:\n channel_value = '5.1'\n elif fmt_maxchannels == 8:\n channel_value = '7.1'\n channel_token = f' {channel_value}'\n ftoken = f' {format}{channel_token} {fmt_bitdepth}-{fmt_samplerate}'\n formats.append(ftoken)\n else:\n fmt_avgbitrate = 0\n item_count = 0\n fmt_maxchannels = 0\n for item in list(filter(lambda i: i.format == format, items)):\n item_count += 1\n fmt_maxchannels = max(fmt_maxchannels, item.channels)\n fmt_avgbitrate += item.bitrate\n if item_count > 0:\n fmt_avgbitrate = round(fmt_avgbitrate / item_count / 1000)\n channel_token = ''\n if fmt_maxchannels > 2:\n channel_value = f'{fmt_maxchannels}.0';\n if fmt_maxchannels == 6:\n channel_value = '5.1'\n elif fmt_maxchannels == 8:\n channel_value = '7.1'\n channel_token = f' {channel_value}'\n ftoken = f' {format}{channel_token} {fmt_avgbitrate}'\n formats.append(ftoken)\nreturn ','.join(formats)\n"
albumdisambig_token: '# leaving logic in case we want to put it behind a flag later
#return '''' if not albumdisambig else f" ({albumdisambig.title()})"
return ''''
'
albumtypes:
types:
- ep: ' EP'
- single: ' (Single)'
- soundtrack: ' OST'
- compilation: ' (Anthology)'
ignore_va: compilation
bracket: ''
beatport4:
art: yes
art_overwrite: no
art_width: 2160
data_source_mismatch_penalty: 0.3
search_limit: 5
username: REDACTED
password: REDACTED
tokenfile: beatport_token.json
client_id:
art_height:
singletons_with_album_metadata:
enabled: no
year: yes
album: yes
label: yes
catalognum: yes
albumartist: yes
track_number: yes
bucket:
bucket_alpha:
- '# - D'
- E - L
- M - R
- S - Z
bucket_alpha_regex:
'# - D': "^[!-\\/0-9:-@A-Da-d¡¢¤©ª«¬²-¿À-Çà-çÐλ]"
E - L: "^[E-Le-lÈ-Ïè-ï£]"
M - R: "^[M-Rm-rÑ-Öñ-öØœ®°μ]"
S - Z: "^[S-Zs-zŠšŽžŸù-ýÿ¥§]"
bucket_year: []
extrapolate: no
chroma:
auto: yes
search_limit: 5
data_source_mismatch_penalty: 0.5
# --------------- Import ---------------
clutter:
- '*.cue'
- '*.doc'
- '*.m3u'
- '*.m3u8'
- '*.par'
- '*.par2'
- '*.pls'
- '*.rtf'
- '*.sfv'
- '*.srr'
- '*.txt'
- .DS_Store
- proof.*
- Thumbs.DB
discogs:
data_source_mismatch_penalty: 0.2
featured_string: ft.
search_limit: 5
search_query_ascii: no
apikey: REDACTED
apisecret: REDACTED
tokenfile: discogs_token.json
user_token: REDACTED
separator: ', '
index_tracks: no
append_style_genre: no
strip_disambiguation: yes
extra_tags: []
anv:
artist_credit: yes
artist: no
album_artist: no
embedart:
auto: yes
maxwidth: 2160
minwidth: 2160
quality: 90
remove_art_file: no
compare_threshold: 0
ifempty: no
clearart_on_import: no
fetchart:
auto: yes
enforce_ratio: yes
fanarttv_key: REDACTED
high_resolution: yes
lastfm_key: REDACTED
max_filesize: 20000000
maxwidth: 2160
minwidth: 2160
quality: 90
sources:
- coverart: release
- itunes
- coverart: releasegroup
- amazon
- albumart
- lastfm
- fanarttv
- filesystem
store_source: yes
cautious: no
cover_names:
- cover
- front
- art
- album
- folder
fallback:
deinterlace: no
cover_format:
google_key: REDACTED
google_engine: REDACTED
filetote:
exclude:
filenames:
- album.jpeg
- album.jpg
- album.png
- cover.jpeg
- cover.jpg
- cover.png
- folder.jpeg
- folder.jpg
- folder.png
- front.jpeg
- front.jpg
- front.png
extensions: ''
patterns: {}
extensions: .diz .jpeg .jpg .log .nfo .pdf .png .srr .txt
paths:
ext:.diz: $albumpath/$subpath$old_filename
ext:.log: $albumpath/$subpath$old_filename
ext:.nfo: $albumpath/$subpath$old_filename
ext:.pdf: $albumpath/$subpath$old_filename
ext:.srr: $albumpath/$subpath$old_filename
ext:.txt: $albumpath/$subpath$old_filename
pattern:artworkdir: $albumpath/$subpath$old_filename
patterns:
artworkdir: ['**/[sS]can*/']
session:
operation:
_beets_lib:
_library_path:
import_path:
filenames: ''
pairing:
enabled: no
pairing_only: no
extensions: .*
print_ignored: no
duplicate_action: merge
ftintitle:
format: ft. {0}
auto: yes
drop: no
keep_in_artist: no
preserve_album_artist: yes
custom_words: []
bracket_keywords:
- abridged
- acapella
- club
- demo
- edit
- edition
- extended
- instrumental
- live
- mix
- radio
- release
- remaster
- remastered
- remix
- rmx
- unabridged
- unreleased
- version
- vip
import:
default_action: none
detail: no
duplicate_action: ask
duplicate_verbose_prompt: yes
incremental: no
incremental_skip_later: no
languages: en
log: /config/beets.log
timid: yes
quiet: no
write: yes
copy: no
move: yes
importreplace:
replacements:
- item_fields: artist artist_sort artist_credit albumartist albumartist_sort albumartist_credit
album_fields: artist artist_sort artist_credit albumartist albumartist_sort albumartist_credit
replace:
'[\u2010-\u2015]': '-'
'[\u2018-\u201B]': ''''
'[\u201C-\u201F]': '"'
- item_fields: title album
album_fields: album
replace:
'[\u2010-\u2015]': '-'
'[\u2018-\u201B]': ''''
'[\u201C-\u201F]': '"'
(?i)\bRMX\b: Remix
(?i)\bRemix\b: Remix
- item_fields: album
album_fields: album
replace:
(?i)\s+EP$: ''
(?i)\s*\(\s*(?=[^)]*(?:Sound\s*track|Score|Songs|Music\s+From|Motion\s+Picture))[^)]*\s*\): ''
- item_fields: albumdisambig
album_fields: albumdisambig
replace:
(?i)\d\d[\s-]?Bit: ''
(?i)\d\d[\s-]?kHz: ''
\s+$: ''
^\s+: ''
\b\s+\b: ' '
\s*,\s*\/?\s*$: ''
^\s*\/?\s*,\s*: ''
- item_fields: label catalognum
album_fields: label catalognum
replace:
'[\u2010-\u2015]': '-'
'[\u2018-\u201B]': ''''
'[\u201C-\u201F]': '"'
(?i)^none$: ''
(?i)^\[none\]$: ''
(?i)^n/a$: ''
^-$: ''
- item_fields: label
album_fields: label
replace:
\u00A9\s+(?:'\d{2}|\d{4})\s*: ''
(?i)\(C\)\s+(?:'\d{2}|\d{4})\s+\s*: ''
(?<=\bRecords\b).*$: ''
(?<=\bLtd\b).*$: ''
(?<=\bLtd\.\b).*$: ''
- item_fields: media
album_fields: media
replace:
'\d+" ': ''
item_fields:
disctitle_token: "if disctotal > 1:\n disctitle_token = f'CD{str(disc).zfill(len(str(disctotal)))}'\n if disctitle not in (album, ''):\n disctitle_token += f' - {disctitle}'\n return disctitle_token\nelse:\n return ''\n"
track_token: "disc_token = ''\nif disctotal > 1:\n disc_token = f'{str(disc).zfill(len(str(disctotal)))}-'\ntrack_token = str(track).zfill(max(len(str(tracktotal)) if tracktotal else 0, 2))\ntoken = f'{disc_token}{track_token}. {artist} - {title}'\nreturn token\n"
lastgenre:
canonical: /config/genre-tree.yaml
min_weight: 50
prefer_specific: yes
source: album
whitelist: /config/genre-whitelist.txt
count: 1
fallback:
cleanup_existing: no
force: no
keep_existing: no
auto: yes
title_case: yes
pretend: no
ignorelist: {}
lyrics:
force: yes
google_API_key: REDACTED
sources: [lrclib, google]
synced: yes
auto: yes
auto_ignore:
translate:
api_key: REDACTED
from_languages: []
to_language:
dist_thresh: 0.11
google_engine_ID: REDACTED
genius_api_key: REDACTED
fallback:
keep_synced: no
local: no
print: no
match:
ignored_media:
- Data CD
- DVD
- DVD-Video
- VCD
- SVCD
- UMD
- VHS
strong_rec_thresh: 0.2
medium_rec_thresh: 0.33
max_rec:
missing_tracks: medium
unmatched_tracks: medium
year: medium
musicbrainz:
host: 172.18.0.20:5000
https: no
ratelimit: 100
extra_tags:
- barcode
- catalognum
- country
- label
- media
- year
search_limit: 5
data_source_mismatch_penalty: 0.0
external_ids:
discogs: yes
spotify: yes
bandcamp: yes
beatport: yes
deezer: yes
tidal: yes
search_query_ascii: no
genres: no
genres_tag: genre
paths:
default: $library_token/%if{$is_music,%bucket{%the{$albumartist},alpha}/}%the{$albumartist}/$year-$month-$day - $album$atypes$albumdisambig_token$label_token%if{$media_token$format_token, [%if{$media_token,$media_token}%if{$format_token,$format_token}]}/%if{$multidisc,$disctitle_token/}$track_token
singleton: $library_token/%if{$is_music,%bucket{%the{$albumartist},alpha}/}%the{$albumartist}/$year-$month-$day - $title$atypes$albumdisambig_token$label_token%if{$media_token$format_token, [%if{$media_token,$media_token}%if{$format_token,$format_token}]}/%if{$multidisc,$disctitle_token/}$track_token
albumtype:soundtrack: $library_token/Soundtracks/%the{$albumartist} - %the{$album}$atypes$albumdisambig_token ($year)$label_token%if{$media_token$format_token, [%if{$media_token,$media_token}%if{$format_token,$format_token}]}/%if{$multidisc,$disctitle_token/}$track_token
comp: $library_token/VA/%the{$label}/$year-$month-$day - $album$atypes$albumdisambig_token$cat_token%if{$media_token$format_token, [%if{$media_token,$media_token}%if{$format_token,$format_token}]}/%if{$multidisc,$disctitle_token/}$track_token
permissions:
file: 660
dir: 770
replace:
/: "⧸"
\\: "⧹"
\?: "?"
':': "∶"
\.\.\.: "…"
^\.: ''
<: "‹"
'>': "›"
\*: "✱"
\|: "|"
'[\x00-\x1F]': ''
\.$: ''
\s+$: ''
'"': """
'[\u2010-\u2015]': '-'
'[\u2018-\u2019]': ''''
"‛": ''''
"′": ''''
'[\u201C-\u201D]': """
"‟": """
"″": """
'[\uFE4D-\uFE4F]': _
"_": _
replaygain:
backend: ffmpeg
overwrite: no
auto: yes
threads: 32
parallel_on_import: no
per_disc: no
peak: 'true'
targetlevel: 89
r128: [Opus]
r128_targetlevel: 84
scrub:
auto: yes
tidal:
client_id: REDACTED
data_source_mismatch_penalty: 0.5
search_limit: 5
tokenfile: tidal_token.json
web:
host: 0.0.0.0
port: 8337
cors: ''
cors_supports_credentials: no
reverse_proxy: no
include_paths: no
readonly: yes
zero:
auto: yes
update_database: yes
fields: mb_albumartistid mb_albumartistids mb_albumid mb_artistid mb_artistids mb_releasegroupid mb_releasetrackid mb_trackid mb_workid
mb_albumartistid: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_albumartistids: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_albumid: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_artistid: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_artistids: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_releasegroupid: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_releasetrackid: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_trackid: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
mb_workid: ['^(?![0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}).*$']
keep_fields: []
omit_single_disc: no
disabled_plugins: []
importadded:
preserve_mtimes: no
preserve_write_mtimes: no
pathfields: {}
rewrite: {}
the:
the: yes
a: yes
format: '{}, {}'
strip: no
patterns: []
Problem
In the
ftintitleplugin, parenthetical features are split at the feature token but surrounding delimiters are left behind on both sides.For example:
becomes:
Setup
My configuration (output of
beet config) is: