Skip to content

Instantly share code, notes, and snippets.

Created February 9, 2019 06:30
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save miyagawa/14b75c66f1f7d79f9f751b1b9cc7e550 to your computer and use it in GitHub Desktop.
mp3chapter adding tool, originally written by rui314
#!/usr/bin/env python3
import re
import string
import sys
import yaml
from mutagen import id3
from os import path, environ
from collections import namedtuple
Chapter = namedtuple('Chapter', ['title', 'start', 'end'])
def parse_time(s):
m = re.match('(\d+):(\d+):(\d+)', s)
if m is not None:
return (int( * 3600 + int( * 60 + int( * 1000
m = re.match('(\d+):(\d+)', s)
if m is not None:
return (int( * 60 + int( * 1000
print("bad timestamp:", s)
def get_chapters(ep, end):
ret = []
for chapter in reversed(ep['chapters']):
m = re.match('([\d:]+)\s+(.+)$', chapter)
if m is None:
start = parse_time(
ret.append(Chapter(, start, end))
end = start
return list(reversed(ret))
mp3file = sys.argv[1]
datafile = sys.argv[2]
ep = yaml.load(open(datafile))
# Add metadata
tag = id3.ID3(mp3file)
# Add chapters
chapters = get_chapters(ep, int(str(tag['TLEN'])))
if len(chapters) > 0:
tag.add(id3.CTOC(element_id=u"toc", flags=id3.CTOCFlags.TOP_LEVEL | id3.CTOCFlags.ORDERED,
child_element_ids=['chp{:02d}'.format(i) for i in range(len(chapters))],
sub_frames=[id3.TIT2(encoding=id3.Encoding.UTF8, text=[u"Table of Contents"])]))
for i, c in enumerate(chapters):
tag.add(id3.CHAP(element_id=u'chp{:02d}'.format(i), start_time=c.start, end_time=c.end,
sub_frames=[id3.TIT2(encoding=id3.Encoding.UTF8, text=[c.title])]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment