Skip to content

Instantly share code, notes, and snippets.

Last active Dec 17, 2015
What would you like to do?
Split MP4 on chapters (by using mp4box)
mp4box = 'C:\Programs\GPAC\MP4Box.exe'
def tosec(s):
# convert time signature to seconds as float
from datetime import datetime
dt = datetime.strptime(s, '%H:%M:%S.%f')
return dt.hour * 3600 + dt.minute * 60 + dt.second + dt.microsecond * 10e-7
def main(arg):
import re, os, time, ctypes
from subprocess import check_call, check_output
fn = arg[0]
if os.path.isfile(fn):
folder = os.path.dirname(fn)
info = check_output([mp4box, "-info", fn])
# extract all chapter time signatures
time_fmt = '\d{2}:\d{2}:\d{2}.\d{3}'
m = re.findall('Chapter #\d+ - (%s)' % time_fmt, info)
if len(m) > 1:
m.append('Duration (%s)' % time_fmt, info).group(1))
# find chapter titles
chapters = re.findall('Chapter #\d+ - %s - "(.*?)"' % time_fmt, info)
# add default values to chapthers w/o title
chapters = ['Chapter %02d' % (x+1) if y == "" else y for (x, y) in enumerate(chapters)]
# make convenient filename for each chapter
chapters = ['%02d - %s.m4a' % (x+1, ''.join(z for z in y if (z.isalnum() or z in ' _'))) for x, y in enumerate(chapters)]
# iterate over each chapter range
for z, (x, y) in enumerate(zip(m[0::1], m[1::1])):
if len(arg) == 1 or int(arg[1]) == z+1:
check_call([mp4box, '-splitx', '%s:%s' % (tosec(x), tosec(y)),
fn, '-out', os.path.join(folder, chapters[z])])
check_call([mp4box, '-add', '%s#1' % os.path.join(folder, chapters[z]),
'-new', os.path.join(folder, chapters[z])])
# make playlist
if len(arg) == 1:
with open(fn.replace(os.path.splitext(fn)[1], '.m3u'), 'w') as pls:
os.startfile(fn.replace(os.path.splitext(fn)[1], '.m3u'), 'open')
msg = 'File "%s" doesn\'t contain chapters' % fn
except Exception as e:
msg = str(e)
msg = 'File "%s" doesn\'t exist' % fn
if 'msg' in vars():
ctypes.windll.user32.MessageBoxA(0, msg, 'MP4Box split', 0)
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
print('Usage: python.exe input.m4a [chapter_number]')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment