Jun 19, 2012

mutagen, python 处理音乐文件的Tag

Mutagen Tutorial
下面例子为 m4a 和 mp3 的 tag 处理。

注意,对于mp3,可能同时有多种 tag. 比如 mp3 文件同时有 apev2, id3v2, id3v1。这些 tag 存放的东西不一定一致。音乐播放软件会优先选取 apev2,然后是 id3v2。
用 python处理时也一样要看看有没有 apev2(用 foobar 看看文件有哪种 tag)。
第二个例子是 apev2的例子。

unicode 的幽灵
今天碰到一件怪事,下载了mp3,想修改名字为 tracknumber.ttitle
以“改变”为例
用python读取title,发现是
t = u'\xb8\xc4\xb1\xe4'
没有怀疑
t.encode('gbk')
报错,很郁闷,查了一个小时才知道怎么回事
原来,正确应该是
u'\xb8c4\xb1e4'
可能是转码的时候,把两个unicode字符,分成4个unicode字符了

修复技巧,foobar 选取,修改tag,随便修改一项
会改成 u'\xb8c4\xb1e4'

# -*- coding: utf-8 -*-

from mutagen.m4a import M4A
import sys
import os
import shutil

def get_trkn(musicfile):
    ''' read track number from music file
    '''
    audio = M4A(musicfile)
    if audio.has_key('trkn'):
        return audio['trkn'][0]
    else:
        return -1
        
def preZero(num, bits):
    ''' prefix a num with zeros, output a string of bits digits
        E.g., preZero(13, 4) --> 0013
    '''
    return str(num).rjust(bits, '0')
    

if __name__ == '__main__':
    cwddir = os.getcwd()
    
    print 'Write the fold path to fold.txt'
    
    srcdir = open('fold.txt').readline()
    
    if os.path.exists(srcdir):
        currsrcdir = srcdir
        
        dirList=os.listdir(currsrcdir)
        for fname in dirList:
            if fname.endswith('.m4a'):
                #print fname
                trkn = get_trkn(os.path.join(currsrcdir, fname))
                pre = preZero(trkn, 2)
                
                newfname = pre + '.' + fname
                shutil.move(os.path.join(currsrcdir, fname), os.path.join(currsrcdir, newfname))
                
                
    else:
        print 'can not open ' + srcdir

'''
读取一个目录下的 mp3 文件的 album,建立album文件夹,把mp3文件放入文件夹。
适合将多个 album 的音乐分开。
'''

from mutagen.apev2 import APEv2 as MUSIC
import sys
import os
import shutil

def get_trkn(musicfile):
    ''' read track number from music file
    '''
    audio = MUSIC(musicfile)
    if audio.has_key('trkn'):
        return audio['trkn'][0]
    else:
        return -1
        
def get_album(musicfile):
    ''' read track number from music file
    '''
    audio = MUSIC(musicfile)
    if audio.has_key('Album'):
        # audio['Album'].__getitem__(0) is unicoded, some of the unicode cannot be encoded in gbk, so use ignore
        return audio['Album'].__getitem__(0).encode('gbk','ignore')
    else:
        return -1
        
def preZero(num, bits):
    ''' prefix a num with zeros, output a string of bits digits
        E.g., preZero(13, 4) --> 0013
    '''
    return str(num).rjust(bits, '0')
    

if __name__ == '__main__':
    cwddir = os.getcwd()
    
    print('Write the fold path to fold.txt')
    
    srcdir = open('fold.txt').readline()
    
    if os.path.exists(srcdir):
        currsrcdir = srcdir
        
        dirList=os.listdir(currsrcdir)
        for fname in dirList:
            if fname.endswith('.mp3'):
                fullname = os.path.join(currsrcdir, fname)
                print fullname
                album = get_album(fullname)
                #print album
                
                albumdir = os.path.join(currsrcdir, album)
                #print albumdir
                if not (os.path.exists(albumdir) and os.path.isdir(albumdir)):
                    os.mkdir(albumdir)
                    
                shutil.move(os.path.join(currsrcdir, fname), albumdir)
    else:
        print('can not open ' + srcdir)
        

0 comments: