Esempio n. 1
0
def main(args):
    from optparse import OptionParser
    p = OptionParser(description='Grabs avisynth trims and outputs chapter '
                     'file, qpfile and/or cuts audio (works with cfr and '
                     'vfr input)',
                     version='VFR Chapter Creator 0.10.0',
                     usage='%prog [options] infile.avs [outfile.avs]')
    p.add_option('--label', '-l', action="store", dest="label",
                 help="Look for a trim() statement or succeeding comment only "
                 "on lines matching LABEL. Default: case insensitive trim")
    p.add_option('--clip', action="store", dest="clip",
                 help="Look for trims() using specific clip, like"
                 "Trim(ClipX,0,100). Default: any trim")
    p.add_option('--line', '-g', action="store", type="int", dest="line",
                 help="Specify directly the line used")
    p.add_option('--input', '-i', action="store", help='Audio file to be cut',
                 dest="input")
    p.add_option('--output', '-o', action="store",
                 help='Cut audio from MKVMerge', dest="output")
    p.add_option('--fps', '-f', action="store",
                 help='Frames per second or Timecodes file', dest="fps")
    p.add_option('--ofps', action="store", help='Output frames per second',
                 dest="ofps")
    p.add_option('--timecodes', action="store", help='Output v2 timecodes',
                 dest="otc")
    p.add_option('--chapters', '-c', action="store",
                 help='Chapters file [.{0}/.txt]'.format("/.".join(
                 exts.keys())), dest="chapters")
    p.add_option('--chnames', '-n', action="store",
                 help='Path to template file for chapter names (utf8 w/o bom)',
                 dest="chnames")
    p.add_option('--template', '-t', action="store",
                 help="Template file for chapters", dest="template")
    p.add_option('--uid', action="store",
                 help="Base UID for --template or --chnames", dest="uid")
    p.add_option('--qpfile', '-q', action="store", help='QPFile for x264',
                 dest="qpfile")
    p.add_option('--verbose', '-v', action="store_true", help='Verbose',
                 dest="verbose")
    p.add_option('--merge', '-m', action="store_true", help='Merge cut files',
                 dest="merge")
    p.add_option('--remove', '-r', action="store_true",
                 help='Remove cut files', dest="remove")
    p.add_option('--delay', '-d', action="store",
                 help="Set delay of audio (can be negative)", dest="delay")
    p.add_option('--reverse', '-b', action="store_true",
                 help="Reverse parsing of .avs", dest="reverse")
    p.add_option('--test', action="store_true",
                 help="Test mode (do not create new files)", dest="test")
    p.add_option('--IDR', '--idr', action="store_true",
                 help="Set this to make qpfile with IDR frames instead of K frames",
                 dest="IDR")
    p.add_option('--sbr', action="store_true",
                 help="Set this if inputting an .aac and it's SBR/HE-AAC",
                 dest="sbr")
    (o, a) = p.parse_args(args)

    if len(a) < 1:
        p.error("No avisynth script specified.")
    if not o.fps:
        o.fps = default_fps
        ifps = False
    else:
        ifps = True

    #Determine chapter type
    if o.chapters:
        chre = compile("\.({0})$(?i)".format("|".join(exts.keys())))
        ret = chre.search(o.chapters)
        chapter_type = exts[ret.group(1).lower()] if ret else "OGM"
    else:
        chapter_type = ''

    if o.template and o.chnames:
        p.error("Choose either --chnames or --template, not both.")
    elif o.template and chapter_type != 'MKV':
        p.error("--template needs to output to .xml.")

    if not o.output and o.input:
        ret = splitext(o.input)
        o.output = '{0}.cut.mka'.format(ret[0])

    if o.verbose:
        status = "Avisynth file: \t{0}\n".format(a[0])
        status += "Label: \t\t{0}\n".format(o.label) if o.label else ""
        status += "Clip name: \t{0}\n".format(o.clip) if o.clip else ""
        status += ("Parsing order: \t{0}\n".format("Bottom to top" if
                    o.reverse else "Top to bottom"))
        status += "Line: \t\t{0}\n".format(o.line) if o.line else ""
        status += ("Audio file: \t{0}{1}\n".format(o.input, "(SBR)" if o.sbr
                    else "") if o.input else "")
        status += "Cut Audio file: {0}\n".format(o.output) if o.output else ""
        status += "Timecodes/FPS: \t{0}{1}\n".format(o.fps, " to " + o.ofps if
                    o.ofps else "") if o.ofps != o.fps else ""
        status += "Output v2 Tc: \t{0}\n".format(o.otc) if o.otc else ""
        status += ("Chapters file: \t{0}{1}\n".format(o.chapters,
                    " ({0})".format(chapter_type) if chapter_type else "") if
                    o.chapters else "")
        status += ("Chapter Names: \t{0}\n".format(o.chnames) if o.chnames
                    else "")
        status += ("Template file: \t{0}\n".format(o.template) if o.template
                    else "")
        status += "QP file: \t{0} ({1} frames)\n".format(o.qpfile, 'I' if
                    o.IDR else 'K') if o.qpfile else ""
        status += "\n"
        status += ("Merge/Rem files:{0}/{1}\n".format(o.merge, o.remove) if
                    o.merge or o.remove else "")
        status += ("Verbose: \t{0}\n".format(o.verbose) if o.verbose
                    else "")
        status += "Test Mode: \t{0}\n".format(o.test) if o.test else ""

        print(status)

    # Get frame numbers and corresponding timecodes from avs
    Trims, Trimsts, Trims2, Trims2ts, audio = parse_trims(a[0], o.fps, o.ofps,
                                           o.otc if not o.test else '', o.input,
                                           o.label, o.reverse, o.line, o.clip,
                                           o.merge)

    nt2 = len(Trims2ts)
    if o.verbose:
        print('In trims: {0}\n'.format(', '.join(['({0},{1})'.format(i[0],
                i[1]) for i in Trims])))
        print('In timecodes: {0}\n'.format(', '.join(['({0},{1})'.format(i[0],
                i[1]) for i in Trimsts])))
        print('Out trims: {0}\n'.format(', '.join(['({0},{1})'.format(i[0],
                i[1]) for i in Trims2])))
        print('Out timecodes: {0}\n'.format(', '.join(['({0},{1})'.format(
                fmt_time(i[0]), fmt_time(i[1])) for i in Trims2ts])))

    # make qpfile
    if o.qpfile and not o.template:
        if not o.test:
            write_qpfile(o.qpfile, Trims2, o.IDR)
        if o.verbose:
            print('Writing keyframes to {0}\n'.format(o.qpfile))

    # make audio cuts
    if o.input:
        split_audio(audio, o.input, o.output, o.delay, o.sbr, o.merge, o.remove,
                    o.verbose, o.test)

    # make offseted avs
    if len(a) > 1:
        try:
            from chapparse import writeAvisynth
            fNum = [i[0] for i in Trims2]
            set = {'avs': '"' + a[1] + '"', 'input': '', 'resize': ''}
            writeAvisynth(set, fNum)
        except ImportError:
            print('Script chapparse.py needed for avisynth output to work.')

    # write chapters
    if chapter_type:

        if chapter_type == 'MKV':
            Trims2ts = [(fmt_time(i[0]), fmt_time(i[1]) if i[1] != 0 else None)
                        for i in Trims2ts]

        if o.template:
            from templates import AutoMKVChapters as amkvc
            output = o.chapters[:-4] if not o.test else None
            chaps = amkvc(o.template, output=output, avs=a[0], trims=Trims2ts,
                            kframes=Trims2, uid=o.uid, label=o.label,
                            ifps=ifps, clip=o.clip, idr=o.IDR)

        else:
            # Assign names to each chapter if --chnames
            chapter_names = []

            if o.chnames:
                with open(o.chnames, encoding='utf-8') as f:
                    [chapter_names.append(line.strip()) for line in
                    f.readlines()]

            if not o.chnames or len(chapter_names) < len(Trims2ts):
                # The if statement is for clarity; it doesn't actually do
                # anything useful
                for i in range(len(chapter_names), len(Trims2ts)):
                    chapter_names.append("Chapter {:02d}".format(i + 1))

            if chapter_type == 'MKV':
                from templates import AutoMKVChapters as amkvc
                tmp = amkvc.Template()
                tmp.trims = Trims2ts
                tmp.kframes = Trims2
                if o.qpfile:
                    tmp.qpf = o.qpfile
                    tmp.idr = o.IDR
                ed = tmp.Edition()
                ed.default = 1
                ed.num_chapters = len(chapter_names)
                ed.uid = int(o.uid) * 100 if o.uid else tmp.uid * 100
                cuid = ed.uid
                ed.chapters = []
                for i in range(len(chapter_names)):
                    ch = tmp.Chapter()
                    cuid += 1
                    ch.uid = cuid
                    ch.name = [chapter_names[i]]
                    ch.start, ch.end = (Trims2ts[i][0], Trims2ts[i][1])
                    ed.chapters.append(ch)
                tmp.editions = [ed]
                chaps = tmp

            if not o.test:
                if chapter_type == 'MKV':
                    chaps.toxml(o.chapters[:-4])
                else:
                    with open(o.chapters, "w", encoding='utf-8') as output:
                        if chapter_type == 'OGM':
                            chap = ('CHAPTER{1:02d}={0}\nCHAPTER{1:02d}'
                                    'NAME={2}\n')
                        elif chapter_type == 'X264':
                            chap = '{0} {2}\n'
                        Trims2ts = [fmt_time(i[0], 1) for i in Trims2ts]
                        [output.write(chap.format(Trims2ts[i], i + 1,
                        chapter_names[i])) for i in range(len(Trims2ts))]
        if o.verbose:
            print("Writing {} Chapters to {}". format(chapter_type,
                    o.chapters))
Esempio n. 2
0
def main(args):
    from optparse import OptionParser
    p = OptionParser(description='Grabs avisynth trims and outputs chapter '
                     'file, qpfile and/or cuts audio (works with cfr and '
                     'vfr input)',
                     version='VFR Chapter Creator 0.10.0',
                     usage='%prog [options] infile.avs [outfile.avs]')
    p.add_option('--label', '-l', action="store", dest="label",
                 help="Look for a trim() statement or succeeding comment only "
                 "on lines matching LABEL. Default: case insensitive trim")
    p.add_option('--clip', action="store", dest="clip",
                 help="Look for trims() using specific clip, like"
                 "Trim(ClipX,0,100). Default: any trim")
    p.add_option('--line', '-g', action="store", type="int", dest="line",
                 help="Specify directly the line used")
    p.add_option('--input', '-i', action="store", help='Audio file to be cut',
                 dest="input")
    p.add_option('--output', '-o', action="store",
                 help='Cut audio from MKVMerge', dest="output")
    p.add_option('--fps', '-f', action="store",
                 help='Frames per second or Timecodes file', dest="fps")
    p.add_option('--ofps', action="store", help='Output frames per second',
                 dest="ofps")
    p.add_option('--timecodes', action="store", help='Output v2 timecodes',
                 dest="otc")
    p.add_option('--chapters', '-c', action="store",
                 help='Chapters file [.{0}/.txt]'.format("/.".join(
                 exts.keys())), dest="chapters")
    p.add_option('--chnames', '-n', action="store",
                 help='Path to template file for chapter names (utf8 w/o bom)',
                 dest="chnames")
    p.add_option('--template', '-t', action="store",
                 help="Template file for chapters", dest="template")
    p.add_option('--uid', action="store",
                 help="Base UID for --template or --chnames", dest="uid")
    p.add_option('--qpfile', '-q', action="store", help='QPFile for x264',
                 dest="qpfile")
    p.add_option('--verbose', '-v', action="store_true", help='Verbose',
                 dest="verbose")
    p.add_option('--merge', '-m', action="store_true", help='Merge cut files',
                 dest="merge")
    p.add_option('--remove', '-r', action="store_true",
                 help='Remove cut files', dest="remove")
    p.add_option('--delay', '-d', action="store",
                 help="Set delay of audio (can be negative)", dest="delay")
    p.add_option('--reverse', '-b', action="store_true",
                 help="Reverse parsing of .avs", dest="reverse")
    p.add_option('--test', action="store_true",
                 help="Test mode (do not create new files)", dest="test")
    p.add_option('--IDR', '--idr', action="store_true",
                 help="Set this to make qpfile with IDR frames instead of K frames",
                 dest="IDR")
    p.add_option('--sbr', action="store_true",
                 help="Set this if inputting an .aac and it's SBR/HE-AAC",
                 dest="sbr")
    (o, a) = p.parse_args(args)

    if len(a) < 1:
        p.error("No avisynth script specified.")
    if not o.fps:
        o.fps = default_fps
        ifps = False
    else:
        ifps = True

    #Determine chapter type
    if o.chapters:
        chre = compile("\.({0})$(?i)".format("|".join(exts.keys())))
        ret = chre.search(o.chapters)
        chapter_type = exts[ret.group(1).lower()] if ret else "OGM"
    else:
        chapter_type = ''

    if o.template and o.chnames:
        p.error("Choose either --chnames or --template, not both.")
    elif o.template and chapter_type != 'MKV':
        p.error("--template needs to output to .xml.")

    if not o.output and o.input:
        ret = splitext(o.input)
        o.output = '{0}.cut.mka'.format(ret[0])

    if o.verbose:
        status = "Avisynth file: \t{0}\n".format(a[0])
        status += "Label: \t\t{0}\n".format(o.label) if o.label else ""
        status += "Clip name: \t{0}\n".format(o.clip) if o.clip else ""
        status += ("Parsing order: \t{0}\n".format("Bottom to top" if
                    o.reverse else "Top to bottom"))
        status += "Line: \t\t{0}\n".format(o.line) if o.line else ""
        status += ("Audio file: \t{0}{1}\n".format(o.input, "(SBR)" if o.sbr
                    else "") if o.input else "")
        status += "Cut Audio file: {0}\n".format(o.output) if o.output else ""
        status += "Timecodes/FPS: \t{0}{1}\n".format(o.fps, " to " + o.ofps if
                    o.ofps else "") if o.ofps != o.fps else ""
        status += "Output v2 Tc: \t{0}\n".format(o.otc) if o.otc else ""
        status += ("Chapters file: \t{0}{1}\n".format(o.chapters,
                    " ({0})".format(chapter_type) if chapter_type else "") if
                    o.chapters else "")
        status += ("Chapter Names: \t{0}\n".format(o.chnames) if o.chnames
                    else "")
        status += ("Template file: \t{0}\n".format(o.template) if o.template
                    else "")
        status += "QP file: \t{0} ({1} frames)\n".format(o.qpfile, 'I' if o.IDR else 'K') if o.qpfile else ""
        status += "\n"
        status += ("Merge/Rem files:{0}/{1}\n".format(o.merge, o.remove) if
                    o.merge or o.remove else "")
        status += ("Verbose: \t{0}\n".format(o.verbose) if o.verbose
                    else "")
        status += "Test Mode: \t{0}\n".format(o.test) if o.test else ""

        print(status)

    # Get frame numbers and corresponding timecodes from avs
    Trims, Trimsts, Trims2, Trims2ts, audio = parse_trims(a[0], o.fps, o.ofps,
                                           o.otc if not o.test else '', o.input,
                                           o.label, o.reverse, o.line, o.clip)

    nt2 = len(Trims2ts)
    if o.verbose:
        print('In trims: {0}\n'.format(', '.join(['({0},{1})'.format(i[0],
                i[1]) for i in Trims])))
        print('In timecodes: {0}\n'.format(', '.join(['({0},{1})'.format(i[0],
                i[1]) for i in Trimsts])))
        print('Out trims: {0}\n'.format(', '.join(['({0},{1})'.format(i[0],
                i[1]) for i in Trims2])))
        print('Out timecodes: {0}\n'.format(', '.join(['({0},{1})'.format(
                fmt_time(i[0]), fmt_time(i[1])) for i in Trims2ts])))

    # make qpfile
    if o.qpfile and not o.template:
        if not o.test:
            write_qpfile(o.qpfile, Trims2, o.IDR)
        if o.verbose:
            print('Writing keyframes to {0}\n'.format(o.qpfile))

    # make audio cuts
    if o.input:
        from subprocess import call, check_output
        from sys import getfilesystemencoding

        if Trims[0][0] == '0':
            includefirst = True
            audio = audio[1:]
        else:
            includefirst = False
            cuttimes = []

        # get mkvmerge version
        get_mkvmerge_version = check_output([mkvmerge, "--version"]).decode()
        ver = [int(n) for n in get_mkvmerge_version.split()[1][1:].split('.')]
        parts_able = ver >= [5,6,0] # first version with --split parts

        if parts_able:
            if includefirst:
                cuttimes = ['-{}'.format(audio.pop(0))]
            if not includefirst and len(audio) == 1:
                cuttimes = '{}-'.format(audio[0])
            else:
                cuttimes = ',+'.join(cuttimes + ['{}-{}'.format(audio[i],
                           audio[i + 1]) for i in range(0,len(audio),2)])
        else:
            cuttimes = ','.join(audio)
        max_audio = len(audio) + 2

        # get info from mkvmerge
        ident = check_output([mkvmerge, "--identify-for-mmg", o.input])
        identre = compile("Track ID (\d+): audio( \(AAC\) "
                    "\[aac_is_sbr:true\])?")
        ret = (identre.search(ident.decode(getfilesystemencoding())) if ident
                else None)

        tid = ret.group(1) if ret else '0'
        sbr = ("0:1" if o.sbr or ret.group(2) else "0:0"
                if o.input.endswith("aac") else "")

        # determine delay
        delre = compile('DELAY ([-]?\d+)')
        ret = delre.search(o.input)
        delay = ('{0}:{1}'.format(tid, o.delay if o.delay else ret.group(1))
                if o.delay or ret else None)

        cutCmd = [mkvmerge, '-o', o.output]
        if not parts_able:
            cutCmd[-1] += '.split.mka'
        if delay:
            cutCmd.extend(['--sync', delay])
        if sbr:
            cutCmd.extend(['--aac-is-sbr', sbr])
        cutCmd.extend([o.input, '--split'])

        if parts_able:
            cutCmd.extend(['parts:' + cuttimes])
        else:
            cutCmd.extend(['timecodes:' + cuttimes])

        if o.verbose:
            print('Cutting: {0}\n'.format(
                        ' '.join(['"{0}"'.format(i) for i in cutCmd])))
        else:
            cutCmd.append('-q')

        if not o.test:
            cutExec = call(cutCmd)
            if cutExec == 1:
                print("Mkvmerge exited with warnings: {0:d}".format(cutExec))
            elif cutExec == 2:
                exit("Failed to execute mkvmerge: {0:d}".format(cutExec))
        if o.merge and not parts_able:
            merge = []
            for i in range(1, max_audio):
                if ((includefirst == True and i % 2 != 0) or
                (includefirst == False and i % 2 == 0)):
                    merge.append('{0}{1}.split-{2:03d}.mka'.format('+' if
                                    len(merge) > 0 else '', o.output, i))
            mergeCmd = [mkvmerge, '-o', o.output]
            mergeCmd.extend(merge)
            if o.verbose:
                print('\nMerging: {0}\n'.format(' '.join(['"{0}"'.format(i) for
                        i in mergeCmd])))
            else:
                mergeCmd.append('-q')

            if not o.test:
                mergeExec = call(mergeCmd)
                if mergeExec == 1:
                    print("Mkvmerge exited with warnings: {0:d}".format(
                            mergeExec))
                elif mergeExec == 2:
                    exit("Failed to execute mkvmerge: {0:d}".format(mergeExec))

        if o.remove and not parts_able:
            remove = ['{0}.split-{1:03d}.mka'.format(o.output, i) for
                        i in range(1, max_audio)]
            if o.verbose:
                print('\nDeleting: {0}\n'.format(', '.join(remove)))
            if not o.test:
                from os import unlink
                [unlink(i) if isfile(i) else True for i in remove]

    # make offseted avs
    if len(a) > 1:
        try:
            from chapparse import writeAvisynth
            fNum = [i[0] for i in Trims2]
            set = {'avs': '"' + a[1] + '"', 'input': '', 'resize': ''}
            writeAvisynth(set, fNum)
        except ImportError:
            print('Script chapparse.py needed for avisynth output to work.')

    # write chapters
    if chapter_type:

        if chapter_type == 'MKV':
            Trims2ts = [(fmt_time(i[0]), fmt_time(i[1]) if i[1] != 0 else None)
                        for i in Trims2ts]

        if o.template:
            from templates import AutoMKVChapters as amkvc
            output = o.chapters[:-4] if not o.test else None
            chaps = amkvc(o.template, output=output, avs=a[0], trims=Trims2ts,
                            kframes=Trims2, uid=o.uid, label=o.label,
                            ifps=ifps, clip=o.clip, idr=o.IDR)

        else:
            # Assign names to each chapter if --chnames
            chapter_names = []

            if o.chnames:
                with open(o.chnames, encoding='utf-8') as f:
                    [chapter_names.append(line.strip()) for line in
                    f.readlines()]

            if not o.chnames or len(chapter_names) < len(Trims2ts):
                # The if statement is for clarity; it doesn't actually do
                # anything useful
                for i in range(len(chapter_names), len(Trims2ts)):
                    chapter_names.append("Chapter {:02d}".format(i + 1))

            if chapter_type == 'MKV':
                from templates import AutoMKVChapters as amkvc
                tmp = amkvc.Template()
                tmp.trims = Trims2ts
                tmp.kframes = Trims2
                if o.qpfile:
                    tmp.qpf = o.qpfile
                    tmp.idr = o.IDR
                ed = tmp.Edition()
                ed.default = 1
                ed.num_chapters = len(chapter_names)
                ed.uid = int(o.uid) * 100 if o.uid else tmp.uid * 100
                cuid = ed.uid
                ed.chapters = []
                for i in range(len(chapter_names)):
                    ch = tmp.Chapter()
                    cuid += 1
                    ch.uid = cuid
                    ch.name = [chapter_names[i]]
                    ch.start, ch.end = (Trims2ts[i][0], Trims2ts[i][1])
                    ed.chapters.append(ch)
                tmp.editions = [ed]
                chaps = tmp

            if not o.test:
                if chapter_type == 'MKV':
                    chaps.toxml(o.chapters[:-4])
                else:
                    with open(o.chapters, "w", encoding='utf-8') as output:
                        if chapter_type == 'OGM':
                            chap = ('CHAPTER{1:02d}={0}\nCHAPTER{1:02d}'
                                    'NAME={2}\n')
                        elif chapter_type == 'X264':
                            chap = '{0} {2}\n'
                        Trims2ts = [fmt_time(i[0], 1) for i in Trims2ts]
                        [output.write(chap.format(Trims2ts[i], i + 1,
                        chapter_names[i])) for i in range(len(Trims2ts))]
        if o.verbose:
            print("Writing {} Chapters to {}". format(chapter_type,
                    o.chapters))
Esempio n. 3
0
File: vfr.py Progetto: breakertt/vfr
def main(args):
    from optparse import OptionParser
    p = OptionParser(description='Grabs avisynth trims and outputs chapter '
                     'file, qpfile and/or cuts audio (works with cfr and '
                     'vfr input)',
                     version='VFR Chapter Creator 0.10.0',
                     usage='%prog [options] infile.avs [outfile.avs]')
    p.add_option('--label',
                 '-l',
                 action="store",
                 dest="label",
                 help="Look for a trim() statement or succeeding comment only "
                 "on lines matching LABEL. Default: case insensitive trim")
    p.add_option('--clip',
                 action="store",
                 dest="clip",
                 help="Look for trims() using specific clip, like"
                 "Trim(ClipX,0,100). Default: any trim")
    p.add_option('--line',
                 '-g',
                 action="store",
                 type="int",
                 dest="line",
                 help="Specify directly the line used")
    p.add_option('--input',
                 '-i',
                 action="store",
                 help='Audio file to be cut',
                 dest="input")
    p.add_option('--output',
                 '-o',
                 action="store",
                 help='Cut audio from MKVMerge',
                 dest="output")
    p.add_option('--fps',
                 '-f',
                 action="store",
                 help='Frames per second or Timecodes file',
                 dest="fps")
    p.add_option('--ofps',
                 action="store",
                 help='Output frames per second',
                 dest="ofps")
    p.add_option('--timecodes',
                 action="store",
                 help='Output v2 timecodes',
                 dest="otc")
    p.add_option('--chapters',
                 '-c',
                 action="store",
                 help='Chapters file [.{0}/.txt]'.format("/.".join(
                     exts.keys())),
                 dest="chapters")
    p.add_option('--chnames',
                 '-n',
                 action="store",
                 help='Path to template file for chapter names (utf8 w/o bom)',
                 dest="chnames")
    p.add_option('--template',
                 '-t',
                 action="store",
                 help="Template file for chapters",
                 dest="template")
    p.add_option('--uid',
                 action="store",
                 help="Base UID for --template or --chnames",
                 dest="uid")
    p.add_option('--qpfile',
                 '-q',
                 action="store",
                 help='QPFile for x264',
                 dest="qpfile")
    p.add_option('--verbose',
                 '-v',
                 action="store_true",
                 help='Verbose',
                 dest="verbose")
    p.add_option('--merge',
                 '-m',
                 action="store_true",
                 help='Merge cut files',
                 dest="merge")
    p.add_option('--remove',
                 '-r',
                 action="store_true",
                 help='Remove cut files',
                 dest="remove")
    p.add_option('--delay',
                 '-d',
                 action="store",
                 help="Set delay of audio (can be negative)",
                 dest="delay")
    p.add_option('--reverse',
                 '-b',
                 action="store_true",
                 help="Reverse parsing of .avs",
                 dest="reverse")
    p.add_option('--test',
                 action="store_true",
                 help="Test mode (do not create new files)",
                 dest="test")
    p.add_option(
        '--IDR',
        '--idr',
        action="store_true",
        help="Set this to make qpfile with IDR frames instead of K frames",
        dest="IDR")
    p.add_option('--sbr',
                 action="store_true",
                 help="Set this if inputting an .aac and it's SBR/HE-AAC",
                 dest="sbr")
    (o, a) = p.parse_args(args)

    if len(a) < 1:
        p.error("No avisynth script specified.")
    if not o.fps:
        o.fps = default_fps
        ifps = False
    else:
        ifps = True

    #Determine chapter type
    if o.chapters:
        chre = compile("\.({0})$(?i)".format("|".join(exts.keys())))
        ret = chre.search(o.chapters)
        chapter_type = exts[ret.group(1).lower()] if ret else "OGM"
    else:
        chapter_type = ''

    if o.template and o.chnames:
        p.error("Choose either --chnames or --template, not both.")
    elif o.template and chapter_type != 'MKV':
        p.error("--template needs to output to .xml.")

    if not o.output and o.input:
        ret = splitext(o.input)
        o.output = '{0}.cut.mka'.format(ret[0])

    if o.verbose:
        status = "Avisynth file: \t{0}\n".format(a[0])
        status += "Label: \t\t{0}\n".format(o.label) if o.label else ""
        status += "Clip name: \t{0}\n".format(o.clip) if o.clip else ""
        status += ("Parsing order: \t{0}\n".format(
            "Bottom to top" if o.reverse else "Top to bottom"))
        status += "Line: \t\t{0}\n".format(o.line) if o.line else ""
        status += ("Audio file: \t{0}{1}\n".format(
            o.input, "(SBR)" if o.sbr else "") if o.input else "")
        status += "Cut Audio file: {0}\n".format(o.output) if o.output else ""
        status += "Timecodes/FPS: \t{0}{1}\n".format(
            o.fps, " to " +
            o.ofps if o.ofps else "") if o.ofps != o.fps else ""
        status += "Output v2 Tc: \t{0}\n".format(o.otc) if o.otc else ""
        status += ("Chapters file: \t{0}{1}\n".format(
            o.chapters, " ({0})".format(chapter_type) if chapter_type else "")
                   if o.chapters else "")
        status += ("Chapter Names: \t{0}\n".format(o.chnames)
                   if o.chnames else "")
        status += ("Template file: \t{0}\n".format(o.template)
                   if o.template else "")
        status += "QP file: \t{0} ({1} frames)\n".format(
            o.qpfile, 'I' if o.IDR else 'K') if o.qpfile else ""
        status += "\n"
        status += ("Merge/Rem files:{0}/{1}\n".format(o.merge, o.remove)
                   if o.merge or o.remove else "")
        status += ("Verbose: \t{0}\n".format(o.verbose) if o.verbose else "")
        status += "Test Mode: \t{0}\n".format(o.test) if o.test else ""

        print(status)

    # Get frame numbers and corresponding timecodes from avs
    Trims, Trimsts, Trims2, Trims2ts, audio = parse_trims(
        a[0], o.fps, o.ofps, o.otc if not o.test else '', o.input, o.label,
        o.reverse, o.line, o.clip, o.merge)

    nt2 = len(Trims2ts)
    if o.verbose:
        print('In trims: {0}\n'.format(', '.join(
            ['({0},{1})'.format(i[0], i[1]) for i in Trims])))
        print('In timecodes: {0}\n'.format(', '.join(
            ['({0},{1})'.format(i[0], i[1]) for i in Trimsts])))
        print('Out trims: {0}\n'.format(', '.join(
            ['({0},{1})'.format(i[0], i[1]) for i in Trims2])))
        print('Out timecodes: {0}\n'.format(', '.join([
            '({0},{1})'.format(fmt_time(i[0]), fmt_time(i[1]))
            for i in Trims2ts
        ])))

    # make qpfile
    if o.qpfile and not o.template:
        if not o.test:
            write_qpfile(o.qpfile, Trims2, o.IDR)
        if o.verbose:
            print('Writing keyframes to {0}\n'.format(o.qpfile))

    # make audio cuts
    if o.input:
        split_audio(audio, o.input, o.output, o.delay, o.sbr, o.merge,
                    o.remove, o.verbose, o.test)

    # make offseted avs
    if len(a) > 1:
        try:
            from chapparse import writeAvisynth
            fNum = [i[0] for i in Trims2]
            set = {'avs': '"' + a[1] + '"', 'input': '', 'resize': ''}
            writeAvisynth(set, fNum)
        except ImportError:
            print('Script chapparse.py needed for avisynth output to work.')

    # write chapters
    if chapter_type:

        if chapter_type == 'MKV':
            Trims2ts = [(fmt_time(i[0]), fmt_time(i[1]) if i[1] != 0 else None)
                        for i in Trims2ts]

        if o.template:
            from templates import AutoMKVChapters as amkvc
            output = o.chapters[:-4] if not o.test else None
            chaps = amkvc(o.template,
                          output=output,
                          avs=a[0],
                          trims=Trims2ts,
                          kframes=Trims2,
                          uid=o.uid,
                          label=o.label,
                          ifps=ifps,
                          clip=o.clip,
                          idr=o.IDR)

        else:
            # Assign names to each chapter if --chnames
            chapter_names = []

            if o.chnames:
                with open(o.chnames, encoding='utf-8') as f:
                    [
                        chapter_names.append(line.strip())
                        for line in f.readlines()
                    ]

            if not o.chnames or len(chapter_names) < len(Trims2ts):
                # The if statement is for clarity; it doesn't actually do
                # anything useful
                for i in range(len(chapter_names), len(Trims2ts)):
                    chapter_names.append("Chapter {:02d}".format(i + 1))

            if chapter_type == 'MKV':
                from templates import AutoMKVChapters as amkvc
                tmp = amkvc.Template()
                tmp.trims = Trims2ts
                tmp.kframes = Trims2
                if o.qpfile:
                    tmp.qpf = o.qpfile
                    tmp.idr = o.IDR
                ed = tmp.Edition()
                ed.default = 1
                ed.num_chapters = len(chapter_names)
                ed.uid = int(o.uid) * 100 if o.uid else tmp.uid * 100
                cuid = ed.uid
                ed.chapters = []
                for i in range(len(chapter_names)):
                    ch = tmp.Chapter()
                    cuid += 1
                    ch.uid = cuid
                    ch.name = [chapter_names[i]]
                    ch.start, ch.end = (Trims2ts[i][0], Trims2ts[i][1])
                    ed.chapters.append(ch)
                tmp.editions = [ed]
                chaps = tmp

            if not o.test:
                if chapter_type == 'MKV':
                    chaps.toxml(o.chapters[:-4])
                else:
                    with open(o.chapters, "w", encoding='utf-8') as output:
                        if chapter_type == 'OGM':
                            chap = ('CHAPTER{1:02d}={0}\nCHAPTER{1:02d}'
                                    'NAME={2}\n')
                        elif chapter_type == 'X264':
                            chap = '{0} {2}\n'
                        Trims2ts = [fmt_time(i[0], 1) for i in Trims2ts]
                        [
                            output.write(
                                chap.format(Trims2ts[i], i + 1,
                                            chapter_names[i]))
                            for i in range(len(Trims2ts))
                        ]
        if o.verbose:
            print("Writing {} Chapters to {}".format(chapter_type, o.chapters))