#!/usr/bin/env python ################### # tscut.py # file cutter for MythTV # cuts transport streams at GOP and reindexes # database cutlist to match updated frame counts ################### from MythTV import Job, Recorded, MythLog, MythError, findfile, MythDB from subprocess import Popen from optparse import OptionParser import sys import os.path LOG = MythLog('tscut.py') DB = MythDB() def itercopy(input, output, size): # copy data in 32KB chunks, or however much is left # which ever is smaller print 'writing %s bytes' % size buff = 2**15 if size > 2**15 else size while buff: output.write(input.read(buff)) size -= buff buff = 2**15 if size > 2**15 else size def cut_video(rec): seekdata = iter(rec.seek) newcutlist = [] newcutpoint = [] for left, right in rec.markup.getuncutlist() if left == 0: seek = 0 leftbyte = 0 else: while True: # search out the closest keyframe inside the cut seek = seekdata.next() if seek.mark >= left: left = seek.mark leftbyte = seek.offset break if right == 9999999: rightbyte = rec.filesize else: while True: lastseek = seek seek = seekdata.next() if seek.mark == right: right = seek.mark rightbyte = seek.offset break elif seek.mark > right: right = lastseek.mark rightbyte = lastseek.offset break newcutlist.append((left,right)) newcutpoint.append((leftbyte,rightbyte)) group = findfile(rec.basename, rec.storagegroup, db=rec._db) if group is None: raise MythError('Could not find recording') recfile = os.path.join(group.dirname, rec.basename) tmpfile = os.path.join(group.dirname, 'temp.m2v') finfile = recfile.rsplit('.') finfile.insert(1,'new') finfile = '.'.join(finfile) fi = open(recfile) proc = Popen(['/usr/local/bin/mythffmpeg', '-i', '-', '-vcodec', 'copy', tmpfile], stdin=-1)#, stdout=null, stderr=null) for left,right in newcutpoint: cur = fi.tell() if left > cur: itercopy(fi, proc.stdin, left-cur) fi.seek(right) proc.stdin.write(fi.read()) fi.close() proc.stdin.close() proc.wait() """ null = open('/dev/null','w') proc = Popen(['/usr/local/bin/mythffmpeg', '-i', '-', '-target', 'ntsc-dvd', '-vcodec', 'copy', '-acodec', 'copy', tmpfile], stdin=-1)#, stdout=null, stderr=null) for left,right in newcutpoint: cur = fi.tell() if left > cur: itercopy(fi, proc.stdin, left-cur) fi.seek(right) proc.stdin.write(fi.read()) fi.close() proc.stdin.close() proc.wait() """ def main(): parser = OptionParser(usage="usage: %prog [options] [jobid]") parser.add_option("--chanid", action="store", type="int", dest="chanid", help="Use chanid for manual operation") parser.add_option("--starttime", action="store", type="int", dest="starttime", help="Use starttime for manual operation") parser.add_option('-o', '--overwrite', action='store_true', dest='overwrite', help="Overwrite the old recording in the database, and update seek and cut tables.") parser.add_option('-v', '--verbose', action='store', type='string', dest='verbose', help='Verbosity level') opts, args = parser.parse_args() if opts.verbose: if opts.verbose == 'help': print MythLog.helptext sys.exit(0) MythLog._setlevel(opts.verbose) if opts.chanid and opts.starttime: rec = Recorded((opts.chanid, opts.starttime), db=DB) elif len(args) == 1: job = Job(args[0], db=DB) rec = Recorded((job.chanid, job.starttime), db=DB) else: parser.print_help() sys.exit(2) cut_video(rec) if opts.overwrite: print 'not yet supported' if __name__ == "__main__": main()