예제 #1
0
    def run_shell_exec(self, cmd, track=True):
        """
        Run the shell exec command.

        @param cmd String Command to be run
        @return int, string
        """
        cmd = 'ulimit -f ' + escape_shellarg(background_size_limit) + ';' + \
            'ulimit -v ' + escape_shellarg(background_memory_limit) + ';' + \
            'ulimit -t ' + escape_shellarg(background_time_limit) + ';' + \
            'ulimit -a;' + \
            'nice -n ' + escape_shellarg(background_priority) + ' ' + cmd + \
            ' 2>&1'

        # Adapted from https://gist.github.com/marazmiki/3015621
        process = subprocess.Popen(cmd,
                                   stdin=None,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT,
                                   universal_newlines=True,
                                   shell=True)

        re_duration = re.compile(r'Duration: (\d{2}:\d{2}:\d{2})')
        re_position = re.compile(r'time=(\d{2}:\d{2}:\d{2})', re.I)

        duration = None
        position = None
        newpercentage = percentage = -1

        while process.poll() is None:
            # for line in process.stdout.readlines():
            # http://bugs.python.org/issue3907
            while True:
                line = process.stdout.readline()
                if not line:
                    break
                print line,

                if track:
                    if duration is None:
                        duration_match = re_duration.search(line)
                        if duration_match:
                            duration = time_to_seconds(duration_match.group(1))
                    else:
                        position_match = re_position.search(line)
                        if position_match:
                            position = time_to_seconds(position_match.group(1))
                            if duration and position:
                                newpercentage = min(
                                    int(math.floor(100 * position / duration)),
                                    100)

                    if newpercentage != percentage:
                        percentage = newpercentage
                        self.statuscallback(None, percentage)

            time.sleep(2)

        return process.returncode, ''
예제 #2
0
    def run_shell_exec(self, cmd, track=True):
        """
        Run the shell exec command.

        @param cmd String Command to be run
        @return int, string
        """
        cmd = 'ulimit -f ' + escape_shellarg(background_size_limit) + ';' + \
            'ulimit -v ' + escape_shellarg(background_memory_limit) + ';' + \
            'ulimit -t ' + escape_shellarg(background_time_limit) + ';' + \
            'ulimit -a;' + \
            'nice -n ' + escape_shellarg(background_priority) + ' ' + cmd + \
            ' 2>&1'

        # Adapted from https://gist.github.com/marazmiki/3015621
        process = subprocess.Popen(
            cmd, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
            universal_newlines=True, shell=True
        )

        re_duration = re.compile(r'Duration: (\d{2}:\d{2}:\d{2})')
        re_position = re.compile(r'time=(\d{2}:\d{2}:\d{2})', re.I)

        duration = None
        position = None
        newpercentage = percentage = -1

        while process.poll() is None:
            # for line in process.stdout.readlines():
            # http://bugs.python.org/issue3907
            while True:
                line = process.stdout.readline()
                if not line:
                    break
                print line,

                if track:
                    if duration is None:
                        duration_match = re_duration.search(line)
                        if duration_match:
                            duration = time_to_seconds(duration_match.group(1))
                    else:
                        position_match = re_position.search(line)
                        if position_match:
                            position = time_to_seconds(position_match.group(1))
                            if duration and position:
                                newpercentage = min(int(
                                    math.floor(100 * position / duration)
                                ), 100)

                    if newpercentage != percentage:
                        percentage = newpercentage
                        self.statuscallback(None, percentage)

            time.sleep(2)

        return process.returncode, ''
예제 #3
0
    def ffmpeg_add_audio_options(self, options, p):
        """
        Add ffmpeg shell options for audio.

        @param options array
        @param p
        @return string
        """
        cmd = ''
        if 'audioQuality' in options:
            cmd += " -aq " + escape_shellarg(options['audioQuality'])

        if 'audioBitrate' in options:
            cmd += ' -ab ' + str(options['audioBitrate']) * 1000

        if 'samplerate' in options:
            cmd += " -ar " + escape_shellarg(options['samplerate'])

        if 'channels' in options:
            cmd += " -ac " + escape_shellarg(options['channels'])

        if 'audioCodec' in options:
            encoders = {
                'vorbis': 'libvorbis',
                'opus': 'libopus',
                'mp3': 'libmp3lame',
            }
            if options['audioCodec'] in encoders:
                codec = encoders[options['audioCodec']]
            else:
                codec = options['audioCodec']

            cmd += " -acodec " + escape_shellarg(codec)
            if codec == 'aac':
                # the aac encoder is currently "experimental" in libav 9? :P
                cmd += ' -strict experimental'
        else:
            # if no audio codec set use vorbis :
            cmd += " -acodec libvorbis "

        return cmd
예제 #4
0
    def ffmpeg_add_theora_video_options(self, options, p):
        """
        Add ffmpeg shell options for ogg.

        Warning: does not create Ogg skeleton metadata track.

        @param options
        @param p
        @return string
        """
        cmd = ' -threads ' + str(ffmpeg_threads)

        # Check for video quality:
        if 'videoQuality' in options and int(options['videoQuality']) >= 0:
            cmd += " -q:v " + escape_shellarg(options['videoQuality'])

        # Check for video bitrate:
        if 'videoBitrate' in options:
            cmd += " -qmin 1 -qmax 51"
            cmd += " -vb " + escape_shellarg(
                int(options['videoBitrate']) * 1000)

        # Set the codec:
        cmd += " -vcodec theora"

        # Check for keyframeInterval
        if 'keyframeInterval' in options:
            cmd += ' -g ' + escape_shellarg(options['keyframeInterval'])
            cmd += ' -keyint_min ' + \
                escape_shellarg(options['keyframeInterval'])

        if 'deinterlace' in options:
            cmd += ' -deinterlace'

        if 'framerate' in options:
            cmd += ' -r ' + escape_shellarg(options['framerate'])

        # Output Ogg
        cmd += " -f ogg"

        return cmd
예제 #5
0
    def ffmpeg_add_audio_options(self, options, p):
        """
        Add ffmpeg shell options for audio.

        @param options array
        @param p
        @return string
        """
        cmd = ''
        if 'audioQuality' in options:
            cmd += " -aq " + escape_shellarg(options['audioQuality'])

        if 'audioBitrate' in options:
            cmd += ' -ab ' + str(options['audioBitrate']) * 1000

        if 'samplerate' in options:
            cmd += " -ar " + escape_shellarg(options['samplerate'])

        if 'channels' in options:
            cmd += " -ac " + escape_shellarg(options['channels'])

        if 'audioCodec' in options:
            encoders = {
                'vorbis': 'libvorbis',
                'opus': 'libopus',
                'mp3': 'libmp3lame',
            }
            if options['audioCodec'] in encoders:
                codec = encoders[options['audioCodec']]
            else:
                codec = options['audioCodec']

            cmd += " -acodec " + escape_shellarg(codec)
            if codec == 'aac':
                # the aac encoder is currently "experimental" in libav 9? :P
                cmd += ' -strict experimental'
        else:
            # if no audio codec set use vorbis :
            cmd += " -acodec libvorbis "

        return cmd
예제 #6
0
    def ffmpeg_add_theora_video_options(self, options, p):
        """
        Add ffmpeg shell options for ogg.

        Warning: does not create Ogg skeleton metadata track.

        @param options
        @param p
        @return string
        """
        cmd = ' -threads ' + str(ffmpeg_threads)

        # Check for video quality:
        if 'videoQuality' in options and options['videoQuality'] >= 0:
            cmd += " -q:v " + escape_shellarg(options['videoQuality'])

        # Check for video bitrate:
        if 'videoBitrate' in options:
            cmd += " -qmin 1 -qmax 51"
            cmd += " -vb " + escape_shellarg(options['videoBitrate'] * 1000)

        # Set the codec:
        cmd += " -vcodec theora"

        # Check for keyframeInterval
        if 'keyframeInterval' in options:
            cmd += ' -g ' + escape_shellarg(options['keyframeInterval'])
            cmd += ' -keyint_min ' + \
                escape_shellarg(options['keyframeInterval'])

        if 'deinterlace' in options:
            cmd += ' -deinterlace'

        if 'framerate' in options:
            cmd += ' -r ' + escape_shellarg(options['framerate'])

        # Output Ogg
        cmd += " -f ogg"

        return cmd
예제 #7
0
    def ffmpeg_add_theora_video_options(self, options, p):
        """
        Add ffmpeg shell options for ogg.

        Warning: does not create Ogg skeleton metadata track.

        @param options
        @param p
        @return string
        """
        cmd = " -threads " + str(ffmpeg_threads)

        # Check for video quality:
        if "videoQuality" in options and options["videoQuality"] >= 0:
            cmd += " -q:v " + escape_shellarg(options["videoQuality"])

        # Check for video bitrate:
        if "videoBitrate" in options:
            cmd += " -qmin 1 -qmax 51"
            cmd += " -vb " + escape_shellarg(options["videoBitrate"] * 1000)

        # Set the codec:
        cmd += " -vcodec theora"

        # Check for keyframeInterval
        if "keyframeInterval" in options:
            cmd += " -g " + escape_shellarg(options["keyframeInterval"])
            cmd += " -keyint_min " + escape_shellarg(options["keyframeInterval"])

        if "deinterlace" in options:
            cmd += " -deinterlace"

        if "framerate" in options:
            cmd += " -r " + escape_shellarg(options["framerate"])

        # Output Ogg
        cmd += " -f ogg"

        return cmd
예제 #8
0
    def ffmpeg_add_audio_options(self, options, p):
        """
        Add ffmpeg shell options for audio.

        @param options array
        @param p
        @return string
        """
        cmd = ""
        if "audioQuality" in options:
            cmd += " -aq " + escape_shellarg(options["audioQuality"])

        if "audioBitrate" in options:
            cmd += " -ab " + str(options["audioBitrate"]) * 1000

        if "samplerate" in options:
            cmd += " -ar " + escape_shellarg(options["samplerate"])

        if "channels" in options:
            cmd += " -ac " + escape_shellarg(options["channels"])

        if "audioCodec" in options:
            encoders = {"vorbis": "libvorbis", "opus": "libopus", "mp3": "libmp3lame"}
            if options["audioCodec"] in encoders:
                codec = encoders[options["audioCodec"]]
            else:
                codec = options["audioCodec"]

            cmd += " -acodec " + escape_shellarg(codec)
            if codec == "aac":
                # the aac encoder is currently "experimental" in libav 9? :P
                cmd += " -strict experimental"
        else:
            # if no audio codec set use vorbis :
            cmd += " -acodec libvorbis "

        return cmd
예제 #9
0
    def ffmpeg_add_webm_video_options(self, options, p):
        """
        Add ffmpeg shell options for webm.

        @param options
        @param p
        @return string
        """
        cmd = ' -threads ' + str(ffmpeg_threads)

        # check for presets:
        if 'preset' in options:
            if options['preset'] == "360p":
                cmd += " -vpre libvpx-360p"
            elif options['preset'] == "720p":
                cmd += " -vpre libvpx-720p"
            elif options['preset'] == "1080p":
                cmd += " -vpre libvpx-1080p"

        # Add the boiler plate vp8 ffmpeg command:
        cmd += " -skip_threshold 0 -bufsize 6000k -rc_init_occupancy 4000"

        # Check for video quality:
        if 'videoQuality' in options and options['videoQuality'] >= 0:
            # Map 0-10 to 63-0, higher values worse quality
            quality = 63 - int(int(options['videoQuality']) / 10.0 * 63)
            cmd += " -qmin " + escape_shellarg(quality)
            cmd += " -qmax " + escape_shellarg(quality)

        # Check for video bitrate:
        if 'videoBitrate' in options:
            cmd += " -qmin 1 -qmax 51"
            cmd += " -vb " + escape_shellarg(options['videoBitrate'] * 1000)

        # Set the codec:
        if options['videoCodec'] == 'vp9':
            cmd += " -vcodec libvpx-vp9"
            if 'tileColumns' in options:
                cmd += ' -tile-columns ' + \
                    escape_shellarg(options['tileColumns'])
        else:
            cmd += " -vcodec libvpx"

        # Check for keyframeInterval
        if 'keyframeInterval' in options:
            cmd += ' -g ' + escape_shellarg(options['keyframeInterval'])
            cmd += ' -keyint_min ' + \
                escape_shellarg(options['keyframeInterval'])

        if 'deinterlace' in options:
            cmd += ' -deinterlace'

        # Output WebM
        cmd += " -f webm"

        return cmd
예제 #10
0
    def ffmpeg_add_webm_video_options(self, options, p):
        """
        Add ffmpeg shell options for webm.

        @param options
        @param p
        @return string
        """
        cmd = ' -threads ' + str(ffmpeg_threads)

        # check for presets:
        if 'preset' in options:
            if options['preset'] == "360p":
                cmd += " -vpre libvpx-360p"
            elif options['preset'] == "720p":
                cmd += " -vpre libvpx-720p"
            elif options['preset'] == "1080p":
                cmd += " -vpre libvpx-1080p"

        # Add the boiler plate vp8 ffmpeg command:
        cmd += " -skip_threshold 0 -bufsize 6000k -rc_init_occupancy 4000"

        # Check for video quality:
        if 'videoQuality' in options and options['videoQuality'] >= 0:
            # Map 0-10 to 63-0, higher values worse quality
            quality = 63 - int(int(options['videoQuality']) / 10.0 * 63)
            cmd += " -qmin " + escape_shellarg(quality)
            cmd += " -qmax " + escape_shellarg(quality)

        # Check for video bitrate:
        if 'videoBitrate' in options:
            cmd += " -qmin 1 -qmax 51"
            cmd += " -vb " + escape_shellarg(options['videoBitrate'] * 1000)

        # Set the codec:
        if options['videoCodec'] == 'vp9':
            cmd += " -vcodec libvpx-vp9"
            if 'tileColumns' in options:
                cmd += ' -tile-columns ' + \
                    escape_shellarg(options['tileColumns'])
        else:
            cmd += " -vcodec libvpx"

        # Check for keyframeInterval
        if 'keyframeInterval' in options:
            cmd += ' -g ' + escape_shellarg(options['keyframeInterval'])
            cmd += ' -keyint_min ' + \
                escape_shellarg(options['keyframeInterval'])

        if 'deinterlace' in options:
            cmd += ' -deinterlace'

        # Output WebM
        cmd += " -f webm"

        return cmd
예제 #11
0
    def ffmpeg_add_h264_video_options(self, options, p):
        """
        Add ffmpeg shell options for h264.

        @param options
        @param p
        @return string
        """
        # Set the codec:
        cmd = " -threads " + str(ffmpeg_threads) + " -vcodec libx264"

        if 'videoBitrate' in options:
            cmd += " -b " + escape_shellarg(options['videoBitrate'])

        # Output mp4
        cmd += " -f mp4"
        return cmd
예제 #12
0
    def ffmpeg_add_h264_video_options(self, options, p):
        """
        Add ffmpeg shell options for h264.

        @param options
        @param p
        @return string
        """
        # Set the codec:
        cmd = " -threads " + str(ffmpeg_threads) + " -vcodec libx264"

        if 'videoBitrate' in options:
            cmd += " -b " + escape_shellarg(options['videoBitrate'])

        # Output mp4
        cmd += " -f mp4"
        return cmd
예제 #13
0
    def ffmpeg_encode(self, options, p=0):
        """
        Utility helper for ffmpeg and ffmpeg2theora mapping.

        @param options array
        @param p int
        @return bool|string
        """
        if not os.path.isfile(self.get_source_path()):
            return "source file is missing, " + self.get_source_path() + \
                ". Encoding failed."

        # Set up the base command
        cmd = escape_shellarg(ffmpeg_location) + ' -y -i ' + \
            escape_shellarg(self.get_source_path())

        if 'vpre' in options:
            cmd += ' -vpre ' + escape_shellarg(options['vpre'])

        if 'novideo' in options:
            cmd += " -vn "
        elif self.preserve['video']:
            cmd += " -vcodec copy"
        elif options['videoCodec'] == 'vp8' or options['videoCodec'] == 'vp9':
            cmd += self.ffmpeg_add_webm_video_options(options, p)
        elif options['videoCodec'] == 'h264':
            cmd += self.ffmpeg_add_h264_video_options(options, p)
        elif options['videoCodec'] == 'theora':
            cmd += self.ffmpeg_add_theora_video_options(options, p)

        # Check for start time
        if 'starttime' in options:
            cmd += ' -ss ' + escape_shellarg(options['starttime'])
        else:
            options['starttime'] = 0

        # Check for end time:
        if 'endtime' in options:
            cmd += ' -t ' + str(options['endtime']) - str(options['starttime'])

        if p == 1 or 'noaudio' in options:
            cmd += ' -an'
        elif self.preserve['audio']:
            cmd += " -acodec copy"
        else:
            cmd += self.ffmpeg_add_audio_options(options, p)

        if p != 0:
            cmd += " -pass " + escape_shellarg(p)
            cmd += " -passlogfile " + \
                escape_shellarg(self.get_target_path() + '.log')

        # And the output target:
        if p == 1:
            cmd += ' /dev/null'
        else:
            cmd += " " + escape_shellarg(self.get_target_path())

        self.output("Running cmd: " + cmd + "\n")

        # Right before we output remove the old file
        retval, shellOutput = self.run_shell_exec(cmd, track=p != 1)

        if int(retval) != 0:
            return cmd + \
                "\nExitcode: " + str(retval)

        return True
예제 #14
0
    def ffmpeg_encode(self, options, p=0):
        """
        Utility helper for ffmpeg and ffmpeg2theora mapping.

        @param options array
        @param p int
        @return bool|string
        """
        if not os.path.isfile(self.get_source_path()):
            return "source file is missing, " + self.get_source_path() + ". Encoding failed."

        # Set up the base command
        cmd = escape_shellarg(ffmpeg_location) + " -y -i " + escape_shellarg(self.get_source_path())

        if "vpre" in options:
            cmd += " -vpre " + escape_shellarg(options["vpre"])

        if "novideo" in options:
            cmd += " -vn "
        elif self.preserve["video"]:
            cmd += " -vcodec copy"
        elif options["videoCodec"] == "vp8" or options["videoCodec"] == "vp9":
            cmd += self.ffmpeg_add_webm_video_options(options, p)
        elif options["videoCodec"] == "h264":
            cmd += self.ffmpeg_add_h264_video_options(options, p)
        elif options["videoCodec"] == "theora":
            cmd += self.ffmpeg_add_theora_video_options(options, p)

        # Check for start time
        if "starttime" in options:
            cmd += " -ss " + escape_shellarg(options["starttime"])
        else:
            options["starttime"] = 0

        # Check for end time:
        if "endtime" in options:
            cmd += " -t " + str(options["endtime"]) - str(options["starttime"])

        if p == 1 or "noaudio" in options:
            cmd += " -an"
        elif self.preserve["audio"]:
            cmd += " -acodec copy"
        else:
            cmd += self.ffmpeg_add_audio_options(options, p)

        if p != 0:
            cmd += " -pass " + escape_shellarg(p)
            cmd += " -passlogfile " + escape_shellarg(self.get_target_path() + ".log")

        # And the output target:
        if p == 1:
            cmd += " /dev/null"
        else:
            cmd += " " + escape_shellarg(self.get_target_path())

        self.output("Running cmd: " + cmd + "\n")

        # Right before we output remove the old file
        retval, shellOutput = self.run_shell_exec(cmd, track=p != 1)

        if int(retval) != 0:
            return cmd + "\nExitcode: " + str(retval)

        return True
예제 #15
0
    def ffmpeg_encode(self, options, p=0):
        """
        Utility helper for ffmpeg and ffmpeg2theora mapping.

        @param options array
        @param p int
        @return bool|string
        """
        if not os.path.isfile(self.get_source_path()):
            return "source file is missing, " + self.get_source_path() + \
                ". Encoding failed."

        # Set up the base command
        cmd = escape_shellarg(ffmpeg_location) + ' -y -i ' + \
            escape_shellarg(self.get_source_path())

        if 'vpre' in options:
            cmd += ' -vpre ' + escape_shellarg(options['vpre'])

        if 'novideo' in options:
            cmd += " -vn "
        elif self.preserve['video']:
            cmd += " -vcodec copy"
        elif options['videoCodec'] == 'vp8' or options['videoCodec'] == 'vp9':
            cmd += self.ffmpeg_add_webm_video_options(options, p)
        elif options['videoCodec'] == 'h264':
            cmd += self.ffmpeg_add_h264_video_options(options, p)
        elif options['videoCodec'] == 'theora':
            cmd += self.ffmpeg_add_theora_video_options(options, p)

        # Check for start time
        if 'starttime' in options:
            cmd += ' -ss ' + escape_shellarg(options['starttime'])
        else:
            options['starttime'] = 0

        # Check for end time:
        if 'endtime' in options:
            cmd += ' -t ' + str(options['endtime']) - str(options['starttime'])

        if p == 1 or 'noaudio' in options:
            cmd += ' -an'
        elif self.preserve['audio']:
            cmd += " -acodec copy"
        else:
            cmd += self.ffmpeg_add_audio_options(options, p)

        if p != 0:
            cmd += " -pass " + escape_shellarg(p)
            cmd += " -passlogfile " + \
                escape_shellarg(self.get_target_path() + '.log')

        # And the output target:
        if p == 1:
            cmd += ' /dev/null'
        else:
            cmd += " " + escape_shellarg(self.get_target_path())

        self.output("Running cmd: " + cmd + "\n")

        # Right before we output remove the old file
        retval, shellOutput = self.run_shell_exec(cmd, track=p != 1)

        if int(retval) != 0:
            return cmd + \
                "\nExitcode: " + str(retval)

        return True
예제 #16
0
    def ffmpeg_add_webm_video_options(self, options, p):
        """
        Add ffmpeg shell options for webm.

        @param options
        @param p
        @return string
        """
        cmd = ' -threads ' + str(ffmpeg_threads)
        if options['videoCodec'] == 'vp9':
            cmd += ' -row-mt 1'

        # check for presets:
        if 'preset' in options:
            if options['preset'] == "360p":
                cmd += " -vpre libvpx-360p"
            elif options['preset'] == "720p":
                cmd += " -vpre libvpx-720p"
            elif options['preset'] == "1080p":
                cmd += " -vpre libvpx-1080p"

        # Check for video quality:
        if 'videoQuality' in options and int(options['videoQuality']) >= 0:
            # Map 0-10 to 63-0, higher values worse quality
            quality = 63 - int(int(options['videoQuality']) / 10.0 * 63)
            cmd += " -qmin " + escape_shellarg(quality)
            cmd += " -qmax " + escape_shellarg(quality)

        # Check for video bitrate:
        if 'videoBitrate' in options:
            cmd += " -qmin 1 -qmax 51"
            cmd += " -vb " + escape_shellarg(int(options['videoBitrate']) * 1000)

        # Set the codec:
        if options['videoCodec'] == 'vp9':
            cmd += " -vcodec libvpx-vp9"
            if 'tileColumns' in options:
                cmd += ' -tile-columns ' + \
                    escape_shellarg(options['tileColumns'])
        else:
            cmd += " -vcodec libvpx"

        if 'altref' in options:
            cmd += ' -auto-alt-ref 1'
            cmd += ' -lag-in-frames 25'

        # Check for keyframeInterval
        if 'keyframeInterval' in options:
            cmd += ' -g ' + escape_shellarg(options['keyframeInterval'])
            cmd += ' -keyint_min ' + \
                escape_shellarg(options['keyframeInterval'])

        if 'deinterlace' in options:
            cmd += ' -deinterlace'

        if p == 1:
            # Make first pass faster...
            cmd += ' -speed 4'
        elif 'speed' in options:
            cmd += ' -speed ' + escape_shellarg(options['speed'])

        # Output WebM
        cmd += " -f webm"

        return cmd
예제 #17
0
    def run_shell_exec(self, cmd, track=True):
        """
        Run the shell exec command.

        @param cmd String Command to be run
        @return int, string
        """
        cmd = (
            "ulimit -f "
            + escape_shellarg(background_size_limit)
            + ";"
            + "ulimit -v "
            + escape_shellarg(background_memory_limit)
            + ";"
            + "ulimit -t "
            + escape_shellarg(background_time_limit)
            + ";"
            + "ulimit -a;"
            + "nice -n "
            + escape_shellarg(background_priority)
            + " "
            + cmd
            + " 2>&1"
        )

        # Adapted from https://gist.github.com/marazmiki/3015621
        process = subprocess.Popen(
            cmd,
            stdin=None,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True,
            shell=True,
            preexec_fn=os.setsid,
        )

        re_duration = re.compile(r"Duration: (\d{2}:\d{2}:\d{2})")
        re_position = re.compile(r"time=(\d{2}:\d{2}:\d{2})", re.I)

        duration = None
        position = None
        newpercentage = percentage = -1

        while process.poll() is None:
            # for line in process.stdout.readlines():
            # http://bugs.python.org/issue3907
            while True:
                line = process.stdout.readline()
                if not line:
                    break
                print line,

                if track:
                    if duration is None:
                        duration_match = re_duration.search(line)
                        if duration_match:
                            duration = time_to_seconds(duration_match.group(1))
                    else:
                        position_match = re_position.search(line)
                        if position_match:
                            position = time_to_seconds(position_match.group(1))
                            if duration and position:
                                newpercentage = min(int(math.floor(100 * position / duration)), 100)

                    if newpercentage != percentage:
                        percentage = newpercentage
                        try:
                            self.statuscallback(None, percentage)
                        except TaskAbort:
                            os.killpg(os.getpgid(process.pid), signal.SIGTERM)
                            raise

            time.sleep(2)

        return process.returncode, ""