mutagen
mutagen copied to clipboard
No io.BytesIO support in mutagen.File function
I need to open the file from BytesIO
but mutagen
doesn't allow me to use it.
is_fileobj
: Broken - doesn't checks anything for real (almost any types is not str
or bytes
). You can use runtime_checkable
protocols for example (or abstract classes from standart library)
https://github.com/quodlibet/mutagen/blob/30f373fa6d56e1afa17d48a0c6f3e111267fbd32/mutagen/_util.py#L62-L69
_openfile
: Useless check - FileThing
is just a container but isinstance
check deny to use user containers variants. Consider to add special class or make FileThing
public (PyCharm warning: Access to a protected member _util of a module
) (for now you can just check attributes of filething by hasattr as you do in other places)
https://github.com/quodlibet/mutagen/blob/30f373fa6d56e1afa17d48a0c6f3e111267fbd32/mutagen/_util.py#L219-L223
You know, that's very funny when open is not supported BytesIO
but save supports.
For now temporary solution is to use ThingFile
from non-public module _util.py
If you now the correct way to use BytesIO in mutagen, let me now. P.S. Mutagen code is awful, have a nice day :D
import io
import urllib.request
import mutagen
r = urllib.request.urlopen("https://opus-codec.org/static/examples/ehren-paper_lights-96.opus")
f = io.BytesIO(r.read())
print(mutagen.File(f))
P.S. Mutagen code is awful, have a nice day :D
yeah, this was all added years later while trying to not break existing users, so lots of hacks and magic in that area...
Mutagen waits that music will have ID3 tag, but it may not (most common situation for me is mp3/m4a music file without tag header - I create it with my code). https://github.com/quodlibet/mutagen/blob/master/mutagen/mp3/init.py#L458-L461
But here we have only pure BytesIO (with music content) so Kinds have 0 score.
Debugger: results = [(0, 'MP3'), (0, 'TrueAudio'), (0, 'OggTheora'), (0, 'OggSpeex'), (0, 'OggVorbis'), (0, 'OggFLAC'), (0, 'FLAC'), (0, 'AIFF'), (0, 'APEv2File'), (0, 'MP4'), (False, 'ID3FileType'), (0, 'WavPack'), (0, 'Musepack'), (0, 'MonkeysAudio'), (0, 'OptimFROG'), (0, 'ASF'), (0, 'OggOpus'), (0, 'AAC'), (0, 'AC3'), (False, 'SMF'), (0, 'TAK'), (0, 'DSF'), (0, 'DSDIFF'), (0, 'WAVE')]
https://github.com/quodlibet/mutagen/blob/master/mutagen/_file.py#L289-L290
Funny story that I have codec from service (but I cannot be sure that I will cover any cases), so I want to use this codec within BytesIO.
class Descriptor:
...
@contextlib.asynccontextmanager
async def to_track(self) -> AsyncIterator[mutagen.FileType]:
async with aiofiles.open(self.__filepath, "br") as file:
buffer = io.BytesIO(await file.read())
logging.debug("BUFFER IS READY")
# if (track := mutagen.File(FileThing(buffer, self.__filepath.name, self.__filepath.name))) is None:
if (track := mutagen.File(buffer)) is None:
logging.debug("MUTAGEN ERROR")
raise RuntimeError
...
This is an example from my application (for now I totally rewrite it and public ready pieces in my GitHub). Commented line is solution.
If you have the solution for BytesIO + codec
- let me know. Because I don't want to use music formats directly
I see, thanks. So we need some way to pass a filename as a hint for the type selection.