beets icon indicating copy to clipboard operation
beets copied to clipboard

error reading /tmp/tmpf3ev1x9k.mp3: can't sync to MPEG frame

Open MahirAbbas opened this issue 8 months ago • 14 comments

Problem

Running this command in verbose (-vv) mode:

$ beet -vv import -A "(any song or directory)"

Led to this problem:

user configuration: /home/user/.config/beets/config.yaml
data directory: /home/user/.config/beets
plugin paths: 
lyrics: Disabling google source: no API key configured.
Sending event: pluginload
library database: /home/user/Music/.database/musiclibrary.db
library directory: /home/user/Music
Sending event: library_opened
Sending event: import_begin
Sending event: import_task_created
/home/user/download/01 - Trojan Horse.flac
Replacing item 27979: /home/user/download/01 - Trojan Horse.flac
Sending event: database_change
Sending event: database_change
Sending event: album_removed
Sending event: item_removed
1 of 1 items replaced
Sending event: database_change
Sending event: database_change
Sending event: database_change
Sending event: database_change
Sending event: database_change
Sending event: database_change
Reimported album: added 1702122116.4249115, flexible attributes [] from album 3481 for /home/user/download
Reimported item added 1702122116.4423912 from item 27979 for /home/user/download/01 - Trojan Horse.flac
Reimported item flexible attributes [] from item 27979 for /home/user/download/01 - Trojan Horse.flac
Sending event: database_change
convert: Encoding /home/user/download/01 - Trojan Horse.flac
convert: Finished encoding /home/user/download/01 - Trojan Horse.flac
Sending event: write
Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/mediafile.py", line 137, in mutagen_call
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/_util.py", line 168, in wrapper_func
    return func(h, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/_file.py", line 301, in File
    return Kind(fileobj, filename=filething.filename)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/_file.py", line 48, in __init__
    self.load(*args, **kwargs)
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/_util.py", line 160, in wrapper
    return func(self, h, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/id3/_file.py", line 421, in load
    self.info = self._Info(fileobj, offset)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/_util.py", line 189, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/mp3/__init__.py", line 402, in __init__
    raise HeaderNotFoundError("can't sync to MPEG frame")
mutagen.mp3.HeaderNotFoundError: can't sync to MPEG frame

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/beets/library.py", line 755, in write
    mediafile = MediaFile(syspath(path), id3v23=id3v23)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/mediafile.py", line 165, in wrapper
    return mutagen_call('loadfile', '', f, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/mediafile.py", line 137, in mutagen_call
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/mutagen/_util.py", line 160, in wrapper
    return func(self, h, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/mediafile.py", line 1580, in __init__
    self.mgfile = mutagen_call(
                  ^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/mediafile.py", line 140, in mutagen_call
    raise UnreadableFileError(filename, six.text_type(exc))
mediafile.UnreadableFileError: can't sync to MPEG frame

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/beets/ui/__init__.py", line 1285, in main
    _raw_main(args)
  File "/usr/lib/python3.11/site-packages/beets/ui/__init__.py", line 1272, in _raw_main
    subcommand.func(lib, suboptions, subargs)
  File "/usr/lib/python3.11/site-packages/beets/ui/commands.py", line 973, in import_func
    import_files(lib, paths, query)
  File "/usr/lib/python3.11/site-packages/beets/ui/commands.py", line 943, in import_files
    session.run()
  File "/usr/lib/python3.11/site-packages/beets/importer.py", line 340, in run
    pl.run_parallel(QUEUE_SIZE)
  File "/usr/lib/python3.11/site-packages/beets/util/pipeline.py", line 446, in run_parallel
    raise exc_info[1].with_traceback(exc_info[2])
  File "/usr/lib/python3.11/site-packages/beets/util/pipeline.py", line 311, in run
    out = self.coro.send(msg)
          ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/beets/util/pipeline.py", line 193, in coro
    func(*(args + (task,)))
  File "/usr/lib/python3.11/site-packages/beets/importer.py", line 1535, in plugin_stage
    func(session, task)
  File "/usr/lib/python3.11/site-packages/beets/plugins.py", line 145, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/beetsplug/convert.py", line 183, in auto_convert
    par_map(lambda item: self.convert_on_import(config.lib, item),
  File "/usr/lib/python3.11/site-packages/beets/util/__init__.py", line 1060, in par_map
    pool.map(transform, items)
  File "/usr/lib/python3.11/multiprocessing/pool.py", line 367, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/multiprocessing/pool.py", line 774, in get
    raise self._value
  File "/usr/lib/python3.11/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
                    ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/multiprocessing/pool.py", line 48, in mapstar
    return list(map(*args))
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/beetsplug/convert.py", line 183, in <lambda>
    par_map(lambda item: self.convert_on_import(config.lib, item),
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/beetsplug/convert.py", line 521, in convert_on_import
    item.write()
  File "/usr/lib/python3.11/site-packages/beets/library.py", line 757, in write
    raise ReadError(path, exc)
beets.library.ReadError: error reading /tmp/tmp6opl2rq7.mp3: can't sync to MPEG frame

error reading /tmp/tmp6opl2rq7.mp3: can't sync to MPEG frame

Here's a link to the music files that trigger the bug (if relevant): Any Music (Flac) file

Setup

  • OS: EndeavourOS (Arch)
  • Python version: 3.11.6
  • beets version: 1.6.0
  • Turning off plugins made problem go away (yes/no): yes (convert)

My configuration (output of beet config) is:

directory: ~/Music/
library: ~/Music/.database/musiclibrary.db
import:
    move: yes
plugins: badfiles duplicates replaygain fetchart embedart lyrics
convert:
    dest: ~/converted_music
    auto: yes
    copy_album_art: yes
    embed: yes
    never_convert_lossy_files: yes
    command: ffmpeg -i $source -vn -aq 2 $dest
    extension: mp3
replaygain:
    auto: yes
    backend: ffmpeg
fetchart:
    high_resolution: yes
    maxwidth: 3000
    quality: 80
embedart:
    ifempty: yes
    remove_art_file: yes
lyrics:
    auto: yes

MahirAbbas avatar Dec 09 '23 11:12 MahirAbbas

removing convert from YAML and then running beet convert after on the library works

MahirAbbas avatar Dec 09 '23 12:12 MahirAbbas

What sticks out here is that you seem to be importing a FLAC file, whereas mutagen (the library used to read/write tags) attempts to parse ID3 tags (but FLAC is usually tagged using Vorbis comments). I don't know any of these well, but I'd guess that there's something unusual about your input files, which gets fixed up when writing tags during the import process (but trips up the convert process otherwise).

wisp3rwind avatar Dec 10 '23 10:12 wisp3rwind

Indeed… is there any chance that the convert plugin is producing an invalid MP3 file? I'm not intimately familiar with the FFmpeg CLI, but is the command ffmpeg -i $source -vn -aq 2 $dest really guaranteed to produce an MP3, even when you feed it a FLAC input?

sampsyo avatar Dec 10 '23 17:12 sampsyo

Ive never had an issue before on FLAC files and my library is >13,000. My guess is that @wisp3rwind was correct about something unusual about the FLAC files. I'm pretty sure it should always be able to convert a FLAC file.

MahirAbbas avatar Dec 12 '23 09:12 MahirAbbas

A simple workaround that would be future-proof is to add a config setting that converts files after importing, instead of doing them as they are being imported. So a simple setting in the config thats something like convert_after_import: yes would likely skip issues like this in the future

MahirAbbas avatar Dec 12 '23 09:12 MahirAbbas

A simple workaround that would be future-proof is to add a config setting that converts files after importing, instead of doing them as they are being imported. So a simple setting in the config thats something like convert_after_import: yes would likely skip issues like this in the future

Sorry, but introducing a config option to "workaround" a bug that we don't even understand at this point seems like a really bad idea: There's no guarantee that it will even work in all the cases, and it does add real complexity to the code that we might be stuck with for backwards compatibility reasons.

Is there any chance you could provide one of the offending files (i.e. one with a sufficiently free license to allow sharing) so that someone (...) with the time to debug this could have a look at what might be the issue?

wisp3rwind avatar Dec 12 '23 10:12 wisp3rwind

I have quite a few of the files, but I don't think any of them have free licenses

MahirAbbas avatar Dec 12 '23 10:12 MahirAbbas

@wisp3rwind could I email you?

MahirAbbas avatar Dec 13 '23 11:12 MahirAbbas

Sorry, I don't have the time currently to investigate this myself. Hopefully someone else can!

wisp3rwind avatar Dec 14 '23 22:12 wisp3rwind

@MahirAbbas, one option might be to try running the relevant ffmpeg command on one of your files manually. Then, you can inspect the result and see if it looks suspicious. You could even try importing that pre-converted "MP3" file into beets, for example. This could help confirm whether it's an issue with your convert config.

sampsyo avatar Dec 15 '23 14:12 sampsyo

@sampsyo I've done all 3. The import without convert, with convert and running ffmpeg manually. It seems the issue is only when you import and convert at the same time. ffmpeg with the same command works fine, so it's not an ffmpeg/config issue (I've been using this config for more than a year with >10,000 songs). The issue seems to be when importing and converting, as mutagen cant match the metadata with ffmpeg.

MahirAbbas avatar Dec 19 '23 12:12 MahirAbbas

This seems to happen to every file now. Not sure why. This error only occurs on import. Is there a way to get even more verbose output?

MahirAbbas avatar Dec 22 '23 09:12 MahirAbbas

That's really mysterious! I think you're already at the most verbose level if you are using -vv.

It's onerous, but one possible way forward would be to somehow modify the convert plugin so it doesn't delete temporary files. Then maybe we can learn something by looking at those files directly and trying to decide why they're broken.

sampsyo avatar Dec 22 '23 13:12 sampsyo

@sampsyo do you know how to do that? I've found that it leved the tmp files, but they're empty.

MahirAbbas avatar Dec 26 '23 21:12 MahirAbbas