beetbox / beets

music library manager and MusicBrainz tagger
http://beets.io/
MIT License
12.57k stars 1.8k forks source link

Template function `%first` doesn't return the first item if the separator is `\0` #5230

Closed anjerukare closed 1 month ago

anjerukare commented 1 month ago

Hello :wave: and thanks for the great project!

I'm want to write configuration that makes track metadata compatible with id3v2.4. Specifically I'm trying to separate multiple artists in the albumartist and artist fields with \0.

In the metadata all is fine, but as for the paths, I can't simply keep the first artist and drop everything after \0. After localizing the problem, I concluded that template function %first doesn't return the first item if the separator is \0.

Problem

Running this command:

$ beet -vv import unorganized
Output ``` user configuration: /home/anjerukare/.config/beets/config.yaml data directory: /home/anjerukare/.config/beets plugin paths: Sending event: pluginload library database: /home/anjerukare/.config/beets/library.db library directory: /home/anjerukare/media/music Sending event: library_opened Sending event: import_begin Sending event: import_task_created Sending event: import_task_start Looking up: /home/anjerukare/media/unorganized/Get Lucky Tagging Daft Punk, Pharrell Williams, Nile Rodgers - Get Lucky No album ID found. Search terms: Daft Punk, Pharrell Williams, Nile Rodgers - Get Lucky Album might be VA: False spotify: Searching Spotify for 'album:Get Lucky artist:Daft Punk, Pharrell Williams, Nile Rodgers' spotify: Found 2 result(s) from Spotify for 'album:Get Lucky artist:Daft Punk, Pharrell Williams, Nile Rodgers' Extracting album ID from '2ePFIvZKMe8zefATp9ofFA' Extracting album ID from '4IjfJlYFVmkPH5WQdFuyS8' Sending event: albuminfo_received Candidate: Daft PunkPharrell WilliamsNile Rodgers - Get Lucky (Radio Edit) [feat. Pharrell Williams and Nile Rodgers] (2ePFIvZKMe8zefATp9ofFA) Computing track assignment... ...done. Success. Distance: 0.14 Sending event: albuminfo_received Candidate: Daft Punk - Get Lucky (Daft Punk Remix) (feat. Pharrell Williams & Nile Rodgers) (4IjfJlYFVmkPH5WQdFuyS8) Computing track assignment... ...done. Success. Distance: 0.27 Evaluating 2 candidates. /home/anjerukare/media/unorganized/Get Lucky (1 items) Sending event: import_task_before_choice Sending event: before_choose_candidate Match (85.7%): Daft PunkPharrell WilliamsNile Rodgers - Get Lucky (Radio Edit) [feat. Pharrell Williams and Nile Rodgers] ≠ year, album Spotify, None, 2013, None, Columbia, None, None https://open.spotify.com/album/2ePFIvZKMe8zefATp9ofFA ≠ Artist: Daft Punk, Pharrell Williams -> Daft PunkPharrell Williams Nile , Nile Rodgers Rodgers ≠ Album: Get Lucky -> Get Lucky (Radio Edit) [feat. Pharrell Williams and Nile Rodgers] ≠ (#0) Get Lucky (Radio Edit - (4:08) -> (#1) Get Lucky (Radio Edit) (4:08) feat. Pharrell Williams and [feat. Pharrell Williams and Nile Rodgers ) Nile Rodgers ] ➜ [A]pply, More candidates, Skip, Use as-is, as Tracks, Group albums, Enter search, enter Id, aBort? Sending event: import_task_choice Sending event: import_task_apply 0 of 1 items replaced Sending event: database_change Sending event: database_change Sending event: database_change Sending event: database_change Parsed query: AndQuery([NoneQuery('album_id', True)]) Parsed sort: NullSort() Parsed query: AndQuery([BooleanQuery('comp', 1, fast=True)]) Parsed sort: NullSort() Sending event: before_item_moved Sending event: item_moved Sending event: database_change Sending event: database_change Sending event: write Sending event: after_write Sending event: database_change Sending event: import_task_files Sending event: album_imported Sending event: import Sending event: cli_exit ```

Expected behavior

The file tree after import would be like this:

media/
└── music/
    └── Daft Punk/
        └── Get Lucky (Radio Edit) [feat. Pharrell Williams and Nile Rodgers]/
            └── 01 Get Lucky (Radio Edit) [feat. Pharrell Williams and Nile Rodgers].opus

Actual behavior

The file tree after import:

media/
└── music/
    └── Daft Punk_Pharrell Williams_Nile Rodgers/
        └── Get Lucky (Radio Edit) [feat. Pharrell Williams and Nile Rodgers]/
            └── 01 Get Lucky (Radio Edit) [feat. Pharrell Williams and Nile Rodgers].opus

Setup

I can't turn off spotify because musicbrainz is blocked in my country and I need at least one autotagger, can't turn off importreplace because I need that \0 replacement.

Info about the track I'm trying to import (output of beet info) is:

           album: Get Lucky
             art: False
          artist: Daft Punk, Pharrell Williams, Nile Rodgers
        bitdepth: 0
         bitrate: 132457
    bitrate_mode:
        channels: 2
        comments: https://www.youtube.com/watch?v=Rgrt_8mXrK8
         encoder: Lavf59.27.100
    encoder_info:
encoder_settings:
          format: Opus
        language: eng
       languages: eng
          length: 248.4135
      samplerate: 48000
           title: Get Lucky (Radio Edit - feat. Pharrell Williams and Nile Rodgers)
            year: 20160408

My configuration (output of beet config) is:

directory: ~/media/music

import:
  move: yes

plugins:
  - spotify
  - importreplace

musicbrainz:
  enabled: no

importreplace:
  replacements:
    - item_fields: artist artist_sort artist_credit
      album_fields: artist artist_sort artist_credit
      replace:
        ', ': '\0'

paths:
    default: '%first{$albumartist,1,0,\0}/$album%aunique{}/$track $title'
    singleton: 'Non-Album/%first{$artist,1,0,\0}/$title'

I also tried to use \x00, \u0000 and \␀ as the separator argument for the %first function but I couldn't get the expected behavior.

anjerukare commented 1 month ago

I solved the problem using the inline plugin.

Added the item_fields: section and edited the paths: section to the configuration listed above:

item_fields:
  first_albumartist: 'albumartist.split("\0")[0]'
  first_artist: 'artist.split("\0")[0]'

paths:
    default: $first_albumartist/$album%aunique{}/$track $title
    singleton: Non-Album/$first_artist/$title