#!/usr/local/bin/python -u
|
import argparse
|
import os
|
import glob
|
import subprocess
|
import shlex
|
import json
|
import requests
|
import unicodedata
|
from querysubsonic import findalbumbyname
|
from time import sleep
|
|
|
# arguments
|
# activation_key, file name, codec(default to mp3)
|
|
parser = argparse.ArgumentParser()
|
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.single:
|
mode = 'single'
|
else:
|
mode = 'chapter'
|
|
if args.verbose:
|
stats = "-stats"
|
else:
|
stats = "-nostats"
|
|
|
def getmetadata(aaxfile):
|
ret = subprocess.check_output(["ffprobe", "-v", "info", "-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 getmetacopyright():
|
copyright = unicodedata.normalize('NFKD', metadata['format']['tags']['copyright']).encode('ascii','ignore')
|
return copyright
|
|
|
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'),
|
getmetacopyright(),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
|
|
def filechecksum(aaxfile):
|
#The the hex checksum from the file
|
ret = subprocess.Popen(["ffprobe", "-v", "info", "-hide_banner", os.path.abspath(aaxfile)], stderr=subprocess.PIPE)
|
grep = subprocess.Popen(["grep", "checksum"], stdin=ret.stderr, stdout=subprocess.PIPE)
|
awk = subprocess.Popen(["awk", " { print $8 } "], stdin=grep.stdout, stdout=subprocess.PIPE)
|
hashsum,out = awk.communicate()
|
hashsum = str(hashsum).strip('\n')
|
return hashsum
|
|
def getcorrectkey(aaxfile):
|
#request the key for the checksum
|
hex = filechecksum(aaxfile)
|
payload = hex
|
recovery = 3
|
while recovery != 0:
|
r = requests.post('http://prod-faas-gw.darkurthe.net:8080/function/checkkey', payload, verify=False, timeout=None)
|
if r.status_code == 200:
|
key = r.text
|
recovery = 0
|
return key
|
else:
|
print('Checkkey function is down please wait')
|
recovery = recovery - 1
|
sleep(15)
|
|
for rfile in glob.glob(args.filename):
|
if rfile.find("aax") != -1 and os.path.isfile(rfile):
|
metadata = getmetadata(rfile)
|
album = getmetadatatags('album')
|
#See if we got it already
|
if (findalbumbyname(album) == False):
|
artist = getmetadatatags('artist')
|
title = getmetadatatags('title')
|
act_byte = getcorrectkey(rfile)
|
ddir = "%s/%s/%s" % (path, artist, title)
|
single_file_path = "/processing/%s.mp3" % (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)
|
else:
|
print('We have that book already')
|
|