【问题标题】:Extract ID3 tags of a MP3 URL with partial download using python使用python提取带有部分下载的MP3 URL的ID3标签
【发布时间】:2015-01-09 10:38:45
【问题描述】:

我需要提取远程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 个字节。你被困在哪里了?
  • 啊,看起来 id3 标签位于文件的最后 128 个字节中。因此,除非您知道文件的大小,否则您将无法制作 Range 标头来获取它们。也许一个 HEAD 请求可以先获取文件的长度...

标签: python metadata id3 mutagen


【解决方案1】:

id3 标签存储在 ID3 元数据中,该元数据通常在 mp3 帧(包含音频)的前面,但 mp3 标准也允许它们"follow the mp3 frames"

要下载最少字节数,您需要:

  1. 下载 mp3 的前 10 个字节,提取 ID3v2 标头并计算 id3v2 标头的大小
  2. 要检索完整的 id3v2 标签下载 mp3 的 size 字节
  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中,如documented on id3.org
  • 不幸的是,mutagen 需要一个完整的 mp3 音频帧来解析 id3 标签。因此,您还需要下载一个 mp3 帧(根据this comment,最长为 2881 字节)
  • 不要盲目地假设专辑封面是 jpg 你应该首先检查图像格式为 id3 allows many different image types
  • 使用来自互联网的大约 10 个随机 mp3 进行测试,例如这个:python url.py http://www.fuelfriendsblog.com/listenup/01%20America.mp3

【讨论】:

    【解决方案2】:

    在您的示例中,未获取 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
    

    【讨论】:

      猜你喜欢
      • 2011-09-02
      • 2011-09-14
      • 1970-01-01
      • 2010-10-18
      • 2011-09-12
      • 2012-10-22
      • 1970-01-01
      • 2012-02-25
      • 1970-01-01
      相关资源
      最近更新 更多