使用Python进行部分下载提取MP3 URL的ID3标签

8

我需要提取远程mp3文件的ID3标签和元数据。

我写了几行代码可以获取本地文件的ID3标签:

from mutagen.mp3 import MP3
import urllib2

audio = MP3("Whistle.mp3")

songtitle = audio["TIT2"]
artist = audio["TPE1"]

print "Title: " + str(songtitle)
print "Artist: "+str(artist)

我需要为mp3文件的url链接实现这个功能。我尝试使用urllib2来获取文件的部分下载。

import urllib2
from mutagen.mp3 import MP3

req = urllib2.Request('http://www.1songday.com/wp-content/uploads/2013/08/Lorde-Royals.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)

如何在不完全下载文件的情况下提取MP3 URL的ID3标签?


你已经成功获取了 MP3 文件的前 100 个字节,你现在卡在哪里了? - scav
2
啊,看起来id3标签在文件的最后128个字节。所以,除非你知道文件的大小,否则你将无法制作一个范围头来获取它们。也许可以先使用HEAD请求获取文件的长度... - scav
2个回答

2
ID3标签存储在ID3元数据中,通常位于mp3帧(包含音频)之前,但是mp3标准也允许它们"跟随mp3帧"
为了下载最少数量的字节,您需要:
  1. 下载mp3的前10个字节,提取ID3v2头,并计算id3v2头的大小
  2. 要检索完整的id3v2标签,请下载size字节的mp3
  3. 使用Python库提取ID3标签
这是一个提取专辑封面的脚本(Python 2或3),下载量最小:
try:
    import urllib2 as request # python 2
except ImportError:
    from urllib import request # python 3
    from functools import reduce
import sys
from io import BytesIO
from mutagen.mp3 import MP3

url = sys.argv[1]

def get_n_bytes(url, size):
    req = request.Request(url)
    req.headers['Range'] = 'bytes=%s-%s' % (0, size-1)
    response = request.urlopen(req)
    return response.read()

data = get_n_bytes(url, 10)
if data[0:3] != 'ID3':
    raise Exception('ID3 not in front of mp3 file')

size_encoded = bytearray(data[-4:])
size = reduce(lambda a,b: a*128+b, size_encoded, 0)

header = BytesIO()
# mutagen needs one full frame in order to function. Add max frame size
data = get_n_bytes(url, size+2881) 
header.write(data)
header.seek(0)
f = MP3(header)

if f.tags and 'APIC:' in f.tags.keys():
    artwork = f.tags['APIC:'].data
    with open('image.jpg', 'wb') as img:
       img.write(artwork)

一些说明:
  • 它检查ID3是否在文件前面,并且它是ID3v2
  • ID3标签的大小存储在第6到9个字节中,如id3.org上所述
  • 不幸的是,mutagen需要一个完整的mp3音频帧来解析id3标签。因此,您还需要下载一个mp3帧(根据这个评论,最长为2881字节)
  • 与其盲目地假设专辑封面是jpg格式,您应该首先检查图像格式,因为id3 允许许多不同的图像类型
  • 使用大约10个来自互联网的随机mp3进行测试,例如: python url.py http://www.fuelfriendsblog.com/listenup/01%20America.mp3

0
在你的例子中,ID3标签没有被获取,因此你无法提取它们。
我在阅读了ID3规范后进行了一些尝试,这里有一个很好的入门方法。
#Search for ID3v1 tags
import string
tagIndex = string.find(data,'TAG')
if (tagIndex>0):
  if data[tagIndex+3]=='+': 
    print "Found extended ID3v1 tag!"
    title = data[tagIndex+3:tagIndex+63]
    print title
  else:
    print  "Found ID3v1 tags"
    title = data[tagIndex+3:tagIndex+33]
    print title
    #So on.
else:
  #Look for ID3v2 tags
  if 'TCOM' in data:
    composerIndex = string.find(data,'TCOM')
    #and so on. See wikipedia for a full list of frame specifications

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接