コード例 #1
0
ファイル: ripdisc.py プロジェクト: trbabb/autoripd
def ripDVD(device, 
           destDir, 
           tmpDir, 
           extraOptions=[], 
           ejectDisk=True, 
           procMgr=DFT_MGR):
    Msg("Reading metadata from %s" % device)
    dvd_data = dvdDiscProperties(device, procMgr)
    
    if dvd_data is None:
        return False
    
    name1 = dvd_data['dvd_title']
    name2 = dvd_data['dvd_alt_title']
    
    # find main_feature title
    main_title = 'unknown'
    for title, props in dvd_data['titles'].iteritems():
        if 'main_feature' in props and props['main_feature']:
            main_title = title
    
    if len(name1) > 0:
        name = name1
    elif len(name2) > 0:
        name = name2
    else:
        name = "Unknown DVD" 
    
    tmpfile = uniquePath(os.path.join(tmpDir,"%s.mp4" % name)) 
    
    Msg("Ripping title %s of %s to %s" % (main_title, name, tmpDir))
    
    retcode, sout, serr = procMgr.call(
                               ['HandBrakeCLI',
                                '-i', device,
                                '-o', tmpfile] + extraOptions)
    
    if retcode != 0:
        Error("HandBrake failed to rip title '%s' of disc '%s'" %
               (main_title, name))
        Error("HandBrake output:\n %s" % serr)
        
        # autoripd will clear up the temp directory
        return None
    else:
        # move movie back to destination
        final_file = uniquePath(os.path.join(destDir, "%s.mp4" % name))
        os.rename(tmpfile, final_file)
        if ejectDisk:
            # not process logged, but probably safe.
            subp.call(['eject', device])
        return os.path.abspath(final_file)
コード例 #2
0
def ripDVD(device,
           destDir,
           tmpDir,
           extraOptions=[],
           ejectDisk=True,
           procMgr=DFT_MGR):
    Msg("Reading metadata from %s" % device)
    dvd_data = dvdDiscProperties(device, procMgr)

    if dvd_data is None:
        return False

    name1 = dvd_data['dvd_title']
    name2 = dvd_data['dvd_alt_title']

    # find main_feature title
    main_title = 'unknown'
    for title, props in dvd_data['titles'].iteritems():
        if 'main_feature' in props and props['main_feature']:
            main_title = title

    if len(name1) > 0:
        name = name1
    elif len(name2) > 0:
        name = name2
    else:
        name = "Unknown DVD"

    tmpfile = uniquePath(os.path.join(tmpDir, "%s.mp4" % name))

    Msg("Ripping title %s of %s to %s" % (main_title, name, tmpDir))

    retcode, sout, serr = procMgr.call(
        ['HandBrakeCLI', '-i', device, '-o', tmpfile] + extraOptions)

    if retcode != 0:
        Error("HandBrake failed to rip title '%s' of disc '%s'" %
              (main_title, name))
        Error("HandBrake output:\n %s" % serr)

        # autoripd will clear up the temp directory
        return None
    else:
        # move movie back to destination
        final_file = uniquePath(os.path.join(destDir, "%s.mp4" % name))
        os.rename(tmpfile, final_file)
        if ejectDisk:
            # not process logged, but probably safe.
            subp.call(['eject', device])
        return os.path.abspath(final_file)
コード例 #3
0
ファイル: remuxer.py プロジェクト: lukeandrew/autoripd
 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
ファイル: ripdisc.py プロジェクト: trbabb/autoripd
def ripBluRay(device, 
              destDir, 
              workingDir, 
              ejectDisc=True,
              procManager=DFT_MGR):
    """Use makemkvcon to rip a blu-ray movie from the given device. 
    <destDir> is the path of the folder into which finished ripped movies 
    will be moved. <tmpDir> is the path of a folder where unfinished rips 
    will reside until they are complete.
    
    Returns path of the ripped media file, or None."""
    
    properties = bluRayDiscProperties(device, procManager)
    if properties is None:
        # failure. brdProperties() will have reported the error.
        return None
    
    disc, titles = properties
    feature_title_id = detectBluRayMainFeature(titles)
    name = disc['name'] if 'name' in disc else 'Unknown Blu-Ray' 
    
    Msg("Ripping title %s of %s to %s" % (feature_title_id, name, tmpdest))
    
    retcode, sout, serr = procManager.call([
                             "makemkvcon",
                             "mkv", 
                             "dev:%s" % device, 
                             str(feature_title_id),
                             workingDir])
    
    if retcode != 0:
        Error("Failed to rip from '%s' %s" % (disc['title'], device))
        Error("makemkvcon output:\n%s" % serr)
        # unfinished mkv laying around for debugging. autoripd will delete the
        # working directory if the user has chosen so with a config setting
        return None
    else: 
        # move tmp mkv to final location
        f_output = titles[feature_title_id]['outputFileName']
        f_output = os.path.join(workingDir, f_output)
        final_filename = "%s.mkv" % name
        final_path = uniquePath(os.path.join(destDir, final_filename))
        os.rename(f_output, final_path)
        
        if ejectDisc:
            # not process logged, but probably safe.
            subp.call(['eject', device])
        
        Msg("Ripped %s successfully" % name)
        return os.path.abspath(final_path)
コード例 #5
0
def ripBluRay(device,
              destDir,
              workingDir,
              ejectDisc=True,
              procManager=DFT_MGR):
    """Use makemkvcon to rip a blu-ray movie from the given device. 
    <destDir> is the path of the folder into which finished ripped movies 
    will be moved. <tmpDir> is the path of a folder where unfinished rips 
    will reside until they are complete.
    
    Returns path of the ripped media file, or None."""

    properties = bluRayDiscProperties(device, procManager)
    if properties is None:
        # failure. brdProperties() will have reported the error.
        return None

    disc, titles = properties
    feature_title_id = detectBluRayMainFeature(titles)
    name = disc['name'] if 'name' in disc else 'Unknown Blu-Ray'

    Msg("Ripping title %s of %s to %s" % (feature_title_id, name, tmpdest))

    retcode, sout, serr = procManager.call([
        "makemkvcon", "mkv",
        "dev:%s" % device,
        str(feature_title_id), workingDir
    ])

    if retcode != 0:
        Error("Failed to rip from '%s' %s" % (disc['title'], device))
        Error("makemkvcon output:\n%s" % serr)
        # unfinished mkv laying around for debugging. autoripd will delete the
        # working directory if the user has chosen so with a config setting
        return None
    else:
        # move tmp mkv to final location
        f_output = titles[feature_title_id]['outputFileName']
        f_output = os.path.join(workingDir, f_output)
        final_filename = "%s.mkv" % name
        final_path = uniquePath(os.path.join(destDir, final_filename))
        os.rename(f_output, final_path)

        if ejectDisc:
            # not process logged, but probably safe.
            subp.call(['eject', device])

        Msg("Ripped %s successfully" % name)
        return os.path.abspath(final_path)
コード例 #6
0
ファイル: remuxer.py プロジェクト: lukeandrew/autoripd
 def processTrack(self, titlename, srcfile, track, workingdir):
     """Return the .meta file line associated with this track, an optional 
     filename to extract the track to, and a function (or None) representing 
     an action to perform on the extracted track. Return None if this track 
     should be skipped.
     
     Track extraction should not be performed here; we extract tracks all
     at once when track analysis is complete (it's faster this way)-- then 
     describe any processing on the extracted tracks with a callback."""
     
     # we'll return this object:
     tkinfo = struct()
     tkinfo.metaline      = ""    # this track's data for the .meta file
     tkinfo.extractTo     = None  # to what file shall this track be extracted?
     tkinfo.doOnExtracted = None  # fn to call when extraction complete
                                  # (will be passed the tkinfo object)
                                  # (shall return false on error, true otherwise)
     tkinfo.cleanupFiles  = set() # extra files to delete after mux completed
     tkinfo.metadata = track
     
     codec = track['codec id']
     id    = track['unique id'] 
     
     if codec not in self.allowedCodecs:
         common_util.Warn("Not muxing track %s; codec '%s' not recognized" %\
                          (id, codec))
         return None
     
     if track['type'] == 'video': 
         tracksrc = srcfile
         trackid  = track['unique id']
         
         # differences in naming convention
         if codec == 'V_MPEG2':
             codec = 'V_MPEG-2'
         elif codec == 'WVC1' or codec == 'V_MS/VFW/WVC1':
             if self.transcodeVC1:
                 h264name = "%s.%s.x264.mkv" % (titlename, id)
                 h264dest = common_util.uniquePath(
                               os.path.join(workingdir, h264name)) 
                 tracksrc = h264dest
                 trackid  = 1
                 codec    = 'V_MPEG4/ISO/AVC'
                 
                 self.doTranscodeVC1(srcfile, h264dest, track)
                 
                 tkinfo.cleanupFiles.add(h264dest)
             else:
                 codec = 'V_MS/VFW/WVC1'
         
         # extra flags for H.264
         if codec == 'V_MPEG4/ISO/AVC':
             extra = ', insertSEI, contSPS'
         else:
             extra = ''
         
         framerate = track['frame rate'].rsplit('fps', 1)[0].strip()
         
         template = '%s, "%s", fps=%s, track=%s, lang=%s%s\n'
         tkinfo.metaline = template % (codec, 
                                       tracksrc, 
                                       framerate,
                                       trackid, 
                                       track['language'], 
                                       extra)
     elif track['type'] in ('audio','text'):
         if self.subtitleLangs is not None and \
                 track['type'] == 'text' and \
                 track['language'] not in self.subtitleLangs:
             # skip this language
             return None
         elif self.audioLanguages is not None and \
                 track['type'] == 'audio' and \
                 track['language'] not in self.audioLanguages:
             # skip this language
             return None
         
         if codec == 'S_HDMV/PGS' and self.subtitleWorkaround:
             # invent a .sup file name
             # save it for when we perform extraction
             # (we will extract them all at once)
             pgsname  = "%s.%s.%s.pgs" % (titlename, track['language'], id)
             tracksrc = common_util.uniquePath(
                           os.path.join(workingdir, pgsname))
             tkinfo.extractTo = tracksrc
             tracktag = '' # not needed; src file only has one track
         elif codec == 'A_DTS' and self.transcodeDTS:
             # we extract to one file (.dts), and mux from another (the 
             # eventual converted .ac3). the meta file must reflect this
             dtsname  = "%s.%s.%s.dts" % (titlename, track['language'], id)
             ac3name  = "%s.%s.%s.ac3" % (titlename, track['language'], id)
             tracksrc = common_util.uniquePath(
                           os.path.join(workingdir, ac3name))
             tkinfo.extractTo = common_util.uniquePath(
                           os.path.join(workingdir, dtsname))
             tkinfo.ac3file = tracksrc # extra info for the callback
             tkinfo.doOnExtracted =  self.doTranscodeDTS
             codec = 'A_AC3'
             tracktag = ''
         else:
             tracksrc = srcfile
             tracktag = ', track=%s' % id
         
         lang = (', lang=%s' % track['language']) if 'language' in track else ''
         tkinfo.metaline = '%s, "%s"%s%s\n' % (codec, tracksrc, tracktag, lang)
     
     return tkinfo
コード例 #7
0
ファイル: remuxer.py プロジェクト: lukeandrew/autoripd
 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