2017-01-19 14 views
1

リモートmp3ファイルからカバーアートを抽出し、mp3全体をダウンロードすることなくファイルに保存する必要があります。しかし、私はそれで成功していない。私はID 3個のタグがmp3の最後の128バイトであることについて読んだリモートmp3からカバーアートを抽出する

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) 

:私のようなファイルの最初の100のバイトをダウンロードしようとしています。今、私はapicカバーアートを含む最後のバイトのみをダウンロードし、イメージを抽出するための助けが必要です。

+0

あなたの例でリンクしているmp3にはアートワークが添付されていません。アートワークを提供できますか? – hansaplast

+0

私はこのmp3 VLCをダウンロードした場合、いくつかのカバーアートを見せます...もう一度お待ちください – fteinz

+0

あなたはLinuxやWindowsを使用していますか? mp3ファイル – hansaplast

答えて

2

秘密の芸術を私を助けるため

おかげでID3v2のタグ内のファイルの先頭にあります。

ここではハックの解決策があります:ファイル全体が読み込まれるか、mutagenがエラーになるまで読み込みます。 mp3がmp3でない場合には、これはファイル全体を読むでしょう。理想的には、バッファリングを行うようなシーク可能なファイルを渡すのが理想的です。おそらくそのためのライブラリがあります。

# 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()) 
+0

これはファイル全体をダウンロードしないかどうかチェックしましたか?ヘッダーに 'Range'を指定しないと、' read'に数バイトしかロードしないと言っても、ファイル全体をダウンロードしていると思いますか? – hansaplast

+0

@hansaplastわかりません。 "strace -y -e recvfrom python foo"を使ってみてください。py "は少なくともファイル全体をロードしていないことを示します。 – lazka

0

ID3タグは通常 mp3ファイルの前ではなく、背中です。 mp3 formatは最後にID3タグを持っていましたが、インターネットからいくつかのランダムなmp3をチェックしました。

あなたは(あなたがあなたの携帯電話ユーザーの帯域幅を無駄にしたくないよう)のみバイトの絶対最小値をダウンロードしたい場合は、あなたがする必要があります:10バイトとチェックの部分的なダウンロードを行う

  1. ID3タグがファイルの前にあることを確認します。ない場合は、次のバイト6-9からサイズを抽出し、ファイル全体
  2. をダウンロード
  3. は、あなただけの
  4. を計算したサイズの新鮮な部分ダウンロードを行う(バイトは described on id3.orgとして、左端のビットは常にゼロに設定されていることに注意してください)

その後、完全なID3タグをダウンロードして抽出することができます。今、mutagenには、最初のmp3オーディオフレームもダウンロードする必要があるという制限があります。それ以外の場合は例外がスローされます:mutagen.mp3.HeaderNotFoundError: can't sync to an MPEG frame。その制限があなたのために大丈夫ならば、私はposted a python solution at a similar questionです(実際これは重複しているかもしれませんが、質問のソースコードもあなたの質問にコピーされているのがわかります)。

ダウンロードサイズを最小限に抑えたい場合は、few other modulesを試してみてください。うまくいけば、最初のオーディオフレームもダウンロードする必要はありません。

関連する問題