Reputation: 1095
I need to extract a cover art from a remote mp3 file and save it to a file without downloading the whole mp3. But I have no success with it. I have try to download the first 100 bytes of the file like:
import urllib2
from mutagen.mp3 import MP3
req = urllib2.Request('http://www.stephaniequinn.com/Music/Commercial%20DEMO%20-%2001.mp3')
req.headers['Range'] = 'bytes=%s-%s' % (0, 100)
response = urllib2.urlopen(req)
headers = response.info()
print headers.type
print headers.maintype
data = response.read()
print len(data)
I have read about that the id 3 Tags are at the last 128 bytes of a mp3. Now I need some help help to download only the last bytes that contains the apic cover art and extract the image.
thanks for helping me out
Upvotes: 1
Views: 2043
Reputation: 11573
ID3 tags are usually in front of the mp3 files, not in the back. I checked some random mp3s from the internet and they had all their ID3 tags in front, although the mp3 format allows them to have it at the end.
If you want to only download the absolute minimum of bytes (as you don't want to waste your mobiles users bandwidth) you'll need to:
After that you'll have downloaded the full ID3 tags and can extract them. Now, mutagen has the limitation that you need to download the first mp3 audio frame as well, otherwise it will throw an exception: mutagen.mp3.HeaderNotFoundError: can't sync to an MPEG frame
. If that limitation is ok for you I posted a python solution at a similar question (in fact this is probably a duplicate, I see you also have copied the source code from the question into your question).
If you absolutely want to minimize your download size then you'd probably want to try a few other modules which hopefully don't require to also download the first audio frame.
Upvotes: 0
Reputation: 743
The covert art is at the beginning of the file in an id3v2 tag.
Here is a hacky solution: read until the whole file is read or mutagen doesn't error out. This would read the whole file in case the mp3 isn't an mp3. Ideally you'd pass it a seekable file-like which does buffering, maybe there is a library for that.
# Python 2 or 3
try:
import urllib2 as request
except ImportError:
from urllib import request
from io import BytesIO
from mutagen import MutagenError
from mutagen.mp3 import MP3
def get_mp3(url):
"""
Args:
url (str)
Returns:
mutagen.mp3.MP3
Raises:
mutagen.MutagenError
EnvironmentError
"""
r = request.urlopen(url)
try:
size = 128
filelike = BytesIO()
while 1:
data = r.read(size)
size *= 2
filelike.seek(0, 2)
filelike.write(data)
filelike.seek(0)
try:
return MP3(filelike)
except MutagenError:
if not data:
raise
pass
finally:
r.close()
try:
f = get_mp3("http://web.ist.utl.pt/antonio.afonso/www.aadsm.net/libraries/id3/music/Bruno_Walter_-_01_-_Beethoven_Symphony_No_1_Menuetto.mp3")
except (MutagenError, EnvironmentError):
pass
else:
if f.tags:
for frame in f.tags.getall("APIC"):
print(frame.pprint())
Upvotes: 2