예제 #1
0
 def doTranscodeVC1(self, srcfile, outfile, trackinfo):
     id = trackinfo['unique id']
     if self.h264bitrate is None:
         # use source stream bitrate
         # convert bits/sec to Kbits/sec
         bitrate = str(int(trackinfo['bit rate'] / 1000.))
     else:
         bitrate = str(self.h264bitrate)
     
     framerate = trackinfo['frame rate'].split()[0]
     
     encopts = ":".join(
                      ["%s=%s" % tuple(map(str, i))
                       for i in self.x264opts.iteritems()])
     
     # TODO: necessary? (TEST)
     encopts += ":fps=%s" % framerate # really force this
     
     txcode_cmd = ['HandBrakeCLI', 
                   '-i', srcfile,
                   '-o', outfile, 
                     # no audio
                   '-a', 'none',
                   '-e', 'x264',
                   '--width',  str(trackinfo['width']),
                   '--height', str(trackinfo['height']),
                   '-b', bitrate,
                   '-r', framerate,
                   '-x', encopts]
     
     if self.twoPassEncode:
         txcode_cmd += ['--two-pass']
         if self.turboFirstPass:
             txcode_cmd += ['--turbo']
     
     printFriendlyCmd = " ".join(txcode_cmd)
     
     common_util.Msg("Transcoding video track %s to H.264" % id)
     common_util.Babble("Video endoding cmd: %s" % printFriendlyCmd)
     
     mgr = self.getProcessManager()
     retcode, sout, serr = mgr.call(txcode_cmd)
     
     if retcode == 0:
         common_util.Msg("Transcode complete.")
     else:
         raise subp.CalledProcessError(retcode, printFriendlyCmd)
예제 #2
0
 def extractTracks(self, srcfile, trackProcessData):
     procMgr = self.getProcessManager()
     files = []
     for id, t in trackProcessData.iteritems():
         if t.extractTo is not None:
             files.append("%s:%s" % (id, t.extractTo))
     
     if len(files) > 0: 
         common_util.Msg("Extracting tracks from %s" % srcfile)
         cmd = [self.mkvextract, 'tracks', srcfile] + files
         retcode, sout, serr = procMgr.call(cmd)
         
         if retcode != 0:
             common_util.Error("Failure to extract track data from %s" % srcfile)
             common_util.Msg("mkvextract output: %s\n%s" % (sout, serr))
             return False
     
     for dat in trackProcessData.itervalues():
         if hasattr(dat.doOnExtracted, '__call__'):
             if not dat.doOnExtracted(dat):
                 # error condition
                 # autoripd will clean up the working dir
                 return False
     return True
예제 #3
0
 def processRip(self, mediaFilePath,
                      mediaMetadata,
                      programSettings,
                      workingDir,
                      previousPluginData):
     """Remux a rip into an .m2ts file."""
     
     self.assignSettings(programSettings)
     self.origFile = mediaFilePath
     
     # should we perform the mux?
     media_base = os.path.basename(mediaFilePath)
     fname, ext = os.path.splitext(media_base)
     if mediaMetadata['format'] != 'Matroska':
         return {}
     
     # find a name/place for the new file
     outdir = self.m2tsDir
     if outdir is None:
         # ship .m2ts files to the same place as the other rips
         outdir = self.autoripd_settings.destDir
     if not os.path.exists(outdir):
         os.makedirs(outdir)
     outname = fname + ".m2ts"
     outfile = common_util.uniquePath(os.path.join(outdir, outname))
     
     # perform the mux
     newfile = self.remux(mediaFilePath, outfile, mediaMetadata, workingDir)
     
     # backup and/or delete the original source
     if newfile is not None:
         bkupdir = self.srcBackupDir
         if bkupdir is not None and \
               self.preserveSrc and \
               not os.path.samefile(bkupdir, os.path.dirname(mediaFilePath)):
             
             if not os.path.isdir(bkupdir):
                 os.path.makedirs(bkupdir)
             dstpath = common_util.uniquePath(os.path.join(bkupdir, media_base))
             os.rename(mediaFilePath, dstpath)
         elif not self.preserveSrc:
             os.unlink(mediaFilePath)
             common_util.Msg("Removed %s" % mediaFilePath) 
     else:
         raise Exception("remuxer encountered a problem; aborted")
     
     return {'mux_new_m2tsfile' : newfile}
예제 #4
0
 def doTranscodeDTS(self, tkinfo):
     pman     = self.getProcessManager()
     metadata = tkinfo.metadata
     dtsfile  = tkinfo.extractTo
     ac3file  = tkinfo.ac3file
     
     common_util.Msg("Encoding DTS track %s to AC3" % metadata['unique id'])
     
     try:
         devnull = open(os.devnull, 'w')
         dcadec_cmd = [self.dcadec, '-o', 'wavall', dtsfile]
         
         # we directly pipe the decoded stream to aften for encoding to avoid
         # writing an enormous 2-hour 6-channel WAV file to disk
         with pman.Popen(dcadec_cmd, 
                         stdout=subp.PIPE,
                         # really important; dcadec spews 'skip' x 1 billion
                         stderr=devnull) as decodp:
             
             aften_cmd = [self.aften, '-b', str(self.dtsBitrate),
                          '-w', str(self.dtsBandwidth),
                          '-v', '0',
                          '-', ac3file]
             
             with pman.Popen(aften_cmd,
                             stderr=subp.PIPE,
                             stdout=subp.PIPE,
                             stdin=decodp.stdout) as encodp:
                 decodp.stdout.close() # release our handle on this pipe
                 e_sout, e_serr = encodp.communicate()
                 d_ret = decodp.wait()
                 e_ret = encodp.returncode
         devnull.close()
     except OSError, err:
         if err.errno == errno.ENOENT:
             Error("Trouble launching program while transcoding DTS. "
                   "Are dcadec and aften installed?")
         try:
             devnull.close()
         except:
             pass
         raise
예제 #5
0
 def remux(self, infile, outfile, info, workingdir):
     """Remux <infile> into an .m2ts at <outfile>, returning the complete 
     path of <outfile> upon success, or None upon failure."""
     
     fpath    = os.path.abspath(infile)
     outfpath = os.path.abspath(common_util.uniquePath(outfile))
     if not os.path.isfile(fpath):
         common_util.Error('File %s could not be found for remuxing' % fpath)
         return None
     titlename = os.path.splitext(info['file name'])[0]
     
     tkProcessData = {}
     
     # generate the .meta file
     # per spec at http://forum.doom9.org/archive/index.php/t-142559.html
     meta = "MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr --vbv-len=500\n"
     for track in info['tracks']:
         if 'unique id' not in track or 'codec id' not in track:
             # not a mux-able track; i.e. a menu track
             continue
             
         id = track['unique id']
         
         result = self.processTrack(titlename, fpath, track, workingdir)
         if result is None:
             continue
         else:
             meta += result.metaline
             tkProcessData[id] = result
     
     # do the remux
     with tempfile.NamedTemporaryFile(mode='w', 
                                      suffix='.meta', 
                                      dir=workingdir) as tmpf:
         # write metafile
         metaname = os.path.abspath(tmpf.name)
         tmpf.write(meta)
         tmpf.flush()
         
         # extract/process streams
         ok = self.extractTracks(fpath, tkProcessData)
         if not ok:
             return None
         
         common_util.Msg("Remuxing %s to %s" % (fpath, outfpath))
         common_util.Babble("Metafile:\n%s\n" % meta)
         
         # do remux
         mgr = self.getProcessManager()
         retcode, sout, serr = mgr.call([self.tsMuxeR, metaname, outfpath])
         if retcode != 0:
             common_util.Error('Failure to remux %s to %s' % 
                              (infile, outfpath))
             common_util.Msg('tsMuxeR output: %s\n%s' % (sout,serr))
             return None
         
         # clean up extracted tracks / extra files:
         for trackdat in tkProcessData.itervalues():
             if trackdat.extractTo and os.path.exists(trackdat.extractTo):
                   os.unlink(trackdat.extractTo)
             for extraf in trackdat.cleanupFiles:
                 if os.path.exists(extraf):
                     os.unlink(extraf)
         
         # .meta tmpfile is deleted automatically
     
     common_util.Msg("%s remuxed successfully" % outfpath)
     
     return outfpath