MusicBrainz Picard

Overview

MusicBrainz Picard

Github Actions Status Codacy Grade

MusicBrainz Picard is a cross-platform (Linux/Mac OS X/Windows) application written in Python and is the official MusicBrainz tagger.

Picard supports the majority of audio file formats, is capable of using audio fingerprints (AcoustIDs), performing CD lookups and disc ID submissions, and it has excellent Unicode support. Additionally, there are several plugins available that extend Picard's features.

When tagging files, Picard uses an album-oriented approach. This approach allows it to utilize the MusicBrainz data as effectively as possible and correctly tag your music. For more information, see the illustrated quick start guide to tagging.

Picard is named after Captain Jean-Luc Picard from the TV series Star Trek: The Next Generation.

Binary downloads are available here.

Support and issue reporting

Please report all bugs and feature requests in the MusicBrainz issue tracker. If you need support in using Picard please read the documentation first and have a look at the MusicBrainz community forums.

Installing

INSTALL.md has instructions on building this codebase.

Comments
  • Mitigate thread competition by scanning directories before loading files

    Mitigate thread competition by scanning directories before loading files

    Summary

    • This is a…
      • [ ] Bug fix
      • [ ] Feature addition
      • [x] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences: Change directory scanning (add_directory) logic to scan everything before adding files (add_files).

    Problem

    The thread pool threads have to deal with a whole bunch of different tasks and compete for both IO and CPU. The current code launches concurrent tasks for directory scanning and file processing, which leads to harmful competition and slows down the file processing.

    • JIRA ticket (optional): PICARD-840

    Solution

    Instead of running the directory scanning interleaved with the file processing, a single Python thread is used to scan first and then forwards the files list to the Tagger.add_files at once. The thread runs the unified recursive/non-recursive file scanning code.

    Tested on a 17k file library cleaning file cache before and between tests (SysInternals RamMap->Empty Standby list). Completely loading the library took:

    • Latest master clone: 32 minutes, with HDD reading speeds fluctuating between 1-5 MB/s for for most of the time (was running reasonably fine until the 7-8k song mark, then slowed down. Seemingly due to the lack of files to process as the directory/file scanning is frequently interrupted);
    • Latest branch clone: 13 minutes, with HDD reading speeds fluctuating between 8-10MB/s for most of the time.

    Action

    opened by Gabrielcarvfer 93
  • PICARD-2471: Restrict Picard to a single instance

    PICARD-2471: Restrict Picard to a single instance

    Summary

    • This is a…
      • [ ] Bug fix
      • [x] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences:

    This is a draft where we can discuss my GSoC project progress. Picard is going to work in single-instance mode thanks to named pipes

    Problem

    Ticket description is clear enough so I'll just paste it here:

    When passing folders to Picard via command line (such as in Foobar), Picard will launch a new instance for each folder rather than loading them all in one instance. The ability to force it all into one instance would be helpful.

    • JIRA ticket (optional): PICARD-2471

    Solution

    I've created a cross-platform communication protocol for Picard instances, based on named pipes. Now, in this draft, you can see my progress in integrating it into the Picard app.

    TODO

    • [x] Communication protocol works on all supported operating systems
    • [x] Pipe can distinguish between app versions
    • [x] If pipe is listened to, Picard sends all the arguments there and leaves without spawning an instance
    • [x] Picard accepts -s/--stand-alone-instance argument to create a forced, standalone instance, that doesn't listen to any pipe
    • [x] Picard creates a "pipe server" thread that listens to any possible messages in the background and passes messages to file-adding methods
    • [x] in tagger.py/main: picard_args.FILE args are converted to absolute paths before passing them to the existing instanec
    • [x] Changes are tested
    • [x] Changes are documented
    • [x] Commits are properly organised
    • [ ] Merge :)

    Notes

    • Type annotations are my helpers, since I always use mypy while writing Python. When we will be merging into master, I can remove them if they are problematic for you
    • Commit structure is also just a draft to be organised properly
    • Because it's just a draft, I'll let you know when workflows will make sense.
    opened by skelly37 61
  • PICARD-2526: Allow starting processing actions from the command line

    PICARD-2526: Allow starting processing actions from the command line

    Summary

    • This is a…
      • [ ] Bug fix
      • [x] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences:

    Users will be able to pass some commands to the existing instance with -e/--exec flag.

    Problem

    It would be useful to tell the existing Picard instance what to do, e.g. QUIT, useful in combination with the other single-instance mode improvements

    • JIRA ticket (optional): PICARD-2526

    Solution

    • add command:// prefix to the commands
    • send them as any other arg
    • parse with urlparse, split by ";"
    • execute

    Action

    opened by skelly37 54
  • PICARD-936: Improve UI responsiveness whilst busy loading, saving etc.

    PICARD-936: Improve UI responsiveness whilst busy loading, saving etc.

    Resolves PICARD-936.

    Improves the responsiveness during worker thread operations by triggering main thread to process events after events are sent to it.

    Improves file loading performance by moving operations into separate threadpools.

    This PR was brought to you as a joint effort between Sophist-UK and @samj1912.

    Needs more work 
    opened by Sophist-UK 54
  • PICARD-1734: Add AcousticBrainz analyzer features

    PICARD-1734: Add AcousticBrainz analyzer features

    Summary

    • This is a…
      • [ ] Bug fix
      • [x] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences: Call the AcousticBrainz/Essentia feature extractor from Picard and submit the extracted features.

    Problem

    • JIRA ticket (optional): PICARD-1734

    Solution

    A single button triggers the check for duplicate AcousticBrainz features duplicates (same recordingID + extractor version), extract features of non-duplicates and tries to submit them.

    Action

    Part of the AcousticBrainz code comes from the acoustic-brainz client, that has a different license (GPL-v3). Not sure what to do with it.

    opened by Gabrielcarvfer 53
  • PICARD-1043: Add support for iTunes Movement tags - 1.4.x branch

    PICARD-1043: Add support for iTunes Movement tags - 1.4.x branch

    Resolves https://tickets.metabrainz.org/browse/PICARD-1043

    Note 1: This is targetted at the 1.4.x branch in order to avoid issues of installing Qt5 with Py2. Note 2: This PR currently includes the commits from #667 pending their inclusion in the 1.4.x branch. Once Py3 support is in master or #667 cherry picked into 1.4.x I will rebase without these. Note 3: See #695 for equivalent PR for master branch.

    opened by Sophist-UK 48
  • PICARD-204: Support for recording-level original release date

    PICARD-204: Support for recording-level original release date

    Summary

    • This is a…
      • [ ] Bug fix
      • [x] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences:

    Use first-release-date of recordings if available.

    Problem

    • JIRA ticket (optional): PICARD-204

    Solution

    Use the first-release-date field on recordings if available and fill originaldate and originalyear with this information. If the data is not set on a recording (should not happen actually once this is fully rolled out) it would still use the data from the release group.

    For more flexibility this makes available two additional variables ~recordingoriginaldate and ~releaseoriginaldate for scripting. This e.g. allows to always use the original date for the entire release instead of using the per recording date.

    Action

    At this moment this is partially rolled out on musicbrainz.org. This patch already works for getting originaldate when querying standalone-recordings. For full support also for releases with different per-recording dates https://github.com/metabrainz/musicbrainz-server/pull/1847 needs to be merged and rolled out.

    opened by phw 39
  • Make Picard tags more comprehensive.

    Make Picard tags more comprehensive.

    This PR will eventually provide a more comprehensive mapping of Picard tags onto tags supported by various file formats. My intention is to develop this in steps and share code at each step for review comments.

    Step 1: Improve compatibility with Jaikoz based on Philip Wolfer's spreadsheet (see first commit) and add support for as many ID3v2.4 tags that can be easily included. Data will be populated from the standard MB responses where data is included, otherwise they will be left to plugins to populate from e.g. AcousticBrainz, other MB calls for artist details etc.

    Step 1 is now complete

    Step 2: Add test support for Step 1.

    Step 3: Bug fixing.

    Needs more work 
    opened by Sophist-UK 38
  • PICARD-2178: Select random sample of loaded files to use as renaming examples

    PICARD-2178: Select random sample of loaded files to use as renaming examples

    Summary

    • This is a…
      • [ ] Bug fix
      • [x] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences: Instead of using the two provided file examples for renaming, pick up to 10 random entries from the loaded files and use them to show before/after the renaming script. Also includes a button to refresh the up to 10 entries.

    Problem

    • JIRA ticket (optional): PICARD-2178

    Writing a naming script is hard by itself.

    Solution

    Make it a bit easier to check the script by selecting loaded files as examples and showing the before and after.

    Action

    opened by Gabrielcarvfer 31
  • PICARD-1273: Add an option to exclude new cover art type

    PICARD-1273: Add an option to exclude new cover art type "Raw / Unedited"

    Summary

    • This is a…
      • [ ] Bug fix
      • [x] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences: This change provides the user with the option of excluding selected cover art types from downloading from CAA.

    Problem

    STYLE-980 has added a new cover art style "Raw / Unedited". Although beneficial for identifying and allowing better images for archival purposes, the images within this type are generally not suitable for tagging purposes. Picard currently allows the user to select the types of images to download from CAA, but does not provide the ability to exclude selected image types from being downloaded.

    • JIRA ticket: PICARD-1273: Add an option to exclude new cover art type "Raw / Unedited"

    Solution

    This change adds new user settings to indicate whether selected image types should be excluded from downloads from CAA and the list of image types to be excluded, similar to the option to only include selected image types. Additional logic is applied to the list of images selected for download, and any images with a type intersecting the user's "exclusion" type list are removed from the download list.

    Generally speaking, the current logic for determining whether to download an image is (where the image is downloaded when "types" evaluates to True):

    if self.restrict_types:
        # only keep enabled caa types
        types = set(image["types"]).intersection(
            set(self.caa_types))
    else:
        types = True
    

    This change adds a further check for exclusion, as:

    if self.restrict_types:
        # only keep enabled caa types
        types = set(image["types"]).intersection(
            set(self.caa_types))
    else:
        types = True
    if types and self.omit_types:
        # omit selected caa types
        types = not set(image["types"]).intersection(
            set(self.caa_types_to_omit))
    

    Action

    Currently, it appears that CAA does not return the new "Raw/Unedited" type in the list of image types associated with an image. This is described (with an example) in CAA-113: CAA does not return "Raw/Unedited" in image type array. This will need to be addressed before the proposed changes will work.

    opened by rdswift 30
  • [PICARD-695] Tags are not properly cleared for some files even with the clear metadata option.

    [PICARD-695] Tags are not properly cleared for some files even with the clear metadata option.

    Hello, I notice that in some case, the metadata were not competetly cleared even with the option enabled. By saving the file without any metadata before saving with the metadata, it seems to work. I would like to provide the mp3 to illustrate the problem but the file is too big...

    Thank you for your work, it is great ;)

    Decision required 
    opened by NCenerar 29
  • PICARD-2605: Ensure packaged Qt5 DLLs get loaded

    PICARD-2605: Ensure packaged Qt5 DLLs get loaded

    Summary

    • This is a…
      • [x] Bug fix
      • [ ] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences:

    Problem

    • JIRA ticket (optional): PICARD-2605

    PyInstaller 5.4 changed the location of the Qt5 DLLs. This bypassed our prioritization of packaged DLLs.

    Solution

    Add install dir PyQt5/Qt5/bin to PATH.

    opened by phw 0
  • Limit worker threads based on CPUs

    Limit worker threads based on CPUs

    Summary

    • This is a…
      • [ ] Bug fix
      • [ ] Feature addition
      • [x] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences:

    Problem

    The default thread pool by default has a max. thread count based on QThread.idealThreadCount(), which basically sets the thread count based on the system's available CPU cores.

    Especially during file loading this number of threads gets exhausted. But this means there are 8 loading threads running, but there is always at least the main UI thread. Also there are the save thread pool (which might be used when the user is saving files in parallel) and the priority thread pool (which currently is used in metadatabox updates only and is meant for everything that should not be blocked by normal background tasks).

    Solution

    Limit number of threads in the main pol to QThread.idealThreadCount() minus 3 (main thread, priority pool + save pool). Keep at least 2, as one thread gets used up by the new pipe config.

    In my tests with 8 cores this gave 5. It improved responsiveness during loading of many files significantly. But we might consider going a bit higher. We have one thread reserved for the pipe handling, which usually isn't doing much. Then save thread pool is usually idle. Priority gets used if the user clicks some item with metadata.

    opened by phw 30
  • PICARD-2331: Port to PyQt6

    PICARD-2331: Port to PyQt6

    Summary

    WIP of porting Picard to PyQt6.

    Problem

    • JIRA ticket (optional): PICARD-2331

    Solution

    • [x] Upgrade all references to PyQt6 and apply general API changes
    • [x] Replacement for QAction.menu (for CD drive selection button) (done in #2169)
    • [x] Remove custom network timeout implementation (now supported by Qt6 itself)
    • [x] Bump API version to 3.0
    • [x] Remove macOS 10.12 / 10.13 builds (no longer supported by Qt6)
    • [x] Update resource loading for PyQt6 (requires PyQt >= 6.3.1)
    • [ ] Handle no longer available QtWinExtras.QWinTaskbarButton (see https://www.qt.io/blog/qt-extras-modules-in-qt-6, QTBUG-94008, QTBUG-89564)
    • [ ] Migrate media player (WIP)
    • [ ] Investigate failings tests on Linux CI
    • [x] Test on Linux
    • [ ] Test on macOS
    • [ ] Test on Windows
    Feature Needs more work Do not merge yet 
    opened by phw 1
  • PICARD-2354: DeprecationWarning: the imp module is deprecated in favour of importlib

    PICARD-2354: DeprecationWarning: the imp module is deprecated in favour of importlib

    Summary

    The imp module will be removed in Python 3.12 so we have to switch to importlib

    • This is a…
      • [ ] Bug fix
      • [ ] Feature addition
      • [x] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences:

    imp is used only in pluginmanager.py in 2 places, so it doesn't change much of the codebase.

    Problem

    • JIRA ticket (optional): PICARD-2354

    Solution

    I've found some way to replace it in importlib examples but I'm not sure if they're the best way to achieve this.

    Action

    opened by skelly37 3
  • PICARD-1001 Rework local cover art handling

    PICARD-1001 Rework local cover art handling

    Summary

    • This is a…
      • [x] Bug fix
      • [ ] Feature addition
      • [x] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences: Rework local cover art handling from a cover art provider to a property of files.

    Problem

    Local cover art as a provider doesn't make sense - local cover art is a property of a file, same as tag cover art. Problems caused by local cover art being treated as a provider include incorrectly indicating that files have been modified, or if an album was loaded without any files associated (for example via a tagger link on musicbrainz.org), no cover art at all.

    • JIRA ticket (optional): PICARD-1001

    Solution

    Move the handling of local cover art to the File class and delete the Local File cover art provider

    Action

    I don't know how to write Qt UI, so someone familiar with that will have to update the UI for this change.

    In the current state, the local_cover_regex setting is re-used, and a new load_local_cover_art boolean is used to enable the feature. The new setting should default to the same as the enabled status of the Local FIle cover art provider used to be.

    Some decision has to be made on how to result ordering of loading cover art from tags vs. local files. Currently local file art loading is skipped if cover art was loaded from tags.

    Needs more work 
    opened by kepstin 9
  • Improve matching for VA releases

    Improve matching for VA releases

    • if an album was incorrectly tagged with a label name or whatever, instead of Various Artists Picard tries to match Various Artists (from database) to the name, usually leading to a very low similarity, reducing a lot the chance to find the correct release

    • a contrario, if an album was tagged with Various Artists, it is very likely it is a VA compilation, so increase the weight

    Summary

    • This is a…
      • [x] Bug fix
      • [ ] Feature addition
      • [ ] Refactoring
      • [ ] Minor / simple change (like a typo)
      • [ ] Other
    • Describe this change in 1-2 sentences:

    Problem

    • JIRA ticket (optional): PICARD-XXX

    Solution

    Action

    opened by zas 0
Releases(release-2.9.0a1)
Owner
MetaBrainz Foundation
A California 501.c.3 non-profit organization running MusicBrainz and other open data/open source projects.
MetaBrainz Foundation
A small project where I identify notes and key harmonies in a piece of music and use them further to recreate and generate the same piece of music through Python

A small project where I identify notes and key harmonies in a piece of music and use them further to recreate and generate the same piece of music through Python

5 Oct 07, 2022
Code for csig audio deepfake detection

FMFCC Audio Deepfake Detection Solution This repo provides an solution for the 多媒体伪造取证大赛. Our solution achieve the 1st in the Audio Deepfake Detection

BokingChen 9 Jun 04, 2022
Terminal-based music player written in Python for the best music in the world 🎵 🎧 💻

audius-terminal-player Terminal-based music player written in Python for the best music in the world 🎵 🎧 💻 Browse and listen to Audius from the com

Audius 21 Jul 23, 2022
Reading list for research topics in sound event detection

Sound event detection aims at processing the continuous acoustic signal and converting it into symbolic descriptions of the corresponding sound events present at the auditory scene.

Soham 64 Jan 05, 2023
:notes: Cross-platform music player

Exaile Exaile is a music player with a simple interface and powerful music management capabilities. Features include automatic fetching of album art,

Exaile 327 Dec 19, 2022
Gammatone-based spectrograms, using gammatone filterbanks or Fourier transform weightings.

Gammatone Filterbank Toolkit Utilities for analysing sound using perceptual models of human hearing. Jason Heeris, 2013 Summary This is a port of Malc

Jason Heeris 188 Dec 14, 2022
Audio processor to map oracle notes in the VoG raid in Destiny 2 to call outs.

vog_oracles Audio processor to map oracle notes in the VoG raid in Destiny 2 to call outs. Huge thanks to mzucker on GitHub for the note detection cod

19 Sep 29, 2022
An 8D music player made to enjoy Halloween this year!🤘

HAPPY HALLOWEEN buddy! Split Player Hello There! Welcome to SplitPlayer... Supposed To Be A 8DPlayer.... You Decide.... It can play the ordinary audio

Akshat Kumar Singh 1 Nov 04, 2021
Scalable audio processing framework written in Python with a RESTful API

TimeSide : scalable audio processing framework and server written in Python TimeSide is a python framework enabling low and high level audio analysis,

Parisson 340 Jan 04, 2023
Anaphones are like anagrams, but for sounds.

Anaphones Anaphones are like anagrams but for sounds (phonemes). Examples include: salami-awesomely, atari-tiara, and beefy-phoebe. Anaphones can be a

James Murphy 18 Nov 02, 2022
OpenClubhouse - A third-part web application based on flask to play Clubhouse audio.

OpenClubhouse - A third-part web application based on flask to play Clubhouse audio.

1.1k Jan 05, 2023
Python audio and music signal processing library

madmom Madmom is an audio signal processing library written in Python with a strong focus on music information retrieval (MIR) tasks. The library is i

Institute of Computational Perception 1k Dec 26, 2022
Expressive Digital Signal Processing (DSP) package for Python

AudioLazy Development Last release PyPI status Real-Time Expressive Digital Signal Processing (DSP) Package for Python! Laziness and object representa

Danilo de Jesus da Silva Bellini 642 Dec 26, 2022
SomaFM Plugin for Kodi

SomaFM XBMC Plugin This description is a bit outdated. You can simply install this addon by browsing the official repositories from within Kodi. Insta

7 Jan 21, 2022
This Is Telegram Music UserBot To Play Music Without Being Admin

This Is Telegram Music UserBot To Play Music Without Being Admin

Krishna Kumar 36 Sep 13, 2022
ianZiPu is a way to write notation for Guqin (古琴) music.

PyBetween Wrapper for Between - 비트윈을 위한 파이썬 라이브러리 Legal Disclaimer 오직 교육적 목적으로만 사용할수 있으며, 비트윈은 VCNC의 자산입니다. 악의적 공격에 이용할시 처벌 받을수 있습니다. 사용에 따른 책임은 사용자가

Nancy Yi Liang 8 Nov 25, 2022
Simple discord bot by @merive 🤖

Parzibot Powerful and Useful Discord Bot on Python. The source code of the bot is available to everyone. Parzibot uses English language. This is free

merive_ 3 Dec 28, 2022
nicfit 425 Jan 01, 2023
SolidMusic rewrite version, need help

Telegram Streamer Bot This is rewrite version of solidmusic, but it can't be deployed now, help me to make this bot running fast and good. If anyone w

Shohih Abdul 63 Jan 06, 2022
BART aids transcribe tasks by taking a source audio file and creating automatic repeated loops, allowing transcribers to listen to fragments multiple times

BART (Beyond Audio Replay Technology) aids transcribe tasks by taking a source audio file and creating automatic repeated loops, allowing transcribers to listen to fragments multiple times (with poss

2 Feb 04, 2022