[PP-Script] mkvdts2ac3 - how to make this nzbget script?

Share your scripts or request scripts with specific features.
Forum rules
Please keep the forum clean - one topic per script. Questions not related to a specific script should be posted in Support forum.
jackiass2
Posts: 42
Joined: 19 Nov 2013, 12:07

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by jackiass2 » 04 Dec 2013, 13:13

Yes, I have it up and running using this command:

Code: Select all

/mnt/disk1/share/nzbget/ppscripts/mkvdts2ac3/mkvdts2ac3.py -n --stereo -w /mnt/disk1/share/test/ -vvv /mnt/disk1/share/_Complete/Video/VIDEONAME/VIDEONAME.mkv
It runs without errors and does what it is supposed to.
This is also why I find it odd that it is now saying stuff like it's not able to find the argparse module.

hugbug
Developer & Admin
Posts: 7645
Joined: 09 Sep 2008, 11:58
Location: Germany

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by hugbug » 04 Dec 2013, 13:25

It may have something to do with environment settings of the account under which nzbget runs.
From the same terminal window where the original script works (please test again that it works - it's not necessary to wait until it remuxes till the end but just check that it starts properly) - start nzbget in console server mode (nzbget -s). This ensures the nzbget pp-script will run under the same user account with the same environment settings. If it still raises an error - there is a problem in the script. If it works - the problem is in user account or environment settings when starting NZBGet in daemon mode.

jackiass2
Posts: 42
Joined: 19 Nov 2013, 12:07

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by jackiass2 » 04 Dec 2013, 13:40

It seems you are on the right track here. It now gives a different error:

Code: Select all

INFO    Executing post-process-script mkvdts2ac3/mkvdts2ac3.py for dts sample                                                                              
INFO    mkvdts2ac3: Traceback (most recent call last):                                                                                                     
INFO    mkvdts2ac3:   File "/mnt/disk1/share/nzbget/ppscripts/mkvdts2ac3/mkvdts2ac3.py", line 223, in <module>                                             
INFO    mkvdts2ac3:     if ppstatus.isdigit():                                                                                                             
INFO    mkvdts2ac3: AttributeError: 'int' object has no attribute 'isdigit'                                                                                
ERROR   Post-process-script mkvdts2ac3/mkvdts2ac3.py for dts sample failed (terminated with unknown status)

hugbug
Developer & Admin
Posts: 7645
Joined: 09 Sep 2008, 11:58
Location: Germany

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by hugbug » 04 Dec 2013, 14:02

The check "if ppstatus.isdigit():" is not necessary and should be removed.
Try replacing (near line 223)

Code: Select all

        if ppstatus.isdigit():
            if int(ppstatus) >= 0 and int(ppstatus) <= 3:
                sab = True
with

Code: Select all

        if ppstatus >= 0 and ppstatus <= 3:
            sab = True

jackiass2
Posts: 42
Joined: 19 Nov 2013, 12:07

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by jackiass2 » 04 Dec 2013, 16:00

Thanks again! That did something. I now get this instead:

Code: Select all

INFO    Executing post-process-script mkvdts2ac3/mkvdts2ac3.py for dts sample                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /opt                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /home                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /tmp                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /usr                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /initrd                                                                                                                                     
INFO    mkvdts2ac3:     Processing dir:  /mnt                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /tmp2                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /sys                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /lib                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /.gphoto                                                                                                                                    
INFO    mkvdts2ac3:     Processing dir:  /lost+found                                                                                                                                 
INFO    mkvdts2ac3:     Processing dir:  /var                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /proc                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /etc                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /www                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /bin                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /boot                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /root                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /dev                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /sbin                                                                                                                                       
INFO    mkvdts2ac3: mkv dts -> ac3 conversion: 0 minutes 0 seconds                                                                                                                   
ERROR   Post-process-script mkvdts2ac3/mkvdts2ac3.py for dts sample failed (terminated with unknown status)  
It looked like it was trying to process all the directories in my root, so I then went into the settings and set the nzbgetdestdir to /mnt/disk1/share/_Complete/ which gives this result instead:

Code: Select all

INFO    Executing post-process-script mkvdts2ac3/mkvdts2ac3.py for dts sample                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /opt                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /home                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /tmp                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /usr                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /initrd                                                                                                                                     
INFO    mkvdts2ac3:     Processing dir:  /mnt                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /tmp2                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /sys                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /lib                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /.gphoto                                                                                                                                    
INFO    mkvdts2ac3:     Processing dir:  /lost+found                                                                                                                                 
INFO    mkvdts2ac3:     Processing dir:  /var                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /proc                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /etc                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /www                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /bin                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /boot                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /root                                                                                                                                       
INFO    mkvdts2ac3:     Processing dir:  /dev                                                                                                                                        
INFO    mkvdts2ac3:     Processing dir:  /sbin                                                                                                                                       
INFO    mkvdts2ac3: Traceback (most recent call last):                                                                                                                               
INFO    mkvdts2ac3:   File "/mnt/disk1/share/nzbget/ppscripts/mkvdts2ac3/mkvdts2ac3.py", line 879, in <module>                                                                       
INFO    mkvdts2ac3:     if args.md5 and (find_mount_point(origpath) != find_mount_point(destpath)):                                                                                  
INFO    mkvdts2ac3: AttributeError: 'Namespace' object has no attribute 'md5'                                                                                                        
ERROR   Post-process-script mkvdts2ac3/mkvdts2ac3.py for dts sample failed (terminated with unknown status)  
Looks like we are getting close. The error is at line 879 and there are only 897 lines in the script :)

For good measure, this is how the script is looking just now:

Code: Select all

#!/usr/bin/env python

#Copyright (C) 2012  Drew Thomson
#
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>.

##############################################################################
### NZBGET POST-PROCESSING SCRIPT                                          ###

# mkvdts2ac3.py is a python script for linux, windows or os x which can be used
# for converting the DTS in Matroska (MKV) files to AC3. It provides you with a
# set of options for controlling the resulting file.

##############################################################################
### OPTIONS                                                                ###

## These options take an argument.

# NZBGetdestdir.
#
#nzbgetdestdir=

# aaccustom.
#
#aaccustom=

# custom.
#
#custom=

# compress.
#
#compress=

# destdir.
#
#destdir=

# ffmpegpath.
#
#ffmpegpath=

# mkvtoolnixpath
#
#mkvtoolnixpath=

# track.
#
#track=

# wd.
#
#wd=

# verbose.
#
#verbose=

## These options don't take any arguments, they are only True or False

# aac (False, True).
#
#aac=

# aacstereo (False, True).
#
#aacstereo=

# default (False, True).
#
#default=

# external (False, True).
#
#external=

# force (False, True).
#
#force=

# initial (False, True).
#
#initial=

# keepdts (False, True).
#
#keepdts=

# mp4 (False, True).
#
#mp4=

# new (False, True).
#
#new=

# nodts (False, True).
#
#nodts=

# no subtitles (False, True).
#
#no_subtitles=

# no overwrite (False, True).
#
#overwrite=

# recursive (False, True).
#
#recursive=

# test (False, True).
#
#test=

#debug (False, True).
#
#debug=

### NZBGET POST-PROCESSING SCRIPT                                          ###
##############################################################################

import argparse
import os
import subprocess
import time
import glob
import re
import tempfile
import sys
import ConfigParser
import shutil
import hashlib
import textwrap
import errno

version = "1.0"

# check if called from sabnzbdplus
sab = False
if len(sys.argv) == 8:
    nzbgroup = sys.argv[6]
    ppstatus = sys.argv[7]
    if ppstatus.isdigit():
        if int(ppstatus) >= 0 and int(ppstatus) <= 3 and "." in nzbgroup:
            sab = True

elif os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0':
    #Logger.info("MAIN: Script triggered from NZBGet (11.0 or later).")

    # NZBGet argv: all passed as environment variables.
    # Exit codes used by NZBGet
    POSTPROCESS_PARCHECK=92
    POSTPROCESS_SUCCESS=93
    POSTPROCESS_ERROR=94
    POSTPROCESS_NONE=95

    # Check nzbget.conf options
    status = 0

    if os.environ['NZBOP_UNPACK'] != 'yes':
        #Logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
        sys.exit(POSTPROCESS_ERROR)

    # Check par status
    if os.environ['NZBPP_PARSTATUS'] == '3':
        #Logger.warning("Par-check successful, but Par-repair disabled, exiting")
        sys.exit(POSTPROCESS_NONE)

    if os.environ['NZBPP_PARSTATUS'] == '1':
        #Logger.warning("Par-check failed, setting status \"failed\"")
        status = 1

    # Check unpack status
    if os.environ['NZBPP_UNPACKSTATUS'] == '1':
        #Logger.warning("Unpack failed, setting status \"failed\"")
        status = 1

    if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] != '2':
        # Unpack is disabled or was skipped due to nzb-file properties or due to errors during par-check

        for dirpath, dirnames, filenames in os.walk(os.environ['NZBPP_DIRECTORY']):
            for file in filenames:
                fileExtension = os.path.splitext(file)[1]

                if fileExtension in ['.rar', '.7z'] or os.path.splitext(fileExtension)[1] in ['.rar', '.7z']:
                    #Logger.warning("Post-Process: Archive files exist but unpack skipped, setting status \"failed\"")
                    status = 1
                    break

                if fileExtension in ['.par2']:
                    #Logger.warning("Post-Process: Unpack skipped and par-check skipped (although par2-files exist), setting status \"failed\"g")
                    status = 1
                    break

        if os.path.isfile(os.path.join(os.environ['NZBPP_DIRECTORY'], "_brokenlog.txt")) and not status == 1:
            #Logger.warning("Post-Process: _brokenlog.txt exists, download is probably damaged, exiting")
            status = 1

        #if not status == 1:
            #Logger.info("Neither archive- nor par2-files found, _brokenlog.txt doesn't exist, considering download successful")

    # Check if destination directory exists (important for reprocessing of history items)
    if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
        #Logger.error("Post-Process: Nothing to post-process: destination directory %s doesn't exist", os.environ['NZBPP_DIRECTORY'])
        status = 1

    # All checks done, now launching the script.

    ppstatus = status
    if ppstatus >= 0 and ppstatus <= 3:
        sab = True

# create parser
parser = argparse.ArgumentParser(description='convert matroska (.mkv) video files audio portion from dts to ac3')

if os.environ.has_key('NZBOP_SCRIPTDIR'): # NZBGet
    args = parser.parse_args()
    args.fileordir = os.environ['NZBPP_DIRECTORY']
    args.aac = os.environ['NZBPO_AAC']
    args.aacstereo = os.environ['NZBPO_AACSTEREO']
    args.aaccustom = os.environ['NZBPO_AACCUSTOM']
    args.custom = os.environ['NZBPO_CUSTOM']
    args.default = os.environ['NZBPO_DEFAULT']
    args.sabdestdir = os.environ['NZBPO_NZBGETDESTDIR']
    args.compress = os.environ['NZBPO_COMPRESS']
    args.destdir = os.environ['NZBPO_DESTDIR']
    args.ffmpegpath = os.environ['NZBPO_FFMPEGPATH']
    args.mkvtoolnixpath = os.environ['NZBPO_MKVTOOLNIXPATH']
    args.track = os.environ['NZBPO_TRACK']
    args.wd = os.environ['NZBPO_WD']
    args.verbose = os.environ['NZBPO_VERBOSE']
    args.external = os.environ['NZBPO_EXTERNAL']
    args.force = os.environ['NZBPO_FORCE']
    args.initial = os.environ['NZBPO_INITIAL']
    args.keepdts = os.environ['NZBPO_KEEPDTS']
    args.mp4 = os.environ['NZBPO_MP4']
    args.new = os.environ['NZBPO_NEW']
    args.nodts = os.environ['NZBPO_NODTS']
    args.no_subtitles = os.environ['NZBPO_NO_SUBTITLES']
    args.overwrite = os.environ['NZBPO_OVERWRITE']
    args.recursive = os.environ['NZBPO_RECURSIVE']
    args.test = os.environ['NZBPO_TEST']
    args.debug = os.environ['NZBPO_DEBUG']
    if not args.verbose:
        args.verbose = 0

else: # default handling

# set config file arguments
    configFilename = os.path.join(os.path.dirname(sys.argv[0]), "mkvdts2ac3.cfg")

    if os.path.isfile(configFilename):
        config = ConfigParser.SafeConfigParser()
        config.read(configFilename)
        defaults = dict(config.items("mkvdts2ac3"))
        for key in defaults:
            if key == "verbose":
                defaults["verbose"] = int(defaults["verbose"])

        parser.set_defaults(**defaults)

    parser.add_argument('fileordir', metavar='FileOrDirectory', nargs='+', help='a file or directory (wildcards may be used)')

    parser.add_argument("--aac", help="Also add aac track", action="store_true")
    parser.add_argument("--aacstereo", help="Make aac track stereo instead of 6 channel", action="store_true")
    parser.add_argument("--aaccustom", metavar="TITLE", help="Custom AAC track title")
    parser.add_argument("-c", "--custom", metavar="TITLE", help="Custom AC3 track title")
    parser.add_argument("-d", "--default", help="Mark AC3 track as default", action="store_true")
    parser.add_argument("--destdir", metavar="DIRECTORY", help="Destination Directory")
    parser.add_argument("-e", "--external", action="store_true",
                        help="Leave AC3 track out of file. Does not modify the original matroska file. This overrides '-n' and '-d' arguments")
    parser.add_argument("-f", "--force", help="Force processing when AC3 track is detected", action="store_true")
    parser.add_argument("--ffmpegpath", metavar="DIRECTORY", help="Path of ffmpeg")
    parser.add_argument("-i", "--initial", help="New AC3 track will be first in the file", action="store_true")
    parser.add_argument("-k", "--keepdts", help="Keep external DTS track (implies '-n')", action="store_true")
    parser.add_argument("--md5", help="check md5 of files before removing the original if destination directory is on a different device than the original file", action="store_true")
    parser.add_argument("--mp4", help="create output in mp4 format", action="store_true")
    parser.add_argument("--mkvtoolnixpath", metavar="DIRECTORY", help="Path of mkvextract, mkvinfo and mkvmerge")
    parser.add_argument("-n", "--nodts", help="Do not retain the DTS track", action="store_true")
    parser.add_argument("--new", help="Do not copy over original. Create new adjacent file", action="store_true")
    parser.add_argument("--no-subtitles", help="Remove subtitles", action="store_true")
    parser.add_argument("-o", "--overwrite", help="Overwrite file if already there. This only applies if destdir or sabdestdir is set", action="store_true")
    parser.add_argument("-r", "--recursive", help="Recursively descend into directories", action="store_true")
    parser.add_argument("-s", "--compress", metavar="MODE", help="Apply header compression to streams (See mkvmerge's --compression)", default='none')
    parser.add_argument("--sabdestdir", metavar="DIRECTORY", help="SABnzbd Destination Directory")
    parser.add_argument("--stereo", help="Make ac3 track stereo instead of 6 channel", action="store_true")
    parser.add_argument("-t", "--track", metavar="TRACKID", help="Specify alternate DTS track. If it is not a DTS track it will default to the first DTS track found")
    parser.add_argument("-w", "--wd", metavar="FOLDER", help="Specify alternate temporary working directory")
    parser.add_argument("-v", "--verbose", help="Turn on verbose output. Use more v's for more verbosity. -v will output what it is doing. -vv will also output the command that it is running. -vvv will also output the command output", action="count")
    parser.add_argument("-V", "--version", help="Print script version information", action='version', version='%(prog)s ' + version + ' by Drew Thomson')
    parser.add_argument("--test", help="Print commands only, execute nothing", action="store_true")
    parser.add_argument("--debug", help="Print commands and pause before executing each", action="store_true")

    args = parser.parse_args()

    if not args.verbose:
        args.verbose = 0

def winexe(program):
    if sys.platform == "win32" and not program.endswith(".exe"):
        program += ".exe"
    return program

# set ffmpeg and mkvtoolnix paths
if args.mkvtoolnixpath:
    mkvinfo = os.path.join(args.mkvtoolnixpath, "mkvinfo")
    mkvinfo = winexe(mkvinfo)
    mkvmerge = os.path.join(args.mkvtoolnixpath, "mkvmerge")
    mkvmerge = winexe(mkvmerge)
    mkvextract = os.path.join(args.mkvtoolnixpath, "mkvextract")
    mkvextract = winexe(mkvextract)
if not args.mkvtoolnixpath or not os.path.exists(mkvinfo):
    mkvinfo = "mkvinfo"
if not args.mkvtoolnixpath or not os.path.exists(mkvmerge):
    mkvmerge = "mkvmerge"
if not args.mkvtoolnixpath or not os.path.exists(mkvextract):
    mkvextract = "mkvextract"
   
if args.ffmpegpath:
    ffmpeg = os.path.join(args.ffmpegpath, "ffmpeg")
    ffmpeg = winexe(ffmpeg)
if not args.ffmpegpath or not os.path.exists(ffmpeg):
    ffmpeg = "ffmpeg"


# check paths
def which(program):
    if sys.platform == "win32" and not program.endswith(".exe"):
        program += ".exe"
    def is_exe(fpath):
        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

    fpath = os.path.split(program)[0]
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file

    return None

missingprereqs = False
missinglist = []
if not which(mkvextract):
    missingprereqs = True
    missinglist.append("mkvextract")
if not which(mkvinfo):
    missingprereqs = True
    missinglist.append("mkvinfo")
if not which(mkvmerge):
    missingprereqs = True
    missinglist.append("mkvmerge")
if not which(ffmpeg):
    missingprereqs = True
    missinglist.append("ffmpeg")
if missingprereqs:
    sys.stdout.write("You are missing the following prerequisite tools: ")
    for tool in missinglist:
        sys.stdout.write(tool + " ")
    if not args.mkvtoolnixpath and not args.ffmpegpath:
        print "\nYou can use --mkvtoolnixpath and --ffmpegpath to specify the path"
    else:
        print   
    sys.exit(1)

if not args.verbose:
    args.verbose = 0

if args.verbose < 2 and (args.test or args.debug):
    args.verbose = 2
   
if sab:
    args.fileordir = [args.fileordir[0]]
    args.verbose = 3

if args.debug and args.verbose == 0:
    args.verbose = 1

def doprint(mystr, v):
    if args.verbose >= v:
        sys.stdout.write(mystr)

def silentremove(filename):
    try:
        os.remove(filename)
    except OSError, e:
        if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory
            raise # re-raise exception if a different error occured

def elapsedstr(starttime):
    elapsed = (time.time() - starttime)
    minutes = int(elapsed / 60)
    mplural = 's'
    if minutes == 1:
        mplural = ''
    seconds = int(elapsed) % 60
    splural = 's'
    if seconds == 1:
        splural = ''
    return str(minutes) + " minute" + mplural + " " + str(seconds) + " second" + splural

def getduration(time):
    (hms, ms) = time.split('.')
    (h, m, s) = hms.split(':')
    totalms = int(ms) + (int(s) * 100) + (int(m) * 100 * 60) + (int(h) * 100 * 60 * 60)
    return totalms
   
def runcommand(title, cmdlist):
    if args.debug:
        raw_input("Press Enter to continue...")
    cmdstarttime = time.time()
    if args.verbose >= 1:
        sys.stdout.write(title)
        if args.verbose >= 2:
            cmdstr = ''
            for e in cmdlist:
                cmdstr += e + ' '
            print
            print "    Running command:"
            print textwrap.fill(cmdstr.rstrip(), initial_indent='      ', subsequent_indent='      ')
    if not args.test:
        if args.verbose >= 3:
            subprocess.call(cmdlist)
        elif args.verbose >= 1:
            if "ffmpeg" in cmdlist[0]:
                proc = subprocess.Popen(cmdlist, stderr=subprocess.PIPE)
                line = ''
                duration_regex = re.compile("  Duration: (\d+:\d\d:\d\d\.\d\d),")
                progress_regex = re.compile("size= +\d+.*time=(\d+:\d\d:\d\d\.\d\d) bitrate=")
                duration = False
                while True:
                    if not duration:
                        durationline = proc.stderr.readline()
                        match = duration_regex.match(durationline)
                        if match:
                            duration = getduration(match.group(1))
                    else: 
                        out = proc.stderr.read(1)
                        if out == '' and proc.poll() != None:
                            break
                        if out != '\r':
                            line += out
                        else:
                            if 'size= ' in line:
                                match = progress_regex.search(line)
                                if match:
                                    percentage = int(float(getduration(match.group(1)) / float(duration)) * 100)
                                    if percentage > 100:
                                        percentage = 100
                                    sys.stdout.write("\r" + title + str(percentage) + '%')
                            line = ''
                        sys.stdout.flush()
                print "\r" + title + elapsedstr(cmdstarttime)
            else:
                proc = subprocess.Popen(cmdlist, stdout=subprocess.PIPE)
                line = ''
                progress_regex = re.compile("Progress: (\d+%)")
                while True:
                    out = proc.stdout.read(1)
                    if out == '' and proc.poll() != None:
                        break
                    if out != '\r':
                        line += out
                    else:
                        if 'Progress: ' in line:
                            match = progress_regex.search(line)
                            if match:
                                percentage = match.group(1)
                                sys.stdout.write("\r" + title + percentage)
                        line = ''
                    sys.stdout.flush()
                print "\r" + title + elapsedstr(cmdstarttime)
        else:
            subprocess.call(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def find_mount_point(path):
    path = os.path.abspath(path)
    while not os.path.ismount(path):
        path = os.path.dirname(path)
    return path

def getmd5(fname, block_size=2**12):
    md5 = hashlib.md5()
    with open(fname, 'rb') as f:
        while True:
            data = f.read(block_size)
            if not data:
                break
            md5.update(data)
        doprint(fname + ": " + md5.hexdigest() + "\n", 3)
    return md5.hexdigest()

def check_md5tree(orig, dest):
    rt = True
    orig = os.path.abspath(orig)
    dest = os.path.abspath(dest)
    for ofile in os.listdir(orig):
        if rt == True:
            if os.path.isdir(os.path.join(orig, ofile)):
                doprint("dir: " + os.path.join(orig, ofile) + "\n", 3)
                odir = os.path.join(orig, ofile)
                ddir = os.path.join(dest, ofile)
                rt = check_md5tree(odir, ddir)
            else:
                doprint("file: " + os.path.join(orig, ofile) + "\n", 3)
                if getmd5(os.path.join(orig, ofile)) != getmd5(os.path.join(dest, ofile)):
                    rt = False
    return rt

def process(ford):
    if os.path.isdir(ford):
        doprint("    Processing dir:  " + ford + "\n", 3)
        if args.recursive:
            for f in os.listdir(ford):
                process(os.path.join(ford, f))
    else:
        doprint("    Processing file: " + ford + "\n", 3)
        # check if file is an mkv file
        child = subprocess.Popen([mkvmerge, "-i", ford], stdout=subprocess.PIPE)
        child.communicate()[0]
        if child.returncode == 0:
            starttime = time.time()
           
            # set up temp dir
            tempdir = False
            if args.wd:
                tempdir = args.wd
                if not os.path.exists(tempdir):
                    os.makedirs(tempdir)
            else:
                tempdir = tempfile.mkdtemp()
                tempdir = os.path.join(tempdir, "mkvdts2ac3")
               
            (dirName, fileName) = os.path.split(ford)
            fileBaseName = os.path.splitext(fileName)[0]
           
            doprint("filename: " + fileName + "\n", 1)
           
            dtsfile = fileBaseName + '.dts'
            tempdtsfile = os.path.join(tempdir, dtsfile)
            ac3file = fileBaseName + '.ac3'
            tempac3file = os.path.join(tempdir, ac3file)
            aacfile = fileBaseName + '.aac'
            tempaacfile = os.path.join(tempdir, aacfile)
            tcfile = fileBaseName + '.tc'
            temptcfile = os.path.join(tempdir, tcfile)
            newmkvfile = fileBaseName + '.mkv'
            tempnewmkvfile = os.path.join(tempdir, newmkvfile)
            adjacentmkvfile = os.path.join(dirName, fileBaseName + '.new.mkv')
            mp4file = os.path.join(dirName, fileBaseName + '.mp4')
            fname = fileName
           
            # get dts track id and video track id
            output = subprocess.check_output([mkvmerge, "-i", ford])
            lines = output.split("\n")
            altdtstrackid = False
            dtstrackid = False
            videotrackid = False
            alreadygotac3 = False
            audiotracks = []
            for line in lines:
                linelist = line.split(' ')
                trackid = False
                if len(linelist) > 2:
                    trackid = linelist[2]
                    linelist = trackid.split(':')
                    trackid = linelist[0]
                if 'audio (A_' in line:
                    audiotracks.append(trackid)
                if ': audio (A_DTS)' in line:
                    dtstrackid = trackid
                elif 'video (V_' in line:
                    videotrackid = trackid
                elif ': audio (A_AC3)' in line:
                    alreadygotac3 = True
                if args.track:
                    if "Track ID " + args.track + ": audio (A_DTS)" in line:
                        altdtstrackid = args.track
            if altdtstrackid:
                dtstrackid = altdtstrackid
           
            if not dtstrackid:
                doprint("  No DTS track found\n", 1)
            elif alreadygotac3 and not args.force:
                doprint("  Already has AC3 track\n", 1)
            else:
                # get dtstrack info
                output = subprocess.check_output([mkvinfo, ford])
                lines = output.split("\n")
                dtstrackinfo = []
                startcount = 0
                for line in lines:
                    match = re.search(r'^\|( *)\+', line)
                    linespaces = startcount
                    if match:
                        linespaces = len(match.group(1))
                    if startcount == 0:
                        if "track ID for mkvmerge & mkvextract:" in line:
                            if "track ID for mkvmerge & mkvextract: " + dtstrackid in line:
                                startcount = linespaces
                        elif "+ Track number: " + dtstrackid in line:
                            startcount = linespaces
                    if linespaces < startcount:
                        break
                    if startcount != 0:
                        dtstrackinfo.append(line)
               
                # get dts language
                dtslang = "eng"
                for line in dtstrackinfo:
                    if "Language" in line:
                        dtslang = line.split()[-1]
               
                # get ac3 track name
                ac3name = False
                if args.custom:
                    ac3name = args.custom
                else:
                    for line in dtstrackinfo:
                        if "+ Name: " in line:
                            ac3name = line.split("+ Name: ")[-1]
                            ac3name = ac3name.replace("DTS", "AC3")
                            ac3name = ac3name.replace("dts", "ac3")
                            if args.stereo:
                                ac3name = ac3name.replace("5.1", "Stereo")
               
                # get aac track name
                aacname = False
                if args.aaccustom:
                    aacname = args.aaccustom
                else:
                    for line in dtstrackinfo:
                        if "+ Name: " in line:
                            aacname = line.split("+ Name: ")[-1]
                            aacname = aacname.replace("DTS", "AAC")
                            aacname = aacname.replace("dts", "aac")
                            if args.aacstereo:
                                aacname = aacname.replace("5.1", "Stereo")
               
                totaljobs = 4
                jobnum = 1
                if args.aac:
                    totaljobs += 1
                if args.mp4:
                    totaljobs += 1
               
                # extract timecodes
                tctitle = "  Extracting Timecodes  [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                jobnum += 1
                tccmd = [mkvextract, "timecodes_v2", ford, dtstrackid + ":" + temptcfile]
                runcommand(tctitle, tccmd)
               
                delay = False
                if not args.test:
                    # get the delay if there is any
                    fp = open(temptcfile)
                    for i, line in enumerate(fp):
                        if i == 1:
                            delay = line
                            break
                    fp.close()
               
                # extract dts track
                extracttitle = "  Extracting DTS track  [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                jobnum += 1
                extractcmd = [mkvextract, "tracks", ford, dtstrackid + ':' + tempdtsfile]
                runcommand(extracttitle, extractcmd)
               
                # convert DTS to AC3
                converttitle = "  Converting DTS to AC3 [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                jobnum += 1
                audiochannels = 6
                if args.stereo:
                    audiochannels = 2
                convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "ac3", "-ac", str(audiochannels), "-ab", "448k", tempac3file]
                runcommand(converttitle, convertcmd)
               
                if args.aac:
                    converttitle = "  Converting DTS to AAC [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                    jobnum += 1
                    audiochannels = 6
                    if args.aacstereo:
                        audiochannels = 2
                    convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "libfaac", "-ac", str(audiochannels), "-ab", "448k", tempaacfile]
                    runcommand(converttitle, convertcmd)
                    if not os.path.isfile(tempaacfile) or os.path.getsize(tempaacfile) == 0:
                        convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "libvo_aacenc", "-ac", str(audiochannels), "-ab", "448k", tempaacfile]
                        runcommand(converttitle, convertcmd)
                    if not os.path.isfile(tempaacfile) or os.path.getsize(tempaacfile) == 0:
                        convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "aac", "-strict", "experimental", "-ac", str(audiochannels), "-ab", "448k", tempaacfile]
                        runcommand(converttitle, convertcmd)
                    if not os.path.isfile(tempaacfile) or os.path.getsize(tempaacfile) == 0:
                        args.aac = False
                        print "ERROR: ffmpeg can't use any aac codecs. Please try to get libfaac, libvo_aacenc, or a newer version of ffmpeg with the experimental aac codec installed"
                       
                if args.external:
                    if not args.test:
                        shutil.move(tempac3file, os.path.join(dirName, fileBaseName + '.ac3'))
                        fname = ac3file
                else:
                    # remux
                    remuxtitle = "  Remuxing AC3 into MKV [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                    jobnum += 1
                    # Start to "build" command
                    remux = [mkvmerge]
                   
                    # Remove subtitles
                    if args.no_subtitles:
                        remux.append("--no-subtitles")
                   
                    # Puts the AC3 track as the second in the file if indicated as initial
                    if args.initial:
                        remux.append("--track-order")
                        if args.aac:
                            remux.append("1:0,2:0")
                        else:
                            remux.append("1:0")

                    # If user doesn't want the original DTS track drop it
                    comp = args.compress
                    if args.nodts or args.keepdts:
                        if len(audiotracks) == 1:
                            remux.append("-A")
                        else:
                            audiotracks = [audiotrack for audiotrack in audiotracks if audiotrack != dtstrackid]
                            remux.append("-a")
                            remux.append(",".join(audiotracks))
                            for tid in audiotracks:
                                remux.append("--compression")
                                remux.append(tid + ":" + comp)
                   
                    # Add original MKV file, set header compression scheme         
                    remux.append("--compression")
                    remux.append(videotrackid + ":" + comp)
                    remux.append(ford)
                   
                    # If user wants new AC3 as default then add appropriate arguments to command
                    if args.default:
                        remux.append("--default-track")
                        remux.append("0:0")
                   
                    # Set the language
                    remux.append("--language")
                    remux.append("0:" + dtslang)
                   
                    # If the name was set for the original DTS track set it for the AC3
                    if ac3name:
                        remux.append("--track-name")
                        remux.append("0:\"" + ac3name.rstrip() + "\"")
                   
                    # set delay if there is any
                    if delay:
                        remux.append("--sync")
                        remux.append("0:" + delay.rstrip())
                       
                    # Set track compression scheme and append new AC3
                    remux.append("--compression")
                    remux.append("0:" + comp)
                    remux.append(tempac3file)
                   
                    if args.aac:
                        # If the name was set for the original DTS track set it for the AAC
                        if aacname:
                            remux.append("--track-name")
                            remux.append("0:\"" + aacname.rstrip() + "\"")
                           
                        # Set track compression scheme and append new AAC
                        remux.append("--compression")
                        remux.append("0:" + comp)
                        remux.append(tempaacfile)
                   
                    # Declare output file
                    remux.append("-o")
                    remux.append(tempnewmkvfile)
                   
                    runcommand(remuxtitle, remux) 

                    if not args.test:
                        if args.mp4:
                            converttitle = "  Converting MKV to MP4 [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                            convertcmd = [ffmpeg, "-i", tempnewmkvfile, "-map", "0", "-vcodec", "copy", "-acodec", "copy", "-c:s", "mov_text", mp4file]
                            runcommand(converttitle, convertcmd)
                            silentremove(ford)
                        else:
                            #~ replace old mkv with new mkv
                            if args.new:
                                shutil.move(tempnewmkvfile, adjacentmkvfile)
                            else:
                                silentremove(ford)
                                shutil.move(tempnewmkvfile, ford)

                if not args.test:
                    #~ clean up temp folder
                    if args.keepdts and not args.external:
                        shutil.move(tempdtsfile, os.path.join(dirName, fileBaseName + ".dts"))
                        fname = dtsfile
                    else:
                        silentremove(tempdtsfile)
                    if not args.external:
                        silentremove(tempac3file)
                        silentremove(tempaacfile)
                        silentremove(temptcfile)
                    if not os.listdir(tempdir):
                        os.rmdir(tempdir)

                #~ print out time taken
                elapsed = (time.time() - starttime)
                minutes = int(elapsed / 60)
                seconds = int(elapsed) % 60
                doprint("  " + fileName + " finished in: " + str(minutes) + " minutes " + str(seconds) + " seconds\n", 1)

            return fname

totalstime = time.time()
for a in args.fileordir:
    for ford in glob.glob(a):
        fname = False
        if os.path.isdir(ford):
            for f in os.listdir(ford):
                process(os.path.join(ford, f))
        else:
            fname = process(ford)
        destdir = False
        if args.destdir:
            destdir = args.destdir
        if sab and args.sabdestdir:
            destdir = args.sabdestdir
        if destdir:
            if fname:
                (dirName, fileName) = os.path.split(ford)
                destfile = os.path.join(destdir, fname)
                origfile = os.path.join(dirName, fname)
                if args.md5 and (find_mount_point(dirName) != find_mount_point(destdir)):
                    if os.path.exists(destfile):
                        if args.overwrite:
                            silentremove(destfile)
                            shutil.copyfile(origfile, destfile)
                            if getmd5(origfile) == getmd5(destfile):
                                silentremove(origfile)
                            else:
                                print "MD5's don't match."
                        else:
                            print "File " + destfile + " already exists"
                    else:
                        doprint("copying: " + origfile + " --> " + destfile + "\n", 3)
                        shutil.copyfile(origfile, destfile)
                        if getmd5(origfile) == getmd5(destfile):
                            silentremove(origfile)
                        else:
                            print "MD5's don't match."
                else: 
                    if os.path.exists(destfile):
                        if args.overwrite:
                            silentremove(destfile)
                            shutil.move(origfile, destfile)
                        else:
                            print "File " + destfile + " already exists"
                    else:
                        shutil.move(origfile, destfile)
            else:
                origpath = os.path.abspath(ford)
                destpath = os.path.join(destdir, os.path.basename(os.path.normpath(ford)))
                if args.md5 and (find_mount_point(origpath) != find_mount_point(destpath)):
                    if os.path.exists(destpath) and args.overwrite:
                        shutil.rmtree(destpath)
                    elif os.path.exists(destpath):   
                        print "Directory " + destpath + " already exists"
                    else:
                        shutil.copytree(origpath, destpath)
                        if check_md5tree(origpath, destpath):
                            shutil.rmtree(origpath)
                        else:
                            print "MD5's don't match."
                else:
                    shutil.move(origpath, destpath)
                   
if sab:
    sys.stdout.write("mkv dts -> ac3 conversion: " + elapsedstr(totalstime))
else:
    doprint("Total Time: " + elapsedstr(totalstime), 1)

clintonhall
Posts: 449
Joined: 15 Dec 2012, 01:52
Location: Australia
Contact:

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by clintonhall » 04 Dec 2013, 19:56

try adding args.md5 = True (or false)... it appears we need to ensure every arg exists... not just those that would be passed from the cfg.

Code: Select all

#!/usr/bin/env python

#Copyright (C) 2012  Drew Thomson
#
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>.

##############################################################################
### NZBGET POST-PROCESSING SCRIPT                                          ###

# mkvdts2ac3.py is a python script for linux, windows or os x which can be used
# for converting the DTS in Matroska (MKV) files to AC3. It provides you with a
# set of options for controlling the resulting file.

##############################################################################
### OPTIONS                                                                ###

## These options take an argument.

# NZBGetdestdir.
#
#nzbgetdestdir=

# aaccustom.
#
#aaccustom=

# custom.
#
#custom=

# compress.
#
#compress=

# destdir.
#
#destdir=

# ffmpegpath.
#
#ffmpegpath=

# mkvtoolnixpath
#
#mkvtoolnixpath=

# track.
#
#track=

# wd.
#
#wd=

# verbose.
#
#verbose=

## These options don't take any arguments, they are only True or False

# aac (False, True).
#
#aac=

# aacstereo (False, True).
#
#aacstereo=

# default (False, True).
#
#default=

# external (False, True).
#
#external=

# force (False, True).
#
#force=

# initial (False, True).
#
#initial=

# keepdts (False, True).
#
#keepdts=

# mp4 (False, True).
#
#mp4=

# new (False, True).
#
#new=

# nodts (False, True).
#
#nodts=

# no subtitles (False, True).
#
#no_subtitles=

# no overwrite (False, True).
#
#overwrite=

# recursive (False, True).
#
#recursive=

# test (False, True).
#
#test=

#debug (False, True).
#
#debug=

### NZBGET POST-PROCESSING SCRIPT                                          ###
##############################################################################

import argparse
import os
import subprocess
import time
import glob
import re
import tempfile
import sys
import ConfigParser
import shutil
import hashlib
import textwrap
import errno

version = "1.0"

# check if called from sabnzbdplus
sab = False
if len(sys.argv) == 8:
    nzbgroup = sys.argv[6]
    ppstatus = sys.argv[7]
    if ppstatus.isdigit():
        if int(ppstatus) >= 0 and int(ppstatus) <= 3 and "." in nzbgroup:
            sab = True

elif os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0':
    #Logger.info("MAIN: Script triggered from NZBGet (11.0 or later).")

    # NZBGet argv: all passed as environment variables.
    # Exit codes used by NZBGet
    POSTPROCESS_PARCHECK=92
    POSTPROCESS_SUCCESS=93
    POSTPROCESS_ERROR=94
    POSTPROCESS_NONE=95

    # Check nzbget.conf options
    status = 0

    if os.environ['NZBOP_UNPACK'] != 'yes':
        #Logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
        sys.exit(POSTPROCESS_ERROR)

    # Check par status
    if os.environ['NZBPP_PARSTATUS'] == '3':
        #Logger.warning("Par-check successful, but Par-repair disabled, exiting")
        sys.exit(POSTPROCESS_NONE)

    if os.environ['NZBPP_PARSTATUS'] == '1':
        #Logger.warning("Par-check failed, setting status \"failed\"")
        status = 1

    # Check unpack status
    if os.environ['NZBPP_UNPACKSTATUS'] == '1':
        #Logger.warning("Unpack failed, setting status \"failed\"")
        status = 1

    if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] != '2':
        # Unpack is disabled or was skipped due to nzb-file properties or due to errors during par-check

        for dirpath, dirnames, filenames in os.walk(os.environ['NZBPP_DIRECTORY']):
            for file in filenames:
                fileExtension = os.path.splitext(file)[1]

                if fileExtension in ['.rar', '.7z'] or os.path.splitext(fileExtension)[1] in ['.rar', '.7z']:
                    #Logger.warning("Post-Process: Archive files exist but unpack skipped, setting status \"failed\"")
                    status = 1
                    break

                if fileExtension in ['.par2']:
                    #Logger.warning("Post-Process: Unpack skipped and par-check skipped (although par2-files exist), setting status \"failed\"g")
                    status = 1
                    break

        if os.path.isfile(os.path.join(os.environ['NZBPP_DIRECTORY'], "_brokenlog.txt")) and not status == 1:
            #Logger.warning("Post-Process: _brokenlog.txt exists, download is probably damaged, exiting")
            status = 1

        #if not status == 1:
            #Logger.info("Neither archive- nor par2-files found, _brokenlog.txt doesn't exist, considering download successful")

    # Check if destination directory exists (important for reprocessing of history items)
    if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
        #Logger.error("Post-Process: Nothing to post-process: destination directory %s doesn't exist", os.environ['NZBPP_DIRECTORY'])
        status = 1

    # All checks done, now launching the script.

    ppstatus = status
    if ppstatus >= 0 and ppstatus <= 3:
        sab = True

# create parser
parser = argparse.ArgumentParser(description='convert matroska (.mkv) video files audio portion from dts to ac3')

if os.environ.has_key('NZBOP_SCRIPTDIR'): # NZBGet
    args = parser.parse_args()
    args.fileordir = os.environ['NZBPP_DIRECTORY']
    args.aac = os.environ['NZBPO_AAC']
    args.aacstereo = os.environ['NZBPO_AACSTEREO']
    args.aaccustom = os.environ['NZBPO_AACCUSTOM']
    args.custom = os.environ['NZBPO_CUSTOM']
    args.default = os.environ['NZBPO_DEFAULT']
    args.sabdestdir = os.environ['NZBPO_NZBGETDESTDIR']
    args.compress = os.environ['NZBPO_COMPRESS']
    args.destdir = os.environ['NZBPO_DESTDIR']
    args.ffmpegpath = os.environ['NZBPO_FFMPEGPATH']
    args.mkvtoolnixpath = os.environ['NZBPO_MKVTOOLNIXPATH']
    args.track = os.environ['NZBPO_TRACK']
    args.wd = os.environ['NZBPO_WD']
    args.verbose = os.environ['NZBPO_VERBOSE']
    args.external = os.environ['NZBPO_EXTERNAL']
    args.force = os.environ['NZBPO_FORCE']
    args.initial = os.environ['NZBPO_INITIAL']
    args.keepdts = os.environ['NZBPO_KEEPDTS']
    args.mp4 = os.environ['NZBPO_MP4']
    args.new = os.environ['NZBPO_NEW']
    args.nodts = os.environ['NZBPO_NODTS']
    args.no_subtitles = os.environ['NZBPO_NO_SUBTITLES']
    args.overwrite = os.environ['NZBPO_OVERWRITE']
    args.recursive = os.environ['NZBPO_RECURSIVE']
    args.test = os.environ['NZBPO_TEST']
    args.debug = os.environ['NZBPO_DEBUG']
    args.md5 = "True"
    if not args.verbose:
        args.verbose = 0

else: # default handling

# set config file arguments
    configFilename = os.path.join(os.path.dirname(sys.argv[0]), "mkvdts2ac3.cfg")

    if os.path.isfile(configFilename):
        config = ConfigParser.SafeConfigParser()
        config.read(configFilename)
        defaults = dict(config.items("mkvdts2ac3"))
        for key in defaults:
            if key == "verbose":
                defaults["verbose"] = int(defaults["verbose"])

        parser.set_defaults(**defaults)

    parser.add_argument('fileordir', metavar='FileOrDirectory', nargs='+', help='a file or directory (wildcards may be used)')

    parser.add_argument("--aac", help="Also add aac track", action="store_true")
    parser.add_argument("--aacstereo", help="Make aac track stereo instead of 6 channel", action="store_true")
    parser.add_argument("--aaccustom", metavar="TITLE", help="Custom AAC track title")
    parser.add_argument("-c", "--custom", metavar="TITLE", help="Custom AC3 track title")
    parser.add_argument("-d", "--default", help="Mark AC3 track as default", action="store_true")
    parser.add_argument("--destdir", metavar="DIRECTORY", help="Destination Directory")
    parser.add_argument("-e", "--external", action="store_true",
                        help="Leave AC3 track out of file. Does not modify the original matroska file. This overrides '-n' and '-d' arguments")
    parser.add_argument("-f", "--force", help="Force processing when AC3 track is detected", action="store_true")
    parser.add_argument("--ffmpegpath", metavar="DIRECTORY", help="Path of ffmpeg")
    parser.add_argument("-i", "--initial", help="New AC3 track will be first in the file", action="store_true")
    parser.add_argument("-k", "--keepdts", help="Keep external DTS track (implies '-n')", action="store_true")
    parser.add_argument("--md5", help="check md5 of files before removing the original if destination directory is on a different device than the original file", action="store_true")
    parser.add_argument("--mp4", help="create output in mp4 format", action="store_true")
    parser.add_argument("--mkvtoolnixpath", metavar="DIRECTORY", help="Path of mkvextract, mkvinfo and mkvmerge")
    parser.add_argument("-n", "--nodts", help="Do not retain the DTS track", action="store_true")
    parser.add_argument("--new", help="Do not copy over original. Create new adjacent file", action="store_true")
    parser.add_argument("--no-subtitles", help="Remove subtitles", action="store_true")
    parser.add_argument("-o", "--overwrite", help="Overwrite file if already there. This only applies if destdir or sabdestdir is set", action="store_true")
    parser.add_argument("-r", "--recursive", help="Recursively descend into directories", action="store_true")
    parser.add_argument("-s", "--compress", metavar="MODE", help="Apply header compression to streams (See mkvmerge's --compression)", default='none')
    parser.add_argument("--sabdestdir", metavar="DIRECTORY", help="SABnzbd Destination Directory")
    parser.add_argument("--stereo", help="Make ac3 track stereo instead of 6 channel", action="store_true")
    parser.add_argument("-t", "--track", metavar="TRACKID", help="Specify alternate DTS track. If it is not a DTS track it will default to the first DTS track found")
    parser.add_argument("-w", "--wd", metavar="FOLDER", help="Specify alternate temporary working directory")
    parser.add_argument("-v", "--verbose", help="Turn on verbose output. Use more v's for more verbosity. -v will output what it is doing. -vv will also output the command that it is running. -vvv will also output the command output", action="count")
    parser.add_argument("-V", "--version", help="Print script version information", action='version', version='%(prog)s ' + version + ' by Drew Thomson')
    parser.add_argument("--test", help="Print commands only, execute nothing", action="store_true")
    parser.add_argument("--debug", help="Print commands and pause before executing each", action="store_true")

    args = parser.parse_args()

    if not args.verbose:
        args.verbose = 0

def winexe(program):
    if sys.platform == "win32" and not program.endswith(".exe"):
        program += ".exe"
    return program

# set ffmpeg and mkvtoolnix paths
if args.mkvtoolnixpath:
    mkvinfo = os.path.join(args.mkvtoolnixpath, "mkvinfo")
    mkvinfo = winexe(mkvinfo)
    mkvmerge = os.path.join(args.mkvtoolnixpath, "mkvmerge")
    mkvmerge = winexe(mkvmerge)
    mkvextract = os.path.join(args.mkvtoolnixpath, "mkvextract")
    mkvextract = winexe(mkvextract)
if not args.mkvtoolnixpath or not os.path.exists(mkvinfo):
    mkvinfo = "mkvinfo"
if not args.mkvtoolnixpath or not os.path.exists(mkvmerge):
    mkvmerge = "mkvmerge"
if not args.mkvtoolnixpath or not os.path.exists(mkvextract):
    mkvextract = "mkvextract"
   
if args.ffmpegpath:
    ffmpeg = os.path.join(args.ffmpegpath, "ffmpeg")
    ffmpeg = winexe(ffmpeg)
if not args.ffmpegpath or not os.path.exists(ffmpeg):
    ffmpeg = "ffmpeg"


# check paths
def which(program):
    if sys.platform == "win32" and not program.endswith(".exe"):
        program += ".exe"
    def is_exe(fpath):
        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

    fpath = os.path.split(program)[0]
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file

    return None

missingprereqs = False
missinglist = []
if not which(mkvextract):
    missingprereqs = True
    missinglist.append("mkvextract")
if not which(mkvinfo):
    missingprereqs = True
    missinglist.append("mkvinfo")
if not which(mkvmerge):
    missingprereqs = True
    missinglist.append("mkvmerge")
if not which(ffmpeg):
    missingprereqs = True
    missinglist.append("ffmpeg")
if missingprereqs:
    sys.stdout.write("You are missing the following prerequisite tools: ")
    for tool in missinglist:
        sys.stdout.write(tool + " ")
    if not args.mkvtoolnixpath and not args.ffmpegpath:
        print "\nYou can use --mkvtoolnixpath and --ffmpegpath to specify the path"
    else:
        print   
    sys.exit(1)

if not args.verbose:
    args.verbose = 0

if args.verbose < 2 and (args.test or args.debug):
    args.verbose = 2
   
if sab:
    args.fileordir = [args.fileordir[0]]
    args.verbose = 3

if args.debug and args.verbose == 0:
    args.verbose = 1

def doprint(mystr, v):
    if args.verbose >= v:
        sys.stdout.write(mystr)

def silentremove(filename):
    try:
        os.remove(filename)
    except OSError, e:
        if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory
            raise # re-raise exception if a different error occured

def elapsedstr(starttime):
    elapsed = (time.time() - starttime)
    minutes = int(elapsed / 60)
    mplural = 's'
    if minutes == 1:
        mplural = ''
    seconds = int(elapsed) % 60
    splural = 's'
    if seconds == 1:
        splural = ''
    return str(minutes) + " minute" + mplural + " " + str(seconds) + " second" + splural

def getduration(time):
    (hms, ms) = time.split('.')
    (h, m, s) = hms.split(':')
    totalms = int(ms) + (int(s) * 100) + (int(m) * 100 * 60) + (int(h) * 100 * 60 * 60)
    return totalms
   
def runcommand(title, cmdlist):
    if args.debug:
        raw_input("Press Enter to continue...")
    cmdstarttime = time.time()
    if args.verbose >= 1:
        sys.stdout.write(title)
        if args.verbose >= 2:
            cmdstr = ''
            for e in cmdlist:
                cmdstr += e + ' '
            print
            print "    Running command:"
            print textwrap.fill(cmdstr.rstrip(), initial_indent='      ', subsequent_indent='      ')
    if not args.test:
        if args.verbose >= 3:
            subprocess.call(cmdlist)
        elif args.verbose >= 1:
            if "ffmpeg" in cmdlist[0]:
                proc = subprocess.Popen(cmdlist, stderr=subprocess.PIPE)
                line = ''
                duration_regex = re.compile("  Duration: (\d+:\d\d:\d\d\.\d\d),")
                progress_regex = re.compile("size= +\d+.*time=(\d+:\d\d:\d\d\.\d\d) bitrate=")
                duration = False
                while True:
                    if not duration:
                        durationline = proc.stderr.readline()
                        match = duration_regex.match(durationline)
                        if match:
                            duration = getduration(match.group(1))
                    else: 
                        out = proc.stderr.read(1)
                        if out == '' and proc.poll() != None:
                            break
                        if out != '\r':
                            line += out
                        else:
                            if 'size= ' in line:
                                match = progress_regex.search(line)
                                if match:
                                    percentage = int(float(getduration(match.group(1)) / float(duration)) * 100)
                                    if percentage > 100:
                                        percentage = 100
                                    sys.stdout.write("\r" + title + str(percentage) + '%')
                            line = ''
                        sys.stdout.flush()
                print "\r" + title + elapsedstr(cmdstarttime)
            else:
                proc = subprocess.Popen(cmdlist, stdout=subprocess.PIPE)
                line = ''
                progress_regex = re.compile("Progress: (\d+%)")
                while True:
                    out = proc.stdout.read(1)
                    if out == '' and proc.poll() != None:
                        break
                    if out != '\r':
                        line += out
                    else:
                        if 'Progress: ' in line:
                            match = progress_regex.search(line)
                            if match:
                                percentage = match.group(1)
                                sys.stdout.write("\r" + title + percentage)
                        line = ''
                    sys.stdout.flush()
                print "\r" + title + elapsedstr(cmdstarttime)
        else:
            subprocess.call(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def find_mount_point(path):
    path = os.path.abspath(path)
    while not os.path.ismount(path):
        path = os.path.dirname(path)
    return path

def getmd5(fname, block_size=2**12):
    md5 = hashlib.md5()
    with open(fname, 'rb') as f:
        while True:
            data = f.read(block_size)
            if not data:
                break
            md5.update(data)
        doprint(fname + ": " + md5.hexdigest() + "\n", 3)
    return md5.hexdigest()

def check_md5tree(orig, dest):
    rt = True
    orig = os.path.abspath(orig)
    dest = os.path.abspath(dest)
    for ofile in os.listdir(orig):
        if rt == True:
            if os.path.isdir(os.path.join(orig, ofile)):
                doprint("dir: " + os.path.join(orig, ofile) + "\n", 3)
                odir = os.path.join(orig, ofile)
                ddir = os.path.join(dest, ofile)
                rt = check_md5tree(odir, ddir)
            else:
                doprint("file: " + os.path.join(orig, ofile) + "\n", 3)
                if getmd5(os.path.join(orig, ofile)) != getmd5(os.path.join(dest, ofile)):
                    rt = False
    return rt

def process(ford):
    if os.path.isdir(ford):
        doprint("    Processing dir:  " + ford + "\n", 3)
        if args.recursive:
            for f in os.listdir(ford):
                process(os.path.join(ford, f))
    else:
        doprint("    Processing file: " + ford + "\n", 3)
        # check if file is an mkv file
        child = subprocess.Popen([mkvmerge, "-i", ford], stdout=subprocess.PIPE)
        child.communicate()[0]
        if child.returncode == 0:
            starttime = time.time()
           
            # set up temp dir
            tempdir = False
            if args.wd:
                tempdir = args.wd
                if not os.path.exists(tempdir):
                    os.makedirs(tempdir)
            else:
                tempdir = tempfile.mkdtemp()
                tempdir = os.path.join(tempdir, "mkvdts2ac3")
               
            (dirName, fileName) = os.path.split(ford)
            fileBaseName = os.path.splitext(fileName)[0]
           
            doprint("filename: " + fileName + "\n", 1)
           
            dtsfile = fileBaseName + '.dts'
            tempdtsfile = os.path.join(tempdir, dtsfile)
            ac3file = fileBaseName + '.ac3'
            tempac3file = os.path.join(tempdir, ac3file)
            aacfile = fileBaseName + '.aac'
            tempaacfile = os.path.join(tempdir, aacfile)
            tcfile = fileBaseName + '.tc'
            temptcfile = os.path.join(tempdir, tcfile)
            newmkvfile = fileBaseName + '.mkv'
            tempnewmkvfile = os.path.join(tempdir, newmkvfile)
            adjacentmkvfile = os.path.join(dirName, fileBaseName + '.new.mkv')
            mp4file = os.path.join(dirName, fileBaseName + '.mp4')
            fname = fileName
           
            # get dts track id and video track id
            output = subprocess.check_output([mkvmerge, "-i", ford])
            lines = output.split("\n")
            altdtstrackid = False
            dtstrackid = False
            videotrackid = False
            alreadygotac3 = False
            audiotracks = []
            for line in lines:
                linelist = line.split(' ')
                trackid = False
                if len(linelist) > 2:
                    trackid = linelist[2]
                    linelist = trackid.split(':')
                    trackid = linelist[0]
                if 'audio (A_' in line:
                    audiotracks.append(trackid)
                if ': audio (A_DTS)' in line:
                    dtstrackid = trackid
                elif 'video (V_' in line:
                    videotrackid = trackid
                elif ': audio (A_AC3)' in line:
                    alreadygotac3 = True
                if args.track:
                    if "Track ID " + args.track + ": audio (A_DTS)" in line:
                        altdtstrackid = args.track
            if altdtstrackid:
                dtstrackid = altdtstrackid
           
            if not dtstrackid:
                doprint("  No DTS track found\n", 1)
            elif alreadygotac3 and not args.force:
                doprint("  Already has AC3 track\n", 1)
            else:
                # get dtstrack info
                output = subprocess.check_output([mkvinfo, ford])
                lines = output.split("\n")
                dtstrackinfo = []
                startcount = 0
                for line in lines:
                    match = re.search(r'^\|( *)\+', line)
                    linespaces = startcount
                    if match:
                        linespaces = len(match.group(1))
                    if startcount == 0:
                        if "track ID for mkvmerge & mkvextract:" in line:
                            if "track ID for mkvmerge & mkvextract: " + dtstrackid in line:
                                startcount = linespaces
                        elif "+ Track number: " + dtstrackid in line:
                            startcount = linespaces
                    if linespaces < startcount:
                        break
                    if startcount != 0:
                        dtstrackinfo.append(line)
               
                # get dts language
                dtslang = "eng"
                for line in dtstrackinfo:
                    if "Language" in line:
                        dtslang = line.split()[-1]
               
                # get ac3 track name
                ac3name = False
                if args.custom:
                    ac3name = args.custom
                else:
                    for line in dtstrackinfo:
                        if "+ Name: " in line:
                            ac3name = line.split("+ Name: ")[-1]
                            ac3name = ac3name.replace("DTS", "AC3")
                            ac3name = ac3name.replace("dts", "ac3")
                            if args.stereo:
                                ac3name = ac3name.replace("5.1", "Stereo")
               
                # get aac track name
                aacname = False
                if args.aaccustom:
                    aacname = args.aaccustom
                else:
                    for line in dtstrackinfo:
                        if "+ Name: " in line:
                            aacname = line.split("+ Name: ")[-1]
                            aacname = aacname.replace("DTS", "AAC")
                            aacname = aacname.replace("dts", "aac")
                            if args.aacstereo:
                                aacname = aacname.replace("5.1", "Stereo")
               
                totaljobs = 4
                jobnum = 1
                if args.aac:
                    totaljobs += 1
                if args.mp4:
                    totaljobs += 1
               
                # extract timecodes
                tctitle = "  Extracting Timecodes  [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                jobnum += 1
                tccmd = [mkvextract, "timecodes_v2", ford, dtstrackid + ":" + temptcfile]
                runcommand(tctitle, tccmd)
               
                delay = False
                if not args.test:
                    # get the delay if there is any
                    fp = open(temptcfile)
                    for i, line in enumerate(fp):
                        if i == 1:
                            delay = line
                            break
                    fp.close()
               
                # extract dts track
                extracttitle = "  Extracting DTS track  [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                jobnum += 1
                extractcmd = [mkvextract, "tracks", ford, dtstrackid + ':' + tempdtsfile]
                runcommand(extracttitle, extractcmd)
               
                # convert DTS to AC3
                converttitle = "  Converting DTS to AC3 [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                jobnum += 1
                audiochannels = 6
                if args.stereo:
                    audiochannels = 2
                convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "ac3", "-ac", str(audiochannels), "-ab", "448k", tempac3file]
                runcommand(converttitle, convertcmd)
               
                if args.aac:
                    converttitle = "  Converting DTS to AAC [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                    jobnum += 1
                    audiochannels = 6
                    if args.aacstereo:
                        audiochannels = 2
                    convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "libfaac", "-ac", str(audiochannels), "-ab", "448k", tempaacfile]
                    runcommand(converttitle, convertcmd)
                    if not os.path.isfile(tempaacfile) or os.path.getsize(tempaacfile) == 0:
                        convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "libvo_aacenc", "-ac", str(audiochannels), "-ab", "448k", tempaacfile]
                        runcommand(converttitle, convertcmd)
                    if not os.path.isfile(tempaacfile) or os.path.getsize(tempaacfile) == 0:
                        convertcmd = [ffmpeg, "-y", "-i", tempdtsfile, "-acodec", "aac", "-strict", "experimental", "-ac", str(audiochannels), "-ab", "448k", tempaacfile]
                        runcommand(converttitle, convertcmd)
                    if not os.path.isfile(tempaacfile) or os.path.getsize(tempaacfile) == 0:
                        args.aac = False
                        print "ERROR: ffmpeg can't use any aac codecs. Please try to get libfaac, libvo_aacenc, or a newer version of ffmpeg with the experimental aac codec installed"
                       
                if args.external:
                    if not args.test:
                        shutil.move(tempac3file, os.path.join(dirName, fileBaseName + '.ac3'))
                        fname = ac3file
                else:
                    # remux
                    remuxtitle = "  Remuxing AC3 into MKV [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                    jobnum += 1
                    # Start to "build" command
                    remux = [mkvmerge]
                   
                    # Remove subtitles
                    if args.no_subtitles:
                        remux.append("--no-subtitles")
                   
                    # Puts the AC3 track as the second in the file if indicated as initial
                    if args.initial:
                        remux.append("--track-order")
                        if args.aac:
                            remux.append("1:0,2:0")
                        else:
                            remux.append("1:0")

                    # If user doesn't want the original DTS track drop it
                    comp = args.compress
                    if args.nodts or args.keepdts:
                        if len(audiotracks) == 1:
                            remux.append("-A")
                        else:
                            audiotracks = [audiotrack for audiotrack in audiotracks if audiotrack != dtstrackid]
                            remux.append("-a")
                            remux.append(",".join(audiotracks))
                            for tid in audiotracks:
                                remux.append("--compression")
                                remux.append(tid + ":" + comp)
                   
                    # Add original MKV file, set header compression scheme         
                    remux.append("--compression")
                    remux.append(videotrackid + ":" + comp)
                    remux.append(ford)
                   
                    # If user wants new AC3 as default then add appropriate arguments to command
                    if args.default:
                        remux.append("--default-track")
                        remux.append("0:0")
                   
                    # Set the language
                    remux.append("--language")
                    remux.append("0:" + dtslang)
                   
                    # If the name was set for the original DTS track set it for the AC3
                    if ac3name:
                        remux.append("--track-name")
                        remux.append("0:\"" + ac3name.rstrip() + "\"")
                   
                    # set delay if there is any
                    if delay:
                        remux.append("--sync")
                        remux.append("0:" + delay.rstrip())
                       
                    # Set track compression scheme and append new AC3
                    remux.append("--compression")
                    remux.append("0:" + comp)
                    remux.append(tempac3file)
                   
                    if args.aac:
                        # If the name was set for the original DTS track set it for the AAC
                        if aacname:
                            remux.append("--track-name")
                            remux.append("0:\"" + aacname.rstrip() + "\"")
                           
                        # Set track compression scheme and append new AAC
                        remux.append("--compression")
                        remux.append("0:" + comp)
                        remux.append(tempaacfile)
                   
                    # Declare output file
                    remux.append("-o")
                    remux.append(tempnewmkvfile)
                   
                    runcommand(remuxtitle, remux) 

                    if not args.test:
                        if args.mp4:
                            converttitle = "  Converting MKV to MP4 [" + str(jobnum) + "/" + str(totaljobs) + "]..."
                            convertcmd = [ffmpeg, "-i", tempnewmkvfile, "-map", "0", "-vcodec", "copy", "-acodec", "copy", "-c:s", "mov_text", mp4file]
                            runcommand(converttitle, convertcmd)
                            silentremove(ford)
                        else:
                            #~ replace old mkv with new mkv
                            if args.new:
                                shutil.move(tempnewmkvfile, adjacentmkvfile)
                            else:
                                silentremove(ford)
                                shutil.move(tempnewmkvfile, ford)

                if not args.test:
                    #~ clean up temp folder
                    if args.keepdts and not args.external:
                        shutil.move(tempdtsfile, os.path.join(dirName, fileBaseName + ".dts"))
                        fname = dtsfile
                    else:
                        silentremove(tempdtsfile)
                    if not args.external:
                        silentremove(tempac3file)
                        silentremove(tempaacfile)
                        silentremove(temptcfile)
                    if not os.listdir(tempdir):
                        os.rmdir(tempdir)

                #~ print out time taken
                elapsed = (time.time() - starttime)
                minutes = int(elapsed / 60)
                seconds = int(elapsed) % 60
                doprint("  " + fileName + " finished in: " + str(minutes) + " minutes " + str(seconds) + " seconds\n", 1)

            return fname

totalstime = time.time()
for a in args.fileordir:
    for ford in glob.glob(a):
        fname = False
        if os.path.isdir(ford):
            for f in os.listdir(ford):
                process(os.path.join(ford, f))
        else:
            fname = process(ford)
        destdir = False
        if args.destdir:
            destdir = args.destdir
        if sab and args.sabdestdir:
            destdir = args.sabdestdir
        if destdir:
            if fname:
                (dirName, fileName) = os.path.split(ford)
                destfile = os.path.join(destdir, fname)
                origfile = os.path.join(dirName, fname)
                if args.md5 and (find_mount_point(dirName) != find_mount_point(destdir)):
                    if os.path.exists(destfile):
                        if args.overwrite:
                            silentremove(destfile)
                            shutil.copyfile(origfile, destfile)
                            if getmd5(origfile) == getmd5(destfile):
                                silentremove(origfile)
                            else:
                                print "MD5's don't match."
                        else:
                            print "File " + destfile + " already exists"
                    else:
                        doprint("copying: " + origfile + " --> " + destfile + "\n", 3)
                        shutil.copyfile(origfile, destfile)
                        if getmd5(origfile) == getmd5(destfile):
                            silentremove(origfile)
                        else:
                            print "MD5's don't match."
                else: 
                    if os.path.exists(destfile):
                        if args.overwrite:
                            silentremove(destfile)
                            shutil.move(origfile, destfile)
                        else:
                            print "File " + destfile + " already exists"
                    else:
                        shutil.move(origfile, destfile)
            else:
                origpath = os.path.abspath(ford)
                destpath = os.path.join(destdir, os.path.basename(os.path.normpath(ford)))
                if args.md5 and (find_mount_point(origpath) != find_mount_point(destpath)):
                    if os.path.exists(destpath) and args.overwrite:
                        shutil.rmtree(destpath)
                    elif os.path.exists(destpath):   
                        print "Directory " + destpath + " already exists"
                    else:
                        shutil.copytree(origpath, destpath)
                        if check_md5tree(origpath, destpath):
                            shutil.rmtree(origpath)
                        else:
                            print "MD5's don't match."
                else:
                    shutil.move(origpath, destpath)
                   
if sab:
    sys.stdout.write("mkv dts -> ac3 conversion: " + elapsedstr(totalstime))
else:
    doprint("Total Time: " + elapsedstr(totalstime), 1)

clintonhall
Posts: 449
Joined: 15 Dec 2012, 01:52
Location: Australia
Contact:

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by clintonhall » 04 Dec 2013, 20:02

if there are other args that don't exist, we can add them and then set those to be configurable via NZBGet web UI

jackiass2
Posts: 42
Joined: 19 Nov 2013, 12:07

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by jackiass2 » 04 Dec 2013, 21:43

I tried adding args.md5 = True

Code: Select all

error	Wed Dec 04 2013 22:24:55	Post-process-script mkvdts2ac3/mkvdts2ac3-2.py for dts sample failed (terminated with unknown status)
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: mkv dts -> ac3 conversion: 0 minutes 0 seconds
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Directory /mnt/disk1/share/_Complete/test/ already exists
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /sbin
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /dev
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /root
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /boot
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /bin
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /www
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /etc
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /proc
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /var
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /lost+found
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /.gphoto
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /lib
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /sys
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /tmp2
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /mnt
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /initrd
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /usr
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /tmp
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /home
info	Wed Dec 04 2013 22:24:55	mkvdts2ac3-2: Processing dir: /opt
info	Wed Dec 04 2013 22:24:51	Executing post-process-script mkvdts2ac3/mkvdts2ac3-2.py for dts sample
It told me that /mnt/disk1/share/_Complete/test/ already existed and then stopped. I tried setting nzbgetdestdir to /mnt/disk1/share/_Complete/test/ (after deleting said folder) and it started working. It did not tell me what it was doing, but I could see that it was filling up the test folder with my /opt/ folder. Basically just copying everything from /opt over to mnt/disk1/share/_Complete/test - I killed the operation after 15 minutes. I don't know what it would have accomplished, but I know it was not what it was supposed to do.

Looking at the behavior it seems to me it just goes through the whole hard drive (starting with /opt). I have no clue why it starts copying everything over.

clintonhall
Posts: 449
Joined: 15 Dec 2012, 01:52
Location: Australia
Contact:

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by clintonhall » 05 Dec 2013, 12:04

Ah...
Replace

Code: Select all

args.fileordir = os.environ['NZBPP_DIRECTORY']
With

Code: Select all

args.fileordir = [os.environ['NZBPP_DIRECTORY']]
The issue is later we set args.fileordir = args.fileordir[0]....
So, if the directory is /mnt/share... With the extra [], this means we are actually looking at the passed directory... Without it, args.fileordir[0] is just "/" and so we start parsing the entire / directory.... This is BAD :?

So, after making this small (but important change) hopefully we will be getting close...

jackiass2
Posts: 42
Joined: 19 Nov 2013, 12:07

Re: [PP-Script] mkvdts2ac3 - how to make this nzbget script?

Post by jackiass2 » 05 Dec 2013, 18:52

Aha! At least it is trying to work on the right directory now :)

More fun with args ahead:

Code: Select all

error	Thu Dec 05 2013 19:47:07	Post-process-script mkvdts2ac3/mkvdts2ac3-2.py for dts sample failed (terminated with unknown status)
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: AttributeError: 'Namespace' object has no attribute 'stereo'
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: if args.stereo:
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: File "/mnt/disk1/share/nzbget/ppscripts/mkvdts2ac3/mkvdts2ac3-2.py", line 641, in process
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: process(os.path.join(ford, f))
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: File "/mnt/disk1/share/nzbget/ppscripts/mkvdts2ac3/mkvdts2ac3-2.py", line 837, in <module>
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: Traceback (most recent call last):
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: filename: Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: Processing file: /mnt/disk1/share/_Complete/dts sample/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv
info	Thu Dec 05 2013 19:47:07	mkvdts2ac3-2: Processing file: /mnt/disk1/share/_Complete/dts sample/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.par2
info	Thu Dec 05 2013 19:47:02	Executing post-process-script mkvdts2ac3/mkvdts2ac3-2.py for dts sample
EDIT:
Tried thinking myself and added args.stereo = True
We are getting close. Now this happens:

Code: Select all

error	Thu Dec 05 2013 20:24:05	Post-process-script mkvdts2ac3/mkvdts2ac3-2.py for Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample failed (terminated with unknown status)
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: IOError: [Errno 2] No such file or directory: '/mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv'
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: with open(src, 'rb') as fsrc:
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: File "/opt/lib/python2.7/shutil.py", line 82, in copyfile
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: copyfile(src, dst)
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: File "/opt/lib/python2.7/shutil.py", line 128, in copy2
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: copy2(src, real_dst)
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: File "/opt/lib/python2.7/shutil.py", line 299, in move
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: shutil.move(tempnewmkvfile, ford)
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: File "/mnt/disk1/share/nzbget/ppscripts/mkvdts2ac3/mkvdts2ac3-2.py", line 808, in process
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: process(os.path.join(ford, f))
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: File "/mnt/disk1/share/nzbget/ppscripts/mkvdts2ac3/mkvdts2ac3-2.py", line 838, in <module>
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Traceback (most recent call last):
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: sample.mkv
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: /mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: sample.ac3 -o
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: /mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: --compression 0:
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: 0:"Antiviral.2012.BluRay.720p.AC3.x264-CHD" --sync 0:6
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: --language 0:eng --track-name
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: -CHD-sample/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: /mnt/disk1/share/_Complete/Antiviral.2012.BluRay.720p.DTS.x264
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: mkvmerge --compression 1:
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Running command:
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Remuxing AC3 into MKV [4/4]...
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: sample.ac3
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: /mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: sample.dts -acodec ac3 -ac 2 -ab 448k
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: /mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: ffmpeg -y -i
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Running command:
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Converting DTS to AC3 [3/4]...
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: sample.dts
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: 2:/mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: -CHD-sample/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: /mnt/disk1/share/_Complete/Antiviral.2012.BluRay.720p.DTS.x264
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: mkvextract tracks
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Running command:
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Extracting DTS track [2/4]...
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: sample.tc
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: 2:/mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: -CHD-sample/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: /mnt/disk1/share/_Complete/Antiviral.2012.BluRay.720p.DTS.x264
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: mkvextract timecodes_v2
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Running command:
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Extracting Timecodes [1/4]...
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: filename: Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Processing file: /mnt/disk1/share/_Complete/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.mkv
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Processing file: /mnt/disk1/share/_Complete/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.par2
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: Error: Invalid compression option. No track ID specified in '--compression 1:'.
info	Thu Dec 05 2013 20:24:04	mkvdts2ac3-2: mkvmerge v4.2.0 ('No Talking') built on Feb 14 2012 14:16:48
info	Thu Dec 05 2013 20:24:01	mkvdts2ac3-2: video:0kB audio:2749kB global headers:0kB muxing overhead 0.000000%
info	Thu Dec 05 2013 20:24:01	mkvdts2ac3-2: bitrate= 448.1kbits/s size= 2352kB time=00:00:43.00 bitrate= 448.1kbits/s size= 2364kB time=00:00:43.22 bitrate= 448.1kbits/s size= 2376kB time=00:00:43.45 bitrate= 448.1kbits/s size= 2390kB time=00:00:43.70 bitrate= 448.1kbits/s size= 2404kB time=00:00:43.96 bitrate= 448.1kbits/s size= 2420kB time=00:00:44.25 bitrate= 448.1kbits/s size= 2432kB time=00:00:44.47 bitrate= 448.1kbits/s size= 2448kB time=00:00:44.76 bitrate= 448.1kbits/s size= 2464kB time=00:00:45.05 bitrate= 448.1kbits/s size= 2478kB time=00:00:45.30 bitrate= 448.1kbits/s size= 2492kB time=00:00:45.56 bitrate= 448.1kbits/s size= 2506kB time=00:00:45.81 bitrate= 448.1kbits/s size= 2516kB time=00:00:46.01 bitrate= 448.1kbits/s size= 2529kB time=00:00:46.23 bitrate= 448.1kbits/s size= 2539kB time=00:00:46.42 bitrate= 448.1kbits/s size= 2552kB time=00:00:46.65 bitrate= 448.1kbits/s size= 2564kB time=00:00:46.87 bitra
info	Thu Dec 05 2013 20:23:45	mkvdts2ac3-2: size= 7kB time=00:00:00.12 bitrate= 467.5kbits/s size= 21kB time=00:00:00.37 bitrate= 454.3kbits/s size= 35kB time=00:00:00.63 bitrate= 451.8kbits/s size= 49kB time=00:00:00.89 bitrate= 450.7kbits/s size= 63kB time=00:00:01.14 bitrate= 450.1kbits/s size= 75kB time=00:00:01.37 bitrate= 449.7kbits/s size= 86kB time=00:00:01.56 bitrate= 449.5kbits/s size= 100kB time=00:00:01.81 bitrate= 449.3kbits/s size= 114kB time=00:00:02.07 bitrate= 449.2kbits/s size= 128kB time=00:00:02.33 bitrate= 449.0kbits/s size= 142kB time=00:00:02.58 bitrate= 448.9kbits/s size= 156kB time=00:00:02.84 bitrate= 448.8kbits/s size= 168kB time=00:00:03.06 bitrate= 448.8kbits/s size= 177kB time=00:00:03.22 bitrate= 448.7kbits/s size= 191kB time=00:00:03.48 bitrate= 448.7kbits/s size= 205kB time=00:00:03.73 bitrate= 448.6kbits/s size= 219kB time=00:00:03.99 bitrate= 448.6kbits/s size=
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Press [q] to stop, [?] for help
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Stream #0:0 -> #0:0 (dca -> ac3)
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Stream mapping:
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Stream #0:0: Audio: ac3, 48000 Hz, stereo, flt, 448 kb/s
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: encoder : Lavf54.6.100
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Metadata:
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Output #0, ac3, to '/mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.ac3':
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: [aresample @ 0x100b610] chl:5.1(side) fmt:s16 r:48000Hz -> chl:stereo fmt:flt r:48000Hz
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: [aformat @ 0x1020b50] auto-inserting filter 'auto-inserted resampler 0' between the filter 'src' and the filter 'aformat'
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Stream #0:0: Audio: dts (DTS), 48000 Hz, 5.1(side), s16, 1536 kb/s
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Duration: 00:00:49.37, start: 0.000000, bitrate: 1536 kb/s
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: Input #0, dts, from '/mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.dts':
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: [dts @ 0xff83c0] Estimating duration from bitrate, this may be inaccurate
info	Thu Dec 05 2013 20:22:15	mkvdts2ac3-2: [dts @ 0xff83c0] max_analyze_duration 5000000 reached at 5002667
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libpostproc 52. 0.100 / 52. 0.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libswresample 0. 15.100 / 0. 15.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libswscale 2. 1.100 / 2. 1.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libavfilter 2. 77.100 / 2. 77.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libavdevice 54. 0.100 / 54. 0.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libavformat 54. 6.100 / 54. 6.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libavcodec 54. 23.100 / 54. 23.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: libavutil 51. 54.100 / 51. 54.100
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: configuration: --prefix=/opt --extra-cflags=-I/opt/include --extra-ldflags=-L/opt/lib --enable-static --disable-shared --enable-libmp3lame --enable-libx264 --enable-gpl --enable-pthreads --disable-ffplay --disable-ffserver
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: built on Jul 23 2012 18:47:09 with gcc 4.2.3
info	Thu Dec 05 2013 20:22:13	mkvdts2ac3-2: ffmpeg version 0.11.1 Copyright (c) 2000-2012 the FFmpeg developers
info	Thu Dec 05 2013 20:22:11	mkvdts2ac3-2: Progress: 3% Progress: 6% Progress: 9% Progress: 12% Progress: 15% Progress: 19% Progress: 22% Progress: 25% Progress: 28% Progress: 32% Progress: 35% Progress: 39% Progress: 42% Progress: 46% Progress: 49% Progress: 50% Progress: 54% Progress: 57% Progress: 61% Progress: 64% Progress: 68% Progress: 68% Progress: 72% Progress: 75% Progress: 79% Progress: 82% Progress: 85% Progress: 88% Progress: 92% Progress: 95% Progress: 99% Progress: 99% Progress: 100%
info	Thu Dec 05 2013 20:22:08	mkvdts2ac3-2: Extracting track 2 with the CodecID 'A_DTS' to the file '/mnt/disk1/share/test/Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample.dts'. Container format: Digital Theater System (DTS)
info	Thu Dec 05 2013 20:22:08	mkvdts2ac3-2: Progress: 0% Progress: 3% Progress: 6% Progress: 9% Progress: 12% Progress: 15% Progress: 19% Progress: 22% Progress: 25% Progress: 28% Progress: 32% Progress: 35% Progress: 39% Progress: 42% Progress: 46% Progress: 49% Progress: 50% Progress: 54% Progress: 57% Progress: 61% Progress: 64% Progress: 68% Progress: 68% Progress: 72% Progress: 75% Progress: 79% Progress: 82% Progress: 85% Progress: 88% Progress: 92% Progress: 95% Progress: 99% Progress: 100%
info	Thu Dec 05 2013 20:22:00	Executing post-process-script mkvdts2ac3/mkvdts2ac3-2.py for Antiviral.2012.BluRay.720p.DTS.x264-CHD-sample
It extracts the DTS, converts it to AC3 and when it has to replace the DTS with AC3 in the MKV, it ends up deleting the MKV and giving the error you see here above.

Post Reply

Who is online

Users browsing this forum: No registered users and 37 guests