Coder Social home page Coder Social logo

beetspluginbpmanalyser's Introduction

Test & Release & Deploy PyPi PyPI pyversions MIT license

BPM Analyser (Beets Plugin)

The beets-bpmanalyser plugin lets you analyse the tempo of the songs you have in your library and write the bpm information on the bpm tag of your media files.

This plugin has a more powerful big brother which does much more than just extracting bpm: beets-xtractor plugin.

Installation

The plugin can be installed via:

pip install beets-bpmanalyser

It has three dependencies: numpy, aubio and pydub all of which are installed automatically when installing the plugin itself. Pydub is a wrapper library around ffmpeg or libav which are used to convert audio files to a temporary non-compressed (wav) version before running the aubio analysis on the song.

Usage

Activate the plugin in your configuration file:

plugins:
  - bpmanalyser
  # [...]

Check if plugin is loaded with beet version. It should list 'bpmanalyser' amongst the loaded plugins.

Your default configuration is:

bpmanalyser:
  auto: no
  dry-run: no
  write: yes
  threads: "AUTO"
  force: no
  quiet: no

By setting the auto option to yes, the plugin will be run automatically on each new item during import.

The other configuration options can also be set from the command line when running the plugin. Here are the options explained:

-d, --dry-run : Do not update the library or the media files. Only display the bpm values.

-f, --force : By default only songs with no bpm value (bpm:0) are analysed. Use this option to force the analysis regardless of the current bpm value.

-w, --write : Write the bpm values directly to the media files.

-t THREADS, --threads=THREADS: Set the number of processes to run in parallel. By default it is set to AUTO (threads: AUTO) and it will use half of the number of cores of your processor(s) have. You can set this to any number to specify how many concurrent threads you want to run.

-q, --quiet : Do not display any output from the command.

-v, --version : Displays the version number of the plugin.

Examples:

Calculate but show only (do not store) tempo information on all AC/DC songs:

$ beet bpmanalyser --dry-run artist:AC/DC

Update tempo information on all songs where it is missing:

$ beet bpmanalyser bpm:0

Force the update of tempo information on all songs where it has already been set:

$ beet bpmanalyser -f ^bpm:0

Accuracy

BPM values from acousticbrainz:

$ beet -c dev.yml acousticbrainz artist:AC/DC
acousticbrainz: getting data for: [format:MP3][bpm:121.106361389] ::: /_TmpMusic_/A/AC_DC/High Voltage/01. Baby, Please Don't Go.mp3
acousticbrainz: getting data for: [format:MP3][bpm:117.203399658] ::: /_TmpMusic_/A/AC_DC/High Voltage/02. She's Got Balls.mp3
acousticbrainz: getting data for: [format:MP3][bpm:106.826393127] ::: /_TmpMusic_/A/AC_DC/High Voltage/03. Little Lover.mp3
acousticbrainz: getting data for: [format:MP3][bpm:119.486862183] ::: /_TmpMusic_/A/AC_DC/High Voltage/04. Stick Around.mp3
acousticbrainz: getting data for: [format:MP3][bpm:133.189102173] ::: /_TmpMusic_/A/AC_DC/High Voltage/05. Soul Stripper.mp3
acousticbrainz: getting data for: [format:MP3][bpm:128.054992676] ::: /_TmpMusic_/A/AC_DC/High Voltage/06. You Ain't Got a Hold on Me.mp3
acousticbrainz: getting data for: [format:MP3][bpm:123.012046814] ::: /_TmpMusic_/A/AC_DC/High Voltage/07. Love Song.mp3
acousticbrainz: getting data for: [format:MP3][bpm:136.914703369] ::: /_TmpMusic_/A/AC_DC/High Voltage/08. Show Business.mp3

BPM values calculated by aubio:

$ beet -c dev.yml bpmanalyser artist:AC/DC -df
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/01. Baby, Please Don't Go.mp3] bpm: 122
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/02. She's Got Balls.mp3] bpm: 117
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/03. Little Lover.mp3] bpm: 106
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/04. Stick Around.mp3] bpm: 120
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/05. Soul Stripper.mp3] bpm: 132
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/06. You Ain't Got a Hold on Me.mp3] bpm: 128
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/07. Love Song.mp3] bpm: 125
bpmanalyser: Song[/_TmpMusic_/A/AC_DC/High Voltage/08. Show Business.mp3] bpm: 139

Issues

If something is not working as expected please use the Issue tracker. If the documentation is not clear please use the Issue tracker. If you have a feature request please use the Issue tracker. In any other situation please use the Issue tracker.

Other plugins by the same author

Acknowledgements

Many thanks to the developers and contributors of the beets check plugin. Some structural concepts and best practices were adopted to get started on this plugin.

Final Remarks

Enjoy!

beetspluginbpmanalyser's People

Contributors

adamjakab avatar andrewjw avatar brianschrameck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

beetspluginbpmanalyser's Issues

AUBIO problem?

Hello!

It worked for a while. Then begun to give me [ERROR]

I did beet -vv bpmanalyser bpm:0 and got:

user configuration: /home/archlinux/.config/beets/config.yaml
data directory: /home/archlinux/.config/beets
plugin paths: 
inline: adding item field albumartistcomp
Sending event: pluginload
library database: /mnt/main/data/beets/musiclibrary.db
library directory: /mnt/storage/data/media/music
Sending event: library_opened
bpmanalyser: External script path: /home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py
bpmanalyser: Analysing[/mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/01 - Blondie - Heart Of Glass.mp3]...
bpmanalyser: calling external script: /home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py
bpmanalyser: Analysing[/mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/02 - Blondie - Dreaming.mp3]...
bpmanalyser: calling external script: /home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py
bpmanalyser: [mp3 @ 0x55b42f923c80] Estimating duration from bitrate, this may be inaccurate
[mp3float @ 0x55b42f9295c0] Header missing
Traceback (most recent call last):
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 52, in <module>
    bpm = _analyse_tempo(file_name)
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 27, in _analyse_tempo
    samples, read = src()
RuntimeError: AUBIO ERROR: source_avcodec: error when sending packet for /mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/02 - Blondie - Dreaming.mp3

bpmanalyser: Bpm[ERROR]: - /mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/02 - Blondie - Dreaming.mp3
bpmanalyser: Analysing[/mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/03 - Blondie - The Tide Is High.mp3]...
bpmanalyser: calling external script: /home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py
bpmanalyser: [mp3 @ 0x560c51ffc680] Estimating duration from bitrate, this may be inaccurate
[mp3float @ 0x560c52002fc0] Header missing
Traceback (most recent call last):
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 52, in <module>
    bpm = _analyse_tempo(file_name)
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 27, in _analyse_tempo
    samples, read = src()
RuntimeError: AUBIO ERROR: source_avcodec: error when sending packet for /mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/01 - Blondie - Heart Of Glass.mp3

bpmanalyser: Bpm[ERROR]: - /mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/01 - Blondie - Heart Of Glass.mp3
bpmanalyser: Analysing[/mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/04 - Blondie - In The Flesh.mp3]...
bpmanalyser: calling external script: /home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py
^Cbpmanalyser: [mp3 @ 0x555d86993480] Estimating duration from bitrate, this may be inaccurate
Traceback (most recent call last):
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 52, in <module>
    bpm = _analyse_tempo(file_name)
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 28, in _analyse_tempo
    is_beat = o(samples)
KeyboardInterrupt

bpmanalyser: Bpm[ERROR]: - /mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/04 - Blondie - In The Flesh.mp3
bpmanalyser: [mp3 @ 0x5653b01a0680] Estimating duration from bitrate, this may be inaccurate
Traceback (most recent call last):
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 52, in <module>
    bpm = _analyse_tempo(file_name)
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/get_song_bpm.py", line 28, in _analyse_tempo
    is_beat = o(samples)
KeyboardInterrupt

bpmanalyser: Bpm[ERROR]: - /mnt/storage/data/media/music/Compilations/Blondie-The Best Of Blondie [1981]/03 - Blondie - The Tide Is High.mp3
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/beets/ui/__init__.py", line 1285, in main
    _raw_main(args)
  File "/usr/lib/python3.10/site-packages/beets/ui/__init__.py", line 1272, in _raw_main
    subcommand.func(lib, suboptions, subargs)
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/command.py", line 116, in func
    self.analyse_songs()
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/command.py", line 161, in analyse_songs
    self.execute_on_items(items, analyse, msg='Analysing tempo...')
  File "/home/archlinux/.local/lib/python3.10/site-packages/beetsplug/bpmanalyser/command.py", line 186, in execute_on_items
    for _ in e.map(func, items):
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 621, in result_iterator
    yield _result_or_cancel(fs.pop())
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 319, in _result_or_cancel
    return fut.result(timeout)
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 453, in result
    self._condition.wait(timeout)
  File "/usr/lib/python3.10/threading.py", line 320, in wait
    waiter.acquire()
KeyboardInterrupt

How can I fix it? Can you help me?

BpmAnalyser not outputting BPM Values

Problem

Running your command in verbose (-vv) mode:

beet bpmanalyser --dry-run title:Tripura - Wizard Project

Led to this problem:

bpmanalyser: BpmAnalyser exec threads: 6
bpmanalyser: Done.

Setup

  • OS: W10
  • Python version: 3.13
  • Beets version: Latest
  • Turning off other plugins made problem go away (yes/no): no

My configuration (output of beet config) is:

directory: C:/Users/Hannes/Desktop/Test
library: C:/Users/Hannes/AppData/Roaming/beets/library.db
import:
  copy: yes
  write: yes
  move: no

plugins:
  - bpmanalyser

bpmanalyser:
  auto: no
  dry-run: no
  write: yes
  threads: "AUTO"
  force: no
  quiet: no

logging:
  level: DEBUG

My plugin version (output of beet bpmanalyser -v) is:

bpmanalyser: Bpm Analyser(beets-bpmanalyser) plugin for Beets: v1.5.9

0 bpm detected

When running bpmanalyser all files are detected as having a bpm of 0.

andrew@tv:~/temp_music$ beet bpmanalyser --dry-run artist:Foals
bpmanalyser: Song[/mnt/nfs/music_hq/Foals/Antidotes/02 Cassius.flac] bpm: 0

Is there any way I can debug this? Running aubio manually works...

andrew@tv:~$ aubio tempo /mnt/nfs/music_hq/Foals/Antidotes/02\ Cassius.flac
148.67 bpm

Initially aubio didn't work because I didn't have the right libraries installed to enable flac files. I've corrected that, but the beet plugin still doesn't work.

Not working on import

Problem

First of all awesome job with the script. It works with beet -vv bpmanalyser whatever and

plugins: fetchart embedart lyrics discogs spotify convert bpmanalyser replaygain
autotag: yes
ignore_hidden: yes
original_date: yes
languages: en
va_name: Compilation
directory: /redacted/
import:
    copy: yes
    write: yes
    move: no
convert:
    auto: yes
    quiet: yes
    delete_originals: no
    format: mp3
    mp3:
      command: ffmpeg -i $source -q:a 0 -map_metadata 0 $dest
      extension: mp3
discogs:
    user_token: redacted
fetchart:
    auto: yes
    sources: fanarttv itunes amazon coverart albumart
    fanarttv_key: redacted
embedart: 
    auto: yes
    maxwidth: 1000
    remove_art_file: yes
lyrics:
    auto: yes
    force: yes
    import.write: yes
    sources: genius
    google_API_key: redacted
replaygain:
  auto: yes
  overwrite: yes
bpmanalyser:
  auto: yes
  dry-run: no
  write: yes
  threads: 2
  force: yes
  quiet: yes
replace:
    'featuring': 'feat\.'
    '’': "'"
    '[“”]': '"'
    '[…]': '...'
    '[-]': '-'
    '[−]': '-'
    '[—]': '-'
    '[Ⅰ]': I
    '[Ⅱ]': II

However, on import, no tag is written to the files automatically.

Setup

  • OS: macOS
  • Python version: 3.9.5
  • Beets version: 1.6.1

New error after 1.5.6 release "AttributeError: 'BpmAnalyserCommand' object has no attribute 'analyse'"

Problem

During import I get an error when BPM runs

beet -vv imp .

and

beet imp .

produce the same information during import, once bpm analyser starts

Led to this problem:

beet imp .
E:\New_Music\import\   (1 items)
Tagging:
    
URL:
    
(Similarity: 100.0%) (Spotify, 2020, RCA/Famouz Records)
 * Don't Mean A Thing
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Scripts\beet.exe\__main__.py", line 7, in <module>
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\ui\__init__.py", line 1285, in main
    _raw_main(args)
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\ui\__init__.py", line 1272, in _raw_main
    subcommand.func(lib, suboptions, subargs)
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\ui\commands.py", line 973, in import_func
    import_files(lib, paths, query)
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\ui\commands.py", line 943, in import_files
    session.run()
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\importer.py", line 340, in run
    pl.run_parallel(QUEUE_SIZE)
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\util\pipeline.py", line 446, in run_parallel
    raise exc_info[1].with_traceback(exc_info[2])
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\util\pipeline.py", line 311, in run
    out = self.coro.send(msg)
          ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\util\pipeline.py", line 193, in coro
    func(*(args + (task,)))
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\importer.py", line 1535, in plugin_stage
    func(session, task)
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beets\plugins.py", line 145, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\beetsplug\bpmanalyser\__init__.py", line 43, in imported
    BpmAnalyserCommand(self.config).analyse(item)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'BpmAnalyserCommand' object has no attribute 'analyse'

Setup

  • OS: Windows x64
  • Python version: 3.12.3
  • Beets version: 1.6.1 (git head)
  • Turning off other plugins made problem go away (yes/no): no

My configuration (output of beet config) is:

bpmanalyser:
  auto: yes
  dry-run: no
  write: yes
  threads: 8
  force: no
  quiet: no

My plugin version (output of beet bpmanalyser -v) is:

bpmanalyser: Bpm Analyser(beets-bpmanalyser) plugin for Beets: v1.5.6

Disabling beets config for threaded did not fix the issue.

I can help with running a git version for debug.

I'll import and then try running over the newly imported items

BPM is different than running aubio separate from it

Problem

I have noticed that using aubio to tag my files with the script below generates a different value for BPM than this plugin. I wonder why? Which one do you think is more accurate?

#!/bin/bash

export PATH=/Library/Frameworks/Python.framework/Versions/3.9/bin/:/usr/bin/:/bin/

for file in "$@"
do
    # Get the filename without extension
    filename=$(basename "$file")
    extension="${filename##*.}"
    filename="${filename%.*}"

    # Use aubio to find the BPM of the audio file
    bpm=$(aubio tempo "$file" | awk '{printf("%.0f\n", $1)}')

	# Write the BPM to the ID3 tag using eyeD3
    eyeD3 "$file" --bpm="$bpm"
done

error when trying to fetch bpm values

when typing in the cmd beet bpmanalyser -t '{directory}' i get an error:

File "/usr/local/lib/python3.7/site-packages/beetsplug/bpmanalyser.py", line 122, in func self.analyse_songs() File "/usr/local/lib/python3.7/site-packages/beetsplug/bpmanalyser.py", line 150, in analyse_songs self.execute_on_items(items, analyse, msg='Analysing tempo...') File "/usr/local/lib/python3.7/site-packages/beetsplug/bpmanalyser.py", line 170, in execute_on_items with futures.ThreadPoolExecutor(max_workers=self.cfg_threads) as e: File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/thread.py", line 128, in __init__ if max_workers <= 0: TypeError: '<=' not supported between instances of 'str' and 'int'

i see bpmanalyser plugin enabled in beets when i do "beet version"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.