Skip to content

Instantly share code, notes, and snippets.

@kkew3
Last active January 22, 2021 08:08
Show Gist options
  • Save kkew3/e7051f473eb30ecb2cc8d4eb3f026ee0 to your computer and use it in GitHub Desktop.
Save kkew3/e7051f473eb30ecb2cc8d4eb3f026ee0 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import os
import sys
import argparse
import subprocess
import ast
HOMEDIR = os.path.normpath(os.environ['HOME'])
MUSICDIR = os.path.join(HOMEDIR, 'Music')
COVERARTDIR = os.path.join(MUSICDIR, '.cover-arts')
OK = 0
ERRNO_MID3V2_NOT_FOUND = 1
ERRNO_MID3V2_TIMEOUT = 2
ERRNO_MID3V2_FAILED = 4
ERRNO_TAGINFO_NO_MIME = 8
ERRNO_TAGINFO_NO_DATA = 16
ERRNO_TAGINFO_NO_APIC = 32
def make_parser():
parser = argparse.ArgumentParser(
description=('Extract cover art, if any, from FILEs under '
'~/Music/ and save them to ~/Music/.cover-arts/.'))
parser.add_argument('filenames', metavar='FILE', nargs='*')
return parser
def extract_apic_info(filename):
command_s = 'mid3v2 --list-raw "{}"'.format(filename)
try:
output = subprocess.check_output(['mid3v2', '--list-raw', filename],
stderr=subprocess.STDOUT,
timeout=5,
cwd=MUSICDIR)
except FileNotFoundError:
print('`mid3v2\' is required to run this script!', file=sys.stderr)
return ERRNO_MID3V2_NOT_FOUND
except subprocess.TimeoutExpired:
print('`{}\' timeout!'.format(command_s), file=sys.stderr)
return ERRNO_MID3V2_TIMEOUT
except subprocess.CalledProcessError as err:
print(
'`{}\' failed with error code {}'.format(command_s,
err.returncode),
file=sys.stderr)
return ERRNO_MID3V2_FAILED
for line in output.decode('utf-8').split('\n'):
if line.startswith('APIC('):
try:
mime_start_pos = line.index("mime='")
except ValueError:
print(
'failed to find MIME type in `{}\'s output'.format(
command_s),
file=sys.stderr)
return ERRNO_TAGINFO_NO_MIME
mime_end_pos = line.index("',", mime_start_pos)
mime = line[mime_start_pos + len("mime='"):mime_end_pos]
_literal_image, ext = mime.split('/', maxsplit=1)
assert _literal_image == 'image', \
'unrecognized MIME {}'.format(mime)
try:
data_start_pos = line.index('data=', mime_end_pos)
except ValueError:
print(
'failed to find image data in `{}\'s output'.format(
command_s),
file=sys.stderr)
return ERRNO_TAGINFO_NO_DATA
data = line[data_start_pos + len('data='):-1]
buffer = ast.literal_eval(data)
fname = os.path.splitext(os.path.basename(filename))[0]
tofile = os.path.join(COVERARTDIR, '.'.join([fname, ext]))
with open(tofile, 'wb') as outfile:
outfile.write(buffer)
return OK
print('{}: no cover art found'.format(filename), file=sys.stderr)
return ERRNO_TAGINFO_NO_APIC
def main():
args = make_parser().parse_args()
for filename in args.filenames:
returncode = extract_apic_info(filename)
if returncode not in [OK, ERRNO_TAGINFO_NO_APIC]:
sys.exit(returncode)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment