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
MelGAN test on audio decoding

Official repository for the paper MelGAN: Generative Adversarial Networks for Conditional Waveform Synthesis The original work URL: https://github.com

Jurio 1 Apr 29, 2022
Python wrapper around sox.

pysox Python wrapper around sox. Read the Docs here. This library was presented in the following paper: R. M. Bittner, E. J. Humphrey and J. P. Bello,

Rachel Bittner 446 Dec 07, 2022
A voice assistant which can handle your everyday task and allows you to book items from your favourite store!

Voicely Table of Contents About The Project Built With Getting Started Prerequisites Installation Usage Roadmap Contributing License Contact Acknowled

Awantika Nigam 2 Nov 17, 2021
Audio library for modelling loudness

Loudness Loudness is a C++ library with Python bindings for modelling perceived loudness. The library consists of processing modules which can be casc

Dominic Ward 33 Oct 02, 2022
Telegram Voice-Chat Bot Written In Python Using Pyrogram.

Telegram Voice-Chat Bot Telegram Voice-Chat Bot To Play Music From Various Sources In Your Group Support All linux based os. Windows Mac Diagram Requi

TheHamkerCat 314 Dec 29, 2022
Mousai is a simple application that can identify song like Shazam

Mousai is a simple application that can identify song like Shazam. It saves the artist, album, and title of the identified song in a JSON file.

Dave Patrick 662 Jan 07, 2023
MusicBrainz Picard

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

MetaBrainz Foundation 3k Dec 31, 2022
Python library for handling audio datasets.

AUDIOMATE Audiomate is a library for easy access to audio datasets. It provides the datastructures for accessing/loading different datasets in a gener

Matthias 121 Nov 27, 2022
python wrapper for rubberband

pyrubberband A python wrapper for rubberband. For now, this just provides lightweight wrappers for pitch-shifting and time-stretching. All processing

Brian McFee 106 Nov 28, 2022
A Python 3 script for capturing and recording a SDR stream to a WAV file (or serving it to a HTTP audio stream).

rfsoapyfile A Python 3 script for capturing and recording a SDR stream to a WAV file (or serving it to a HTTP audio stream). The script is threaded fo

4 Dec 19, 2022
Port Hitsuboku Kumi Chinese CVVC voicebank to deepvocal. / 筆墨クミDeepvocal中文音源

Hitsuboku Kumi (筆墨クミ) is a UTAU virtual singer developed by Cubialpha. This project ports Hitsuboku Kumi Chinese CVVC voicebank to deepvocal. This is the first open-source deepvocal voicebank on Gith

8 Apr 26, 2022
Algorithmic Multi-Instrumental MIDI Continuation Implementation

Matchmaker Algorithmic Multi-Instrumental MIDI Continuation Implementation Taming large-scale MIDI datasets with algorithms This is a WIP so please ch

Alex 2 Mar 11, 2022
Audio augmentations library for PyTorch for audio in the time-domain

Audio augmentations library for PyTorch for audio in the time-domain, with support for stochastic data augmentations as used often in self-supervised / contrastive learning.

Janne 166 Jan 08, 2023
Algorithmic and AI MIDI Drums Generator Implementation

Algorithmic and AI MIDI Drums Generator Implementation

Tegridy Code 8 Dec 30, 2022
Desktop music recognition application for windows

MusicRecognizer Music recognition application for windows You can choose from which of the devices the recording will be made. If you choose speakers,

Nikita Merzlyakov 28 Dec 13, 2022
An audio digital processing toolbox based on a workflow/pipeline principle

AudioTK Audio ToolKit is a set of audio filters. It helps assembling workflows for specific audio processing workloads. The audio workflow is split in

Matthieu Brucher 238 Oct 18, 2022
A GUI-based audio player with support for a large variety of formats

Miza-Player A GUI-based audio player with support for a large variety of formats, able to play from web-hosted media platforms such as YouTube, includ

Thomas Xin 3 Dec 14, 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
Music bot of # Owner

Pokimane-Music Music bot of # Owner How To Host The easiest way to deploy this Bot Support Channel :- TeamDlt Support Group :- TeamDlt Please fork thi

5 Dec 23, 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