[FFmpeg-user] How to determine progression

Tom Evans tevans.uk at googlemail.com
Tue May 21 18:07:02 CEST 2013


On Tue, May 21, 2013 at 11:00 AM, Molly Millions
<mollyrazormillions at gmail.com> wrote:
> Well, redirect the output to a file:
>
> ffmpeg -i whatever.mp4 ....... output.mp4 >>
> '/var/tmp/convert/CONVERTID.log' 2>&1
>
> And whenever you need to get the progress, just read the contents of
> /var/tmp/convert/CONVERTID.log.
>
> Getting the progress is done by parsing the Duration: at the very beginning.
>
> Duration: ***00:00:14.67***, start: 0.000000, bitrate: 989 kb/s
>
> Get the fps from the video stream:
> Stream #0:0(und): ***Video***: h264 (Constrained Baseline) (avc1 /
> 0x31637661), yuv420p, 640x356, 862 kb/s, ***30 fps***, 30 tbr, 30 tbn, 60
> tbc
>
> frame= ***1135*** fps= 21 q=23.0 size=   11687kB time=00:00:37.80
> bitrate=2532.5kbits/s
>
> Convert Duration to frames, so you get the total amount of frames the video
> has and by looking at the latest frame= variable, now you can calculate
> just fine whats the actual progress...
>

Having done precisely this, there are some helpful hints I can suggest:

FFmpeg outputs status lines ending with '\r', so that on the console
it overwrites the current line. Most scripting languages have easy
ways of reading lines, you can use tr to turn CR into a LF, eg in
python:

    pffmpeg = Popen(self.args, stdout=PIPE, stderr=STDOUT, close_fds=True)
    ptr = Popen(['tr', '-u', '\\r', '\\n'], stdin=pffmpeg.stdout, stdout=PIPE)

Parse and discard lines until you get one which mentions the duration:

    while True:
      line = ptr.stdout.readline()
      if not line:
        break
      if not self.duration:
        match = DURATION_RE.search(line)
        if match:
          self.duration = self.__hr_mins_secs_to_secs(match.groupdict())
        elif self.debug:
          print u'ffmpeg pre-duration: %s' % (line,)
        continue

Once you have a duration, parse and discard lines until you get lines
with status information:

      match = FRAME_RE.search(line)
      if match:
        data = match.groupdict()
        frame = int(data['frames'])
        fps = int(data['fps'])
        time = self.__hr_mins_secs_to_secs(data)
        self.update_cache(frame, fps, time)

Not shown here is my app storing the cache value in memcached, with a
key based upon the assigned task id. This allows me to easily retrieve
the status when drawing a web page of it. It also pushes the info out
via AMQP/websockets pub/sub every couple of seconds to continually
update open web pages, but that is a bit OTT.

I did the timing/percentages based off time, not frames, as this
doesn't always work if you have variable frame rate input or output.

Cheers

Tom


More information about the ffmpeg-user mailing list