Skip to content

Instantly share code, notes, and snippets.

@halloleo
Created August 5, 2014 01:51
Show Gist options
  • Save halloleo/d1b56f6826a8b09b8130 to your computer and use it in GitHub Desktop.
Save halloleo/d1b56f6826a8b09b8130 to your computer and use it in GitHub Desktop.
copying text tags between mp3 files using id3v2 as a back-end.
#!/usr/bin/env python
"""id3copy - copy id3 (text) tags from mp3 file SRC to mp3 file DEST
usage: id3copy [-h] [-v... | -q] SRC DEST
options:
-h, --help show this help message and exit
-v, --verbose verbose output (give it twice for debug output)
-q, --quiet no information output
note 1:
this tool uses the program `id3v2` to read and then write the tags. it got
developed, because the `id3cp` program adds wrong characters into the text
tags.
note 2:
this tool writes only TEXT tags (no images, etc). therefore use `id3cp'
first and then correct the text tags with this tool.
"""
import os
import sys
import docopt
import atexit
import subprocess
def exename():
exepath=sys.argv[0]
pathparts=exepath.split(os.sep)
return pathparts[-1]
args = {}
def get_tagtext(src):
tagtext = subprocess.check_output(['id3v2', '-l', src], universal_newlines=True, stderr=subprocess.STDOUT)
print_verbose("tagtext:\n%s" % tagtext)
return tagtext
# List of allow keys
ALLOWEDKEYS = ['IPLS', 'LINK', 'SYLT', 'TALB', 'TBPM', 'TCOM', 'TCOP', 'TDAT', 'TDLY', 'TENC', 'TEXT', 'TIME', 'TIT2', 'TIT3', 'TKEY', 'TLAN', 'TOAL', 'TOFN', 'TOLY', 'TOPE', 'TORY', 'TOWN', 'TPE1', 'TPE2', 'TPE3', 'TPE4', 'TPUB', 'TRCK', 'TRDA', 'TRSN', 'TRSO', 'TSSE', 'TXXX', 'TYER', 'USER', 'USLT', 'WCOM', 'WCOP', 'WOAF', 'WOAR', 'WOAS', 'WORS', 'WPUB', 'WXXX']
# Seperator of comment from real value
INVALUESEP = ": "
def get_tagdict(tagtext):
tagdict = {}
pre=True
try :
for line in tagtext.splitlines():
if pre:
if line.find("id3v2 tag info for")>=0:
pre=False
else:
(k, v) = line.split(" ", 1)
if k in ALLOWEDKEYS:
i = v.find(INVALUESEP)
if i >= 0:
v = v[i+len(INVALUESEP):]
print_verbose("keep frame '%s' with value '%s'" % (k,v))
tagdict[k]=v
else:
print_verbose("cannot copy frame '%s'" % k)
except ValueError, e:
raise ValueError("cannot read id3 information properly")
if pre==True:
# raise exception if no id3(v2) information found (either no present or fopen error or... )
raise ValueError("no id3 information found")
print_verbose (tagdict)
return tagdict
def apply_tagdict(dest, tagdict):
for k in tagdict:
v = tagdict[k]
print_verbose("write frame '%s' with value '%s'" % (k, v))
tagtext = subprocess.check_call(['id3v2', '--%s' % k, v, dest], stderr=subprocess.STDOUT)
def work():
src = args['SRC']
dest = args['DEST']
tagtext = get_tagtext(src)
tagdict = get_tagdict(tagtext)
apply_tagdict(dest, tagdict)
def print_verbose(msg):
if args['--verbose']:
print("--- %s" % str(msg))
if __name__ == '__main__':
try:
args = docopt.docopt(__doc__, version='0.1.0')
print_verbose("args:\n%s" % str(args))
work()
except docopt.DocoptExit as e:
print ("%s: wrong commandline" % exename())
print (str(e))
print ("try '%s -h' for more information." % exename())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment