Chris Pomeroy
2017-08-11 ee622a7476eefbc90136b86ea0bf60d6e27c5936
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/python
import argparse
import os
import glob
import subprocess
import shlex
import json
 
# arguments
# activation_key, file name, codec(default to mp3)
parser = argparse.ArgumentParser()
parser.add_argument("--code", help="Activation Code from audible to decrypt files")
parser.add_argument("-s","--single", help="Use this option to create a single file. This is false by default", action="store_true")
parser.add_argument("-d","--dpath", help="Use this to set the destination path. Otherwise I will use the current directory")
parser.add_argument("-v", "--verbose", help="Send output to stdout", action="store_true")
parser.add_argument("filename", help="Filename to convert, or directory to look in")
 
args = parser.parse_args()
 
act_byte = ""
metadata = ""
mode = ""
stats = ""
 
if args.dpath:
    path = args.dpath
else:
    path = os.getcwd()
 
if args.code:
    act_byte = args.code
elif os.path.isfile('./.authcode'):
    act_byte = open('./.authcode').readline()
 
if act_byte == "":
    print "Please provide an activation code from audible. Either at the command line or the .authcode file"
 
if args.single:
    mode = 'single'
else:
    mode = 'chapter'
 
if args.verbose:
    stats = "-stats"
else:
    stats = "-nostats"
 
 
def getmetadata(aaxfile):
    ret = subprocess.check_output(["ffprobe", "-v", "quiet", "-hide_banner", "-show_format", "-show_chapters", "-print_format", "json", os.path.abspath(aaxfile)])
    mdata = json.loads(ret)
    return mdata
 
 
def getmetabitrate():
    bit_rate = metadata['format']['bit_rate']
    return bit_rate[:2]
 
 
def getmetadatatags(key):
    # get specific data
    tag = metadata['format']['tags'][key]
    return tag
 
 
def reencode(aaxfile, outpath):
    # decrypt and reencode to mp3
    command = ("ffmpeg -loglevel error {} -activation_bytes {} -i {} -vn -codec:a libmp3lame -ab {}k -map_metadata -1 "
               "-metadata \"title={}\" -metadata 'artist={}' -metadata 'album_artist={}' -metadata \"album={}\" -metadata 'date={}' "
               "-metadata track=1/1 -metadata 'genre={}' -metadata 'copyright={}' \"{}\" " ).format(stats, act_byte,aaxfile,getmetabitrate(),
                                                                                           getmetadatatags('title'), getmetadatatags('artist'),
                                                                                           getmetadatatags('album_artist'), getmetadatatags('album'),
                                                                                           getmetadatatags('date'), getmetadatatags('genre'),
                                                                                           getmetadatatags('copyright'),outpath)
    if args.verbose:
        print command
        process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if output:
                print output.strip()
        rc = process.poll()
        return rc
    else:
        process = subprocess.call(shlex.split(command))
    return 
 
 
def getchaptercount():
    # Get the number of chapters
    ccount = metadata['chapters']
    return len(ccount)
 
 
def getchaptermetadata(cid, key):
    # get the Chapter metadata
    for i in metadata['chapters']:
        if i['id'] == cid:
            return i[key]
 
def movetochapters(path, outpath, chapter, title, start,end):
    # Creating individual chapters
 
    outfile = "{}/Ch - {} {}.mp3".format(outpath, chapter, title)
    command = "ffmpeg -loglevel error {} -i \"{}\" -ss {} -to {} -codec:a copy -metadata 'track={}' \"{}\"".format(stats, path,
                                                                                                               start, end,
                                                                                                               chapter, outfile)
    if args.verbose:
        print command
        process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if output:
                print output.strip()
        rc = process.poll()
        return rc
    else:
        process = subprocess.call(shlex.split(command))
    return
 
 
def getcoverart(path,outpath):
    # Pull the coverart from the file
    command = "ffmpeg -loglevel error -activation_bytes {} -i \"{}\" -an -codec:v copy \"{}/cover.jpg\"".format(act_byte,
                                                                                                               path, outpath)
    if args.verbose:
        print command
    process = subprocess.call(shlex.split(command))
    return
 
for rfile in glob.glob(args.filename):
    if rfile.find("aax") != -1 and os.path.isfile(rfile):
        metadata = getmetadata(rfile)
        album = getmetadatatags('album')
        artist = getmetadatatags('artist')
        title = getmetadatatags('title')
        ddir = "%s/%s/%s" % (path, artist, title)
        single_file_path = "%s/%s.mp3" % (ddir, title)
        if not os.path.exists(ddir):
            os.makedirs(ddir)
        print ddir
        reencode(rfile, single_file_path)
        if mode == 'chapter':
            chapter = 0
            numchapters = getchaptercount()
            while (numchapters > 0 ):
                cstart = getchaptermetadata(chapter, 'start_time')
                cend = getchaptermetadata(chapter, 'end_time')
                chapter += 1
                numchapters -= 1
                schap = str(chapter).zfill(2)
                movetochapters(single_file_path, ddir, schap, title, cstart,cend)
            os.remove(single_file_path)
        getcoverart(rfile, ddir)