Giter VIP home page Giter VIP logo

mediafile's People

Contributors

arcresu avatar autrimpo avatar bpruessm avatar brunal avatar daveisadork avatar dosoe avatar eigengrau avatar ibmibmibm avatar jackwilsdon avatar jacobwgillespie avatar jeandeaual avatar jesseward avatar jmbannon avatar joj0 avatar jtpavlock avatar juniorjpdj avatar kiefermat avatar ktkonrad avatar mhendu avatar pkess avatar postlund avatar rawrmonkeys avatar s-fleck avatar sampsyo avatar simonhova avatar simonluijk avatar slogsdon7 avatar stevenmaude avatar untitaker avatar zsinskri avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mediafile's Issues

Add barcode as mediafield

I use mediafile to update my music as an alternative Python-based ampache scanner, and it works wonderfully; however the one field that ampache needs is the barcode field, and I have to make an expensive call back to MusicBrainz to fetch it. Can someone please add the barcode field to the list of fields that it can retrieve?

Test failure on Arch Linux

Building python-mediafile from the AUR I'm getting the following error. https://aur.archlinux.org/pkgbase/python-mediafile/#comment-758314

~/python-mediafile/src/python3 ~/python-mediafile/src ~/python-mediafile/src
..............................................................................................................................................................................................................................................................................................................................................................................F.....................................................................
======================================================================
FAIL: test_read_audio_properties (test.test_mediafile.WavpackTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/build/python-mediafile/src/python3/test/test_mediafile.py", line 442, in test_read_audio_properties
    self.assertEqual(getattr(mediafile, key), value)
AssertionError: 16 != 0

----------------------------------------------------------------------
Ran 436 tests in 0.983s

I tried naively changing the value to 16 on line 910 of the test but the test then fails for python2. I'm not sure what the right change is. https://github.com/beetbox/mediafile/blob/master/test/test_mediafile.py#L910

MediaFile: More general comments field in ID3

An outgrowth of #1043, courtesy of @kiefermat.

Apparently, some software uses COMM frames with funky desc fields to store comments. (Most software uses an empty desc field.) We should probably read these various frames and interpret them as comments.

The question gets a little trickier when writing. I lean toward automatically "standardizing" these fields when MediaFile needs to update the tag—i.e., we should drop any frames with custom desc fields and just preserve the descless frame. That would require a bit more machinery than we currently have in MP3DescStorageStyle.

0.10.0 test failure

I'm getting a test failure in the 0.10.0 release (Arch Linux, python 3.10.8), is that an oversight?

..............................................................................................................................................................................................................................................................................................................................................F.....................................................................................................................................
======================================================================
FAIL: test_read_audio_properties (test.test_mediafile.WAVETest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/build/python-mediafile/src/mediafile/test/test_mediafile.py", line 445, in test_read_audio_properties
    self.assertEqual(getattr(mediafile, key), value)
AssertionError: 705600 != 88200
----------------------------------------------------------------------
Ran 468 tests in 0.563s
FAILED (failures=1)

Support filelike objects, not only pathes

Hi!
I'm trying to use this library with remote files defined as file-likes in python.
mutagen supports file-like interface, why tho mediafile doesn't?
Docs say it needs local file path as first argument.

PyPi version is still 0.3.0

Working on a personal project and noticed that the PyPi release hasn't been updated to 0.4.0 yet. Thought I would bring it to your attention since it seems likely that it was an oversight.

Failing test in AIFFTest.test_read_audio_properties

The test suite is currently failing across both Python2 and Python3, on multiple Linux distributions:

.........F........................................................................................................................................................................................................................................................................................................................................................................................................................................
======================================================================
FAIL: test_read_audio_properties (test.test_mediafile.AIFFTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/apetresc/src/arch/python-mediafile/src/python3/test/test_mediafile.py", line 441, in test_read_audio_properties
    self.assertEqual(getattr(mediafile, key), value)
AssertionError: 16 != 0

----------------------------------------------------------------------
Ran 434 tests in 0.663s

FAILED (failures=1)

This is blocking the Arch Linux AUR package (among, probably, many others) for everyone.

Tests for saving ID3v2.3

I think we should have some tests for this as It's supported but not checked if works.
I'm pretty sure big part of multi-valued tags would fail and this should be only expected failure.

mb_artistid and mb_albumartistid should be lists

Hey!
When trying to fix my PR (#42) I found error I can't fix myself.

mb_artistid and mb_albumartistid should be lists!
mediafile's version:

>>> mf = MediaFile('/home/juniorjpdj/temp/Szpadyzor crew.flac')
>>> mf.mb_artistid
'164ed128-525d-4798-883f-be13502de86b'
>>> mf.mb_albumartistid
'164ed128-525d-4798-883f-be13502de86b'

Picard is tagging it like that (mutagen dump):
FLAC: 'musicbrainz_artistid': ['164ed128-525d-4798-883f-be13502de86b', 'ded6b91b-26d8-4bc0-8aa9-fab9b54cd157'],
MP3 (ID3v2.3): 'TXXX:MusicBrainz Artist Id': TXXX(encoding=<Encoding.UTF16: 1>, desc='MusicBrainz Artist Id', text=['ca780457-5bf6-4a7d-95fa-0d0d4920f26f/258a67d1-172d-4d16-8d6c-09efde60896f/af262d86-542d-4864-8527-083065166d6c']),

Fixing FLAC parsing is easy I can't make it work in MP3 case.

Current code is returning only the first author in case of FLAC and '/' separated string in case of MP3.

Helping fixing this will also help me solve some problems with #42 ;D

Empty fields returning None

Going off the docs.

MediaFile attempts to always return a usable value (i.e., it never returns None or throws an exception when a tag is accessed). If a tag is not present, an empty and false value of the appropriate type – such as zero or the empty string – is returned.

>>> f = MediaFile('tests/resources/audio_files/empty.mp3')
>>> print(f.title)
None

Is this going against expected behavior or maybe the docs are out of date?

Crash on import of library.

I started the import run for the first time, and it got about ten albums in, and this happened.
The import will not proceed past this problem.

beet crash.txt
.
Please let me know what other information I need to provide here to assist you.

New deprication warning

While testing beets with pytest under windows python 3.12 the following warning appears:


C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\mediafile.py:52
  C:\Users\arogl\AppData\Local\Programs\Python\Python312\Lib\site-packages\mediafile.py:52: DeprecationWarning: 'imghdr' is deprecated and slated for removal in Python 3.13
    import imghdr

Tests failing on NixOS

While packaging mediafile 0.5.0 for NixOS I encountered a test failure:

python2.7-mediafile> ======================================================================
python2.7-mediafile> FAIL: test_known_fields (test.test_mediafile.MediaFieldTest)
python2.7-mediafile> ----------------------------------------------------------------------
python2.7-mediafile> Traceback (most recent call last):
python2.7-mediafile> File "/build/mediafile-0.5.0/test/test_mediafile.py", line 979, in test_known_fields
python2.7-mediafile> assertCountEqual(self, MediaFile.fields(), fields)
python2.7-mediafile> File "/nix/store/k948hw0if2rsyicvxgqa07mpfjqsr0gv-python2.7-six-1.15.0/lib/python2.7/site-packages/six.py", line 679, in assertCountEqual
python2.7-mediafile> return getattr(self, _assertCountEqual)(*args, **kwargs)
python2.7-mediafile> AssertionError: Element counts were not equal:
python2.7-mediafile> First has 1, Second has 0:  u'read_only_test'
python2.7-mediafile> ----------------------------------------------------------------------
python2.7-mediafile> Ran 436 tests in 1.072s
python2.7-mediafile> FAILED (failures=1)
python2.7-mediafile> Test failed: <unittest.runner.TextTestResult run=436 errors=0 failures=1>
python2.7-mediafile> error: Test failed: <unittest.runner.TextTestResult run=436 errors=0 failures=1>
builder for '/nix/store/av1l4k090h4sphyn8glj1nj3i1lcdh6a-python2.7-mediafile-0.5.0.drv' failed with exit code 1; last 10 log lines:
      return getattr(self, _assertCountEqual)(*args, **kwargs)
  AssertionError: Element counts were not equal:
  First has 1, Second has 0:  u'read_only_test'

  ----------------------------------------------------------------------
  Ran 436 tests in 1.072s

  FAILED (failures=1)
  Test failed: <unittest.runner.TextTestResult run=436 errors=0 failures=1>
  error: Test failed: <unittest.runner.TextTestResult run=436 errors=0 failures=1>

The tests seem to pass with Python 3.8, however

The m4a label tag should be in all caps

The other day I noticed that a lot of my files were missing label info in the beets database, despite them being present on the files. After a little looking, I realized that the beets tag definition was cased differently than how its listed on MusicBrainz tag mapping page.

The code in question:
https://github.com/beetbox/beets/blob/7b910c3fde50d502e63b890f1ffbaf3d59515c0e/beets/mediafile.py#L1736

On https://picard.musicbrainz.org/docs/mappings/ it is listed as:

----:com.apple.iTunes:LABEL

I ended up just replacing it on my machine for the quick fix(which worked, but probably not ideal for the official fix).

six usage is redundant

Could you please eventually consider to drop dependency on six as long as you declare only python 3 support?

In MP3s, TXXX fields are always case insensitive

Beets seems to write replaygain tags in upper-case regardless of changelog entry 1.3.2 (https://beets.readthedocs.io/en/stable/changelog.html#december-22-2013)
There are music player in the wild which only understand lower-case ReplayGain tags (Poweramp, KODI),

Using an actual version of a of Beets I can only find upper-case ReplayGain tags in my tagged files with a hex editor.

How I reproduced it:

First of all I download a clean WAV file from bandcamp.com for example. I convert the WAV file to a mp3 via Foobar using the Lame mp3 encoder. After that this mp3 goes into Picard. This goes through processing by Beets. For this I use a Docker Beets version (https://hub.docker.com/r/linuxserver/beets). After that I get a mp3 file including replay gain tags: 03 - New Light.mp3

03.-.New.Light.zip

Using a hex editor I only find upper-case ReplayGain tags in the header of the file.

192885491-bf485e2e-22b7-48fb-8386-0ed8d8900031

I tried beet write (files have not changed) and beet write -f (files have changed) but the mp3 files still only have upper-case ReplayGain tags.

I also tried: I have completely deleted the ReplayGain tags from a series of files with zero and checked that they are really gone in the library (info) and the mp3 files. After that I re-tagged them with replaygain (replaygain). After that I found the ReplayGain tags again, only in upper-case.

I changed the lines of code in mediafile.py (

mediafile/mediafile.py

Lines 2202 to 2209 in edc6414

MP3DescStorageStyle(
u'REPLAYGAIN_ALBUM_GAIN',
float_places=2, suffix=u' dB'
),
MP3DescStorageStyle(
u'replaygain_album_gain',
float_places=2, suffix=u' dB'
),
) to see what tags are written. After applying scrub and relaygain again, I suddenly found two tags in my file, although with different names.
So when both are named differently, all of a sudden both show up. If both have the same name but are capitalized differently, they don't show up.

194117912-0c47220f-0332-4673-b2b3-2ef49e6a7eb8

194117932-44bebc12-37e3-46a3-ac4a-eabd21f8424a

Add additional ORIGINALDATE freeform mp4 tag for Plex support

It seems that Plex does not properly detect the com.apple.iTunes:ORIGINAL YEAR' freeform tag (presented as ORIGINAL YEAR by ffmpeg).

After searching around the web for a little, it seems that Plex relies on ffmpeg output to determine tags of certain files. I've confirmed with a small script (https://gist.github.com/chrisbenincasa/3b518514fd2b0d3cc494dce82b84b3a7) that setting ----:com.apple.iTunes:ORIGINALDATE on m4a files (mimicking behavior of Vorbis) allows Plex to recognize the tag.

It doesn't seem as if Picard defines a mapping for this field (https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html) but the popular Typescript music-metadata library has mappings for to ORIGINALYEAR and ORIGINALDATE: https://github.com/Borewit/music-metadata/blob/master/doc/common_metadata.md

One way to fix this would be to append a second tag for m4a called ORIGINALDATE. I'm not sure what the implications of changing the existing tag would be... It would probably also be beneficial to set ORIGINALYEAR in a separate tag.

List fields don't return None if the tag doesn't exist

If a list tag does not exist, it returns an empty list rather than None, but if a non-list tag does not exist, None is returned.

I believe non-existent list tags should also return None so that this behavior is consistent.

(Bug) import - mediafile.py issue

Problem

Running this command in verbose (-vv) mode:

$ beet -vv import . 

Led to this problem:

/home/home/src/beets/beets/mediafile.py:21: UserWarning: beets.mediafile is deprecated; use mediafile instead
  warnings.warn("beets.mediafile is deprecated; use mediafile instead")
....
....
....
Success. Distance: 0.49
Requesting MusicBrainz release 1e4666e0-bfd7-4e00-88b6-101d18fe024a
Sending event: mb_track_extract
Sending event: mb_track_extract
Sending event: mb_track_extract
primary MB release type: ep
Sending event: mb_album_extract
Sending event: albuminfo_received
Candidate: Nick Curly - Sun City EP (1e4666e0-bfd7-4e00-88b6-101d18fe024a)
Computing track assignment...
...done.
Success. Distance: 0.52
Evaluating 4 candidates.
Traceback (most recent call last):
  File "/home/home/miniconda3/bin/beet", line 11, in <module>
    load_entry_point('beets', 'console_scripts', 'beet')()
  File "/home/home/src/beets/beets/ui/__init__.py", line 1291, in main
    _raw_main(args)
  File "/home/home/src/beets/beets/ui/__init__.py", line 1278, in _raw_main
    subcommand.func(lib, suboptions, subargs)
  File "/home/home/src/beets/beets/ui/commands.py", line 973, in import_func
    import_files(lib, paths, query)
  File "/home/home/src/beets/beets/ui/commands.py", line 943, in import_files
    session.run()
  File "/home/home/src/beets/beets/importer.py", line 341, in run
    pl.run_parallel(QUEUE_SIZE)
  File "/home/home/src/beets/beets/util/pipeline.py", line 442, in run_parallel
    six.reraise(exc_info[0], exc_info[1], exc_info[2])
  File "/home/home/miniconda3/lib/python3.7/site-packages/six.py", line 693, in reraise
    raise value
  File "/home/home/src/beets/beets/util/pipeline.py", line 259, in run
    msg = next(self.coro)
  File "/home/home/src/beets/beets/importer.py", line 1320, in read_tasks
    for t in task_factory.tasks():
  File "/home/home/src/beets/beets/importer.py", line 1144, in tasks
    tasks = self._create(self.album(paths, dirs))
  File "/home/home/src/beets/beets/importer.py", line 1224, in album
    items = [item for item in items if item]
  File "/home/home/src/beets/beets/importer.py", line 1224, in <listcomp>
    items = [item for item in items if item]
  File "/home/home/src/beets/beets/importer.py", line 1273, in read_item
    return library.Item.from_path(path)
  File "/home/home/src/beets/beets/library.py", line 603, in from_path
    i.read(path)
  File "/home/home/src/beets/beets/library.py", line 710, in read
    value = getattr(mediafile, key)
  File "/home/home/miniconda3/lib/python3.7/site-packages/mediafile.py", line 1276, in __get__
    out = style.get(mediafile.mgfile)
  File "/home/home/miniconda3/lib/python3.7/site-packages/mediafile.py", line 612, in get
    return self.get_list(mutagen_file)[0]
  File "/home/home/miniconda3/lib/python3.7/site-packages/mediafile.py", line 619, in get_list
    return [self.deserialize(item) for item in self.fetch(mutagen_file)]
  File "/home/home/miniconda3/lib/python3.7/site-packages/mediafile.py", line 951, in fetch
    return sum([el.split('/') for el in frame.text], start=[])
TypeError: sum() takes no keyword arguments

This is only happening with some folders, but I can't pin-point to what exactly. I have had a few similar issues since the new release, and wondering if it's not related to the mediafile warning above

Setup

  • OS: debian
  • Python version: Python 3.7.4
  • beets version: 1.5.0
  • Turning off plugins made problem go away (yes/no):

My configuration (output of beet config) is:

acousticbrainz:
    auto: yes

badfiles:
    commands: {}
    #    commands:
    #    ogg: myoggchecker --opt1 --opt2
    #    flac: flac --test --warnings-as-errors --silent

chroma:
    auto: yes

convert:
    auto: no
    never_convert_lossy_files: yes
    quiet: false
    dest: /tmp/convert
    formats:
      alac:
        command: ffmpeg -i $source -y -vn -aq 2 $dest
        extension: flac

directory: /export/music/beet_library/

duplicates:
    album: yes
    path: yes

fetchart:
    auto: yes
    maxwidth: 1000
    cover_names: cover Cover front Front art album portada folder Folder
    google-key:
    sources:
        - filesystem
        - coverart: release
        - itunes
        - covertart: releasegroup
        - amazon
        - albumart
        - google
        - '*'

ftintitle:
    auto: yes

import:
    copy: no
    move: yes
    write: yes
    languages: en
    resume: yes
    autotag: yes

item_fields:
    multidisc: 1 if disctotal > 1 else 0
    genre_fix: genre.title()
    genre_no_space: genre.lower().replace(' ','_')

lastgenre:
    auto: yes
    fallback: 'unknown'
    source: artist
    canonical: ~/.config/beets/genres-tree.yaml
    whitelist: ~/.config/beets/beets_genre
    #prefer_specific: true

wlg:
    auto: no
    force: no
    count: 1
    separator: ', '
    whitelist: ~/.config/beets/beets_genre

library: /export/music/musiclibrary2.blb

replaygain:
    backend: ffmpeg

sort_item: albumartist+ album+ disc+ track+

spotify:
    mode: open
    region_filter: US
    show_failures: on
    tiebreak: popularity
    regex: [
        {
            field: "albumartist", # Field in the item object to regex.
            search: "Something", # String to look for.
            replace: "Replaced" # Replacement value.
        },
        {
            field: "title",
            search: "Something Else",
            replace: "AlsoReplaced"
        }
    ]


#the:
    #the: yes
    #a: yes
    #format: '{0}, {1}'
    #strip: no
#    patterns: []

threaded: yes

paths:
    default: '$genre_fix/%title{$albumartist}/$original_year - $album/%if{$multidisc,Disc $disc/}$track $title'
    albumtype:soundtrack: Soundtracks/$albumartist - $original_year - $album/%if{$multidisc,Disc $disc/}$track $title
    singleton: '$albumartist/$year -  $album/$track $title'
    mis:1: '$albumartist/$year - $album/$track $title'

per_disc_numbering: true

plugins:
    - acousticbrainz
    - artistcountry
    - badfiles
    - cmus
    - convert
    - discogs
    - duplicates
    - edit
    - fetchartist
    - fetchart
    - fromfilename
    - ftintitle
    - fuzzy
    - hook
    - importadded
    - info
    - inline
    - lastgenre
    - mbsync
    - play
    - random
    - replaygain
    - rewrite
    - scrub
    - smartplaylist
    - web
    - wlg

pluginpath:
    - ~/.config/beets/plugins/
    - ~/.config/beets/plugins/bandcamp/beetsplug
    - ~/.config/beets/plugins/airsonic/
    - ~/.config/beets/plugins/fetchartist/beetsplug/
    - ~/.config/beets/whatlastgenre/plugin/beets/beetsplug

# recreated at each run monthly import playlists
smartplaylist:
    relative_to: /export/music/beet_library# as setup on docker container
    playlist_dir: /export/music/playlists
    playlists:
        - name: 'New_%time{$added,%Y-%m}_$genre_no_space.m3u'
          query: 'added:2018-10..' # first month of using beet. monthly playlists will be created afterwards

hook:
  hooks:
    # renaming the "relative_to" part of the playlist created in smartplaylist so this can be used in the airsonic docker container automatically
    - event: cli_exit
      command: "sh -c 'bash /home/lbesnard/bin/beet_playlist_management.sh'"
    - event: import
      command: "sh -c 'bash /home/lbesnard/bin/beet_playlist_management.sh'"


    - event: import
      command: "sh -c 'sh /home/lbesnard/bin/airsonic_update_lib.sh'"

edit:
    itemfields: track title artist album albumartist genre year
    albumfields: album albumartist genre year

importadded:
    preserve_mtimes: yes
    preserve_write_mtimes: yes

play:
    command: mp3blaster --list

replace:
    '[\\/]': _
    '^\.':
    '[\x00-\x1f]': _
    '[<>:"\?\*\|]': _
    '\.$': _
    '\s+$': ''
    '^\s+': ''
    '[\xe2\x80\x90]': '-'
    '[\u2010]': '-'
    '': '-'
    '': "'"
    '': "'"

rewrite:
    artist The Jimi Hendrix Experience: Jimi Hendrix
    albumartist The Jimi Hendrix Experience: Jimi Hendrix
    artist .*Grateful Dead.*: Grateful Dead
    albumartist .*Grateful Dead.*: Grateful Dead
    artist .*Bill Monroe.*: Bill Monroe
    albumartist .*Bill Monroe.*: Bill Monroe
    #albumartist Alt-j: "alt-J"
    #albumartist Alt-j: "alt-J"

path_sep_replace: _

scrub:
    auto: yes

ui:
    color: yes
    text_success: green
    text_warning: yellow
    text_error: red
    text_highlight: red
    text_highlight_minor: lightgray
    action_default: turquoise
    action: blue

# http://akeil.net/listings/beets.config.yaml.html
# Auto Tagger ----------------------------------------------------------------

match:
    strong_rec_thresh: 0.1      # match 90% or better for auto import
    medium_rec_thresh: 0.25
    rec_gap_thresh: 0.25
    max_rec:
        missing_tracks: medium
        unmatched_tracks: medium
    distance_weights:
        source: 2.0
        artist: 3.0
        album: 3.0
        media: 1.0
        mediums: 1.0
        year: 1.0
        country: 0.5
        label: 0.5
        catalognum: 0.5
        albumdisambig: 0.5
        album_id: 5.0
        tracks: 2.0
        missing_tracks: 0.9
        unmatched_tracks: 0.6
        track_title: 3.0
        track_artist: 2.0
        track_index: 1.0
        track_length: 2.0
        track_id: 5.0
    preferred:
        countries: []
        media: []
        original_year: no
    ignored: []
    track_length_grace: 10
    track_length_max: 30

fetchartist:
    cover_name: "folder"

How to add custom field - ID3 Popularimeter

I need to read/write the ID3 Popularimeter tag within my app, specifically in the way that Native Instruments Traktor writes them.

This is a sample file containing the tag as written by Traktor:
https://github.com/ifischer/django-tracks-api/raw/master/tracks_api/tests/fixtures/popm.mp3

This is how mutagen-inspect shows it on command line:

$ mutagen-inspect tracks_api/tests/fixtures/popm.mp3
-- tracks_api/tests/fixtures/popm.mp3
- MPEG 1 layer 3, 32678 bps (VBR), 44100 Hz, 1 chn, 5.04 seconds (audio/mp3)
[email protected]=0 102/255
TSSE=Lavf57.83.100

So far I'm using pure mutagen in my app to do it:

from mutagen.id3 import ID3
from mutagen.id3 import POPM

ID3_POPM = 'POPM'

class SimpleID3(ID3):
    def __init__(self, filename):
        super().__init__(filename)

    @property
    def rating(self):
        rating = self.getall(ID3_POPM)
        if rating:
            rating = rating[0].rating
            return int(rating / 51)
        return None

    @rating.setter
    def rating(self, rating: int):
        popm = POPM(email='[email protected]', rating=rating * 51, count=0)
        self[ID3_POPM] = popm

How can I achieve something similar with mediafile, adding the popularimeter tag as a custom field?

mediafile saves track to multiple vorbis comment fields

Simple reproduction:

Get empty file:

$ ffmpeg -f lavfi -i 'anullsrc=channel_layout=5.1:sample_rate=48000' -t 1 file.flac

Write track field

>>> from mediafile import MediaFile
>>> f = MediaFile('file.flac')
>>> f.track
>>> f.track = 1
>>> f.save()
>>> f.track
1

View result

$ metaflac --list "file.flac"
METADATA block #0
  type: 0 (STREAMINFO)
  is last: false
  length: 34
  minimum blocksize: 4608 samples
  maximum blocksize: 4608 samples
  minimum framesize: 26 bytes
  maximum framesize: 28 bytes
  sample_rate: 48000 Hz
  channels: 6
  bits-per-sample: 16
  total samples: 48000
  MD5 signature: 0dd0e989e9556334ac746c39d72d6aea
METADATA block #1
  type: 4 (VORBIS_COMMENT)
  is last: false
  length: 116
  vendor string: Lavf58.76.100
  comments: 4
    comment[0]: encoder=Lavf58.76.100
    comment[1]: WAVEFORMATEXTENSIBLE_CHANNEL_MASK=0x3f
    comment[2]: TRACK=1
    comment[3]: TRACKNUMBER=1
METADATA block #2
  type: 1 (PADDING)
  is last: true
  length: 8164

Specifically the TRACK and TRACKNUMBER fields. This is the case in all the files in my collection that are managed by beets. I haven't noticed this before, but I recently switched to ncmpc (for mpd), and noticed that the %track% format specifier outputs 1, 1. I saw this issue (MusicPlayerDaemon/ncmpc#71) and asked about it in the #mpd irc channel, where they said the problem was with my files having multiple track tags. I don't know how standardized the tag keys are, or where this bug belongs, but I'm filing this issue if it should be fixed here.

Side note: I also noticed this happens for a couple other fields like disc number as well

ID3v2.3 multi-value field separator is always "/"

For some libraries, users might decide to store ID3v2.3 tags for greater compatibility with older software (as opposed to the ID3v2.4 default).

Now ID3v2.4 allows storing multiple tags of the same name (for multi-value entries like artists, genres and so on) and ID3v2.3 traditionally used a slash "/" character (which brought us the "AC/DC problem").

People (and tagging software like MusicBrainz Picard) have started to support other separators to store multiple values on one ID3v2.3 field. Typical separators used today are the semicolon ;, the vertical bar |, a comma , the NULL character \0 and even character sequences like semicolon blank ; for better readability. The underlying Mutagen supports all of these by specifying v23_sep.

This is a missing feature in MediaFile (and beets) and I’d like to add it to the MediaFile class so it could also be supported via a beets config entry:

class MediaFile(object):
    """Represents a multimedia file on disk and provides access to its
    metadata.
    """
    def __init__(self, path, id3v23=False, id3v23_sep='/'):
        """Constructs a new `MediaFile` reflecting the file at path. May
        throw `UnreadableFileError`.

        By default, MP3 files are saved with ID3v2.4 tags. You can use
        the older ID3v2.3 standard by specifying the `id3v23` option
        and (optionally) the desired separator `id3v23_sep` for
        multi-value fields (defaults to a slash character).

        To use a NULL character as terminator, pass `id3v23_sep=None`.
        """

Objections?
Would it need a u'/' instead?

N.B.: Making this a core config entry in beets should also help some plugins who currently specify their own separators.

Version bump to down integrate to beets

Hello, I'm just wondering what the release process is for this repo. A few months ago I authored 93c6c3b which unfortunately still hasn't been tied to an official release of this library, from what I can tell. Im hoping that we could get a release here so that I could potentially bump the version in beets and take advantage of the commit. Thanks!

Exception when loading WAV-files

Whenever I try to load a WAV file I get this exception:

>>> import mediafile
>>> mediafile.MediaFile("file_example_WAV_1MG.wav")Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/postlund/pyatv_dev/pyatv/lib/python3.8/site-packages/mediafile.py", line 163, in wrapper    return mutagen_call('loadfile', '', f, *args, **kwargs)
  File "/home/postlund/pyatv_dev/pyatv/lib/python3.8/site-packages/mediafile.py", line 135, in mutagen_call
    return func(*args, **kwargs)
  File "/home/postlund/pyatv_dev/pyatv/lib/python3.8/site-packages/mutagen/_util.py", line 156, in wrapper
    return func(self, h, *args, **kwargs)
  File "/home/postlund/pyatv_dev/pyatv/lib/python3.8/site-packages/mediafile.py", line 1595, in __init__
    raise FileTypeError(self.filename, type(self.mgfile).__name__)
mediafile.FileTypeError: 'file_example_WAV_1MG.wav': of mutagen type WAVE

Loading it in mutagen directly seems to work fine though:

>>> import mutagen
>>> mutagen.File("file_example_WAV_1MG.wav")
{'TCON': TCON(encoding=<Encoding.LATIN1: 0>, text=['Cinematic']), 'TALB': TALB(encoding=<Encoding.LATIN1: 0>, text=['YouTube Audio Library']), 'TIT2': TIT2(encoding=<Encoding.LATIN1: 0>, text=['Impact Moderato']), 'TPE1': TPE1(encoding=<Encoding.LATIN1: 0>, text=['Kevin MacLeod'])}

I'm using this file as an example, but the same thing happens with other WAV files too.

Tests can’t run without being packages ("ImportError: cannot import name _common")

Under Python 3 (python3 -m nose):

EE
======================================================================
ERROR: Failure: ImportError (cannot import name '_common' from 'test' (/usr/lib/python3.7/test/__init__.py))
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/nose/failure.py", line 39, in runTest
    raise self.exc_val.with_traceback(self.tb)
  File "/usr/lib/python3.7/site-packages/nose/loader.py", line 417, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python3.7/site-packages/nose/importer.py", line 47, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python3.7/site-packages/nose/importer.py", line 94, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/usr/lib/python3.7/imp.py", line 234, in load_module
    return load_source(name, filename, file)
  File "/usr/lib/python3.7/imp.py", line 171, in load_source
    module = _load(spec)
  File "<frozen importlib._bootstrap>", line 696, in _load
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/tmp/makepkg/python-mediafile/src/python3/test/test_mediafile.py", line 28, in <module>
    from test import _common
ImportError: cannot import name '_common' from 'test' (/usr/lib/python3.7/test/__init__.py)

======================================================================
ERROR: Failure: ImportError (cannot import name '_common' from 'test' (/usr/lib/python3.7/test/__init__.py))
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/nose/failure.py", line 39, in runTest
    raise self.exc_val.with_traceback(self.tb)
  File "/usr/lib/python3.7/site-packages/nose/loader.py", line 417, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python3.7/site-packages/nose/importer.py", line 47, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python3.7/site-packages/nose/importer.py", line 94, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/usr/lib/python3.7/imp.py", line 234, in load_module
    return load_source(name, filename, file)
  File "/usr/lib/python3.7/imp.py", line 171, in load_source
    module = _load(spec)
  File "<frozen importlib._bootstrap>", line 696, in _load
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/tmp/makepkg/python-mediafile/src/python3/test/test_mediafile_edge.py", line 25, in <module>
    from test import _common
ImportError: cannot import name '_common' from 'test' (/usr/lib/python3.7/test/__init__.py)

----------------------------------------------------------------------
Ran 2 tests in 0.025s

FAILED (errors=2)

Under Python 2 (python2 -m nose):

EE
======================================================================
ERROR: Failure: ImportError (cannot import name _common)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/nose/loader.py", line 418, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python2.7/site-packages/nose/importer.py", line 47, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python2.7/site-packages/nose/importer.py", line 94, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/tmp/makepkg/python-mediafile/src/python2/test/test_mediafile.py", line 28, in <module>
    from test import _common
ImportError: cannot import name _common

======================================================================
ERROR: Failure: ImportError (cannot import name _common)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/nose/loader.py", line 418, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python2.7/site-packages/nose/importer.py", line 47, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python2.7/site-packages/nose/importer.py", line 94, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/tmp/makepkg/python-mediafile/src/python2/test/test_mediafile_edge.py", line 25, in <module>
    from test import _common
ImportError: cannot import name _common

----------------------------------------------------------------------
Ran 2 tests in 0.140s

FAILED (errors=2)

Same as with beetbox/confuse#54, this is needed to run tests during packaging at a stage after building but before packaging/installing.

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.