处理cue文件并转换出mp3文件

Tue 12 May 2015 | tags:

例如cue和wav文件,用这个解析cue文件转换除独立的mp3文件, 并写上id3 tag。

to mp3:

#!/usr/bin/env python2.7

import subprocess as subp
import sys
import os
from os.path import splitext, basename
import random
import glob

records = []
filename = ""
album=''
alb_artist=''
codec = 'libmp3lame'
ffmpeg_exec = 'ffmpeg'
encodingList = ('utf-8', 'shift-jis', 'cp936')

filecontent = open(sys.argv[1]).read()
for enc in encodingList:
    try:
        lines = filecontent.decode(enc).split('\n')
        encoding = enc
        break
    except UnicodeDecodeError as e:
        if enc == encodingList[-1]:
            raise e
        else:
            pass

for l in lines:
    a = l.split()
    if not a:
        continue
    if a[0] == "FILE":
        filename = ' '.join(a[1:-1]).strip('\'"')
    elif a[0]=='TRACK':
        records.append({})
        records[-1]['index'] = a[1]
    elif a[0]=='TITLE':
        if len(records)>0:
            records[-1]['title'] = ' '.join(a[1:]).strip('\'"')
        else:
            album =  ' '.join(a[1:]).strip('\'"')
    elif a[0]=='INDEX' and a[1]=='01':
        timea = a[2].split(':')
        if len(timea) == 3 and int(timea[0]) >= 60:
            timea.insert(0, str(int(timea[0])/60))
            timea[1] = str(int(timea[1])%60)
        times = '{0}.{1}'.format(':'.join(timea[:-1]), timea[-1])
        records[-1]['start'] = times
    elif a[0]=='PERFORMER':
        if len(records)>1:
            records[-1]['artist'] = ' '.join(a[1:]).strip('\'"')
        else:
            alb_artist = ' '.join(a[1:]).strip('\'"')

for i, j in enumerate(records):
    try:
        j['stop'] = records[i+1]['start']
    except IndexError:
        pass

if not os.path.isfile(filename):
    tmpname = splitext(basename(sys.argv[1]))[0]+splitext(filename)[1]
    if os.path.exists(tmpname):
        filename = tmpname
        del tmpname
    else:
        for ext in ('.ape', '.flac', '.wav', '.mp3'):
            tmpname = splitext(filename)[0] + ext
            if os.path.exists(tmpname):
                filename = tmpname
                break

if not os.path.isfile(filename):
    raise IOError("Can't not find file: {0}".format(filename))

fstat = os.stat(filename)
atime = fstat.st_atime
mtime = fstat.st_mtime

records[-1]['stop'] = '0'
tmpfile = splitext(filename)[0] + str(random.randint(10000,90000)) + '.mp3'

try:
    ret = subp.call([ffmpeg_exec, '-hide_banner', '-y', '-i', filename, 
        '-acodec', codec, '-q:a', '0', '-abr', '0', 
        '-compression_level', '0', tmpfile])

    if ret != 0:
        raise SystemExit('Converting failed.')

    for i in records:
        output = i['index'] +' - '+ i['title']+'.mp3'
        commandline = [ffmpeg_exec, '-hide_banner', 
        '-y', '-i', tmpfile,
        '-c', 'copy', 
        '-ss', i['start'], '-to', i['stop'],
        '-metadata', u'title={0}'.format(i['title']), 
        '-metadata', u'artist={0}'.format(i.get('artist', '')),
        '-metadata', u'performer={0}'.format(i.get('artist', '')),
        '-metadata', u'album={0}'.format(album), 
        '-metadata', 'track={0}/{1}'.format(i['index'], len(records)), 
        '-metadata', u'album_artist={0}'.format(alb_artist), 
        '-metadata', u'composer={0}'.format(alb_artist), 
        '-metadata', 'encoder=Meow', 
        '-id3v2_version', '3', '-write_id3v1', '1', 
        output]
        subp.call(commandline)
        os.utime(output, (atime, mtime))
finally:
    if os.path.isfile(tmpfile):
        os.remove(tmpfile)

to m4a:

#!/usr/bin/env python2.7

import subprocess as subp
import sys
import os
from os.path import splitext
import random
import glob
import mediainfo
import re

remPtn = re.compile(u'^(\ufeff)?REM ')

records = []
filename = ""
album=''
alb_artist=''
genre=''
year=''
codec = 'libfdk_aac'
ffmpeg_exec = 'ffmpeg'
encodingList = ('utf-8','euc-kr', 'shift-jis', 'cp936', 'big5')

filecontent = open(sys.argv[1]).read()
for enc in encodingList:
    try:
        lines = filecontent.decode(enc).split('\n')
        encoding = enc
        break
    except UnicodeDecodeError as e:
        if enc == encodingList[-1]:
            raise e
        else:
            pass

for l in lines:

    if len(records) == 0 and remPtn.match(l):
        l = remPtn.sub('', l)

    a = l.split()

    if not a:
        continue

    if len(records) == 0:

        # if a[0] == "REM" and len(a) > 2:
        #   a.pop(0)

        if a[0] == "FILE":
            filename = ' '.join(a[1:-1]).strip('\'"')
        elif a[0] == 'TITLE':
            album =  ' '.join(a[1:]).strip('\'"')
        elif a[0]=='PERFORMER':
            alb_artist = ' '.join(a[1:]).strip('\'"')
        elif a[0] == 'GENRE':
            genre = ' '.join(a[1:]).strip('\'"')
        elif a[0] == 'DATE':
            year = a[1]
        elif a[0]=='TRACK':
            records.append({})
            records[-1]['index'] = a[1]
    else:
        if a[0]=='TRACK':
            records.append({})
            records[-1]['index'] = a[1]
        elif a[0]=='TITLE':
            records[-1]['title'] = ' '.join(a[1:]).strip('\'"')
        elif a[0]=='INDEX' and a[1]=='01':
            timea = a[2].split(':')
            if len(timea) == 3 and int(timea[0]) >= 60:
                timea.insert(0, str(int(timea[0])/60))
                timea[1] = str(int(timea[1])%60)
            times = '{0}.{1}'.format(':'.join(timea[:-1]), timea[-1])
            records[-1]['start'] = times
        elif a[0]=='PERFORMER':
            records[-1]['artist'] = ' '.join(a[1:]).strip('\'"')

# print genre
# print year
# raise SystemExit

for i, j in enumerate(records):
    try:
        j['stop'] = records[i+1]['start']
    except IndexError:
        pass

if not os.path.isfile(filename):
    for i in glob.glob(splitext(filename)[0] + '.*'):
        if splitext(i)[1] in ('.ape', '.flac', '.wav', '.mp3'):
            filename = i
            break

if not os.path.isfile(filename):
    raise IOError("Can't not find file: {0}".format(filename))

fstat = os.stat(filename)
atime = fstat.st_atime
mtime = fstat.st_mtime

#records[-1]['stop'] = '0'
tmpfile = splitext(filename)[0] + str(random.randint(10000,90000)) + '.m4a'

try:
    ret = subp.call([ffmpeg_exec, '-hide_banner', '-y', '-i', filename, 
        '-acodec', codec, '-b:a', '320k','-profile:a', 'aac_low', 
        '-cutoff', '20000', '-movflags','faststart', 
        '-f','ipod',tmpfile])

    if ret != 0:
        raise SystemExit('Converting failed.')

    tmpinfo = mediainfo.mediainfo(tmpfile)

    records[-1]['stop'] = tmpinfo.get('duration', '0')

    for i in records:
        output = i['index'] +' - '+ i['title']+'.m4a'
        commandline = [ffmpeg_exec, '-hide_banner', 
        '-y', '-i', tmpfile,
        '-c', 'copy', '-movflags','faststart', 
        '-ss', i['start'], '-to', i['stop'],
        '-metadata', u'title={0}'.format(i['title']), 
        '-metadata', u'date={0}'.format(year), 
        '-metadata', u'genre={0}'.format(genre), 
        '-metadata', u'artist={0}'.format(i.get('artist', '')),
        '-metadata', u'album_artist={0}'.format(i.get('artist', '')),
        '-metadata', u'performer={0}'.format(i.get('artist', '')),
        '-metadata', u'album={0}'.format(album), 
        '-metadata', 'track={0}/{1}'.format(i['index'], len(records)), 
        '-metadata', u'album_artist={0}'.format(alb_artist), 
        '-metadata', u'composer={0}'.format(alb_artist), 
        '-metadata', 'encodedby=Meow', 
        '-metadata', 'tool=ffmpeg', 
        '-metadata', 'type=music', 
        '-f', 'ipod', 
        output]
        subp.call(commandline)
        os.utime(output, (atime, mtime))
finally:
    if os.path.isfile(tmpfile):
        os.remove(tmpfile)

to flac

#!/usr/bin/env python2.7

import subprocess as subp
import sys
import os
from os.path import splitext, basename
import random
import glob

records = []
filename = ""
album=''
alb_artist=''
codec = 'flac'
ffmpeg_exec = 'ffmpeg'
encodingList = ('utf-8', 'shift-jis', 'cp936')

filecontent = open(sys.argv[1]).read()
for enc in encodingList:
    try:
        lines = filecontent.decode(enc).split('\n')
        encoding = enc
        break
    except UnicodeDecodeError as e:
        if enc == encodingList[-1]:
            raise e
        else:
            pass

for l in lines:
    a = l.split()
    if not a:
        continue
    if a[0] == "FILE":
        filename = ' '.join(a[1:-1]).strip('\'"')
    elif a[0]=='TRACK':
        records.append({})
        records[-1]['index'] = a[1]
    elif a[0]=='TITLE':
        if len(records)>0:
            records[-1]['title'] = ' '.join(a[1:]).strip('\'"')
        else:
            album =  ' '.join(a[1:]).strip('\'"')
    elif a[0]=='INDEX' and a[1]=='01':
        timea = a[2].split(':')
        if len(timea) == 3 and int(timea[0]) >= 60:
            timea.insert(0, str(int(timea[0])/60))
            timea[1] = str(int(timea[1])%60)
        times = '{0}.{1}'.format(':'.join(timea[:-1]), timea[-1])
        records[-1]['start'] = times
    elif a[0]=='PERFORMER':
        if len(records)>1:
            records[-1]['artist'] = ' '.join(a[1:]).strip('\'"')
        else:
            alb_artist = ' '.join(a[1:]).strip('\'"')

for i, j in enumerate(records):
    try:
        j['stop'] = records[i+1]['start']
    except IndexError:
        pass

if not os.path.isfile(filename):
    tmpname = splitext(basename(sys.argv[1]))[0]+splitext(filename)[1]
    if os.path.exists(tmpname):
        filename = tmpname
        del tmpname
    else:
        for ext in ('.ape', '.flac', '.wav', '.mp3'):
            tmpname = splitext(filename)[0] + ext
            if os.path.exists(tmpname):
                filename = tmpname
                break

if not os.path.isfile(filename):
    raise IOError("Can't not find file: {0}".format(filename))

fstat = os.stat(filename)
atime = fstat.st_atime
mtime = fstat.st_mtime

records[-1]['stop'] = '0'
if filename.lower().endswith('.flac'):
    tmpfile = filename
else:
    tmpfile = splitext(filename)[0] + str(random.randint(10000,90000)) + '.flac'

try:
    if filename != tmpfile:
        ret = subp.call([ffmpeg_exec, '-hide_banner', '-y', '-i', filename, 
            '-acodec', codec,'-compression_level','12','-f','flac',tmpfile])

        if ret != 0:
            raise SystemExit('Converting failed.')

    for i in records:
        output = i['index'] +' - '+ i['title']+'.flac'
        commandline = [ffmpeg_exec, '-hide_banner', 
        '-y', '-i', tmpfile,
        '-c', 'copy', 
        '-ss', i['start'], '-to', i['stop'],
        '-metadata', u'title={0}'.format(i['title']), 
        '-metadata', u'artist={0}'.format(i.get('artist', '')),
        '-metadata', u'performer={0}'.format(i.get('artist', '')),
        '-metadata', u'album={0}'.format(album), 
        '-metadata', 'track={0}/{1}'.format(i['index'], len(records)), 
        '-metadata', u'album_artist={0}'.format(alb_artist), 
        '-metadata', u'composer={0}'.format(alb_artist), 
        '-metadata', 'encoder=Meow', 
        '-write_id3v1', '1', 
        output]
        subp.call(commandline)
        os.utime(output, (atime, mtime))
finally:
    if os.path.isfile(tmpfile):
        os.remove(tmpfile)
        os.exit(1)