question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ability to track progress of an ffmpeg command

See original GitHub issue

Is there a way to track a progress after running an ffmpeg?

For example, below is what i would like to do:

import ffmpeg
ffmpeg.input('test.mp4').output('frame_%06d.jpg').run()

This command writes each frame of a video as an image to disk.

At the very least it would be great if we could see the output generated by running ffmpeg on commandline ffmpeg -i test.mp4 %06d.png -hide_banner

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'workflow_video_01.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 2036-02-06 06:28:16
    encoder         : HandBrake 0.10.2 2015060900
  Duration: 00:50:57.00, start: 0.000000, bitrate: 7040 kb/s
    Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 7038 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc (default)
    Metadata:
      creation_time   : 2036-02-06 06:28:16
      handler_name    : VideoHandler
Output #0, image2, to 'dump/%06d.png':
  Metadata:
    major_brand     : mp42
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf56.40.101
    Stream #0:0(und): Video: png, rgb24, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc (default)
    Metadata:
      creation_time   : 2036-02-06 06:28:16
      handler_name    : VideoHandler
      encoder         : Lavc56.60.100 png
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> png (native))
Press [q] to stop, [?] for help
frame=  677 fps= 59 q=-0.0 Lsize=N/A time=00:00:27.08 bitrate=N/A  

Any ideas on how to do this?

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:7
  • Comments:13 (2 by maintainers)

github_iconTop GitHub Comments

19reactions
kkroeningcommented, May 9, 2018

Perhaps the above example could be condensed into something like the following at some point:

def progress_handler(progress_info):
    print('{:.2f}'.format(progress_info['percentage']))

(ffmpeg
    .input('in.mp4')
    .output('out.mp4')
    .progress(progress_handler)
    .overwrite_output()
    .run()
)
5reactions
kkroeningcommented, May 9, 2018

Here’s a semi-hacked-together example using gevent and the -progress param @Depau mentioned:

import gevent.monkey; gevent.monkey.patch_all()

import contextlib
import ffmpeg
import gevent
import os
import shutil
import socket
import subprocess
import sys
import tempfile


@contextlib.contextmanager
def _tmpdir_scope():
    tmpdir = tempfile.mkdtemp()
    try:
        yield tmpdir
    finally:
        shutil.rmtree(tmpdir)


def _watch_progress(filename, sock, handler):
    connection, client_address = sock.accept()
    data = ''
    with contextlib.closing(connection):
        while True:
            more_data = connection.recv(16)
            if not more_data:
                break
            data += more_data
            lines = data.split('\n')
            for line in lines[:-1]:
                parts = line.split('=')
                key = parts[0] if len(parts) > 0 else None
                value = parts[1] if len(parts) > 1 else None
                handler(key, value)
            data = lines[-1]


@contextlib.contextmanager
def watch_progress(handler):
    with _tmpdir_scope() as tmpdir:
        filename = os.path.join(tmpdir, 'sock')
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        with contextlib.closing(sock):
            sock.bind(filename)
            sock.listen(1)
            child = gevent.spawn(_watch_progress, filename, sock, handler)
            try:
                yield filename
            except:
                gevent.kill(child)
                raise


duration = float(ffmpeg.probe('in.mp4')['format']['duration'])

prev_text = None

def handler(key, value):
    global prev_text
    if key == 'out_time_ms':
        text = '{:.02f}%'.format(float(value) / 10000. / duration)
        if text != prev_text:
            print(text)
            prev_text = text


with watch_progress(handler) as filename:
    p = subprocess.Popen(
        (ffmpeg
            .input('in.mp4')
            .output('out.mp4')
            .global_args('-progress', 'unix://{}'.format(filename))
            .overwrite_output()
            .compile()
        ),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    out = p.communicate()

if p.returncode != 0:
    sys.stderr.write(out[1])
    sys.exit(1)
  • It creates and listens on a unix-domain socket and passes that to ffmpeg.
  • The watcher runs in its own gevent greenlet, but it could be changed to use actual threads instead if desired.
  • In order to know the progress percentage, it uses the duration reported by ffprobe, since the normal progress info doesn’t seem to contain such info.
  • It runs with subprocess.Popen to silence stdout/stderr. There’s probably a better way to silence ffmpeg, in which case .run() can be used instead of calling subprocess manually.

I’m not sure if/when this will be incorporated into ffmpeg-python, but something to play with in the mean time.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can ffmpeg show a progress bar? - Stack Overflow
I use ffpb and python subprocess to tracking ffmpeg progress. Then I push status to a database (ex: Redis) for display a progress...
Read more >
How can I get ffmpeg command running status in real time?
If you run ffmpeg with the -progress - -nostats options, it'll print its progress in a parsable format to the output:
Read more >
ffmpeg Documentation
When there are multiple input files, ffmpeg tries to keep them synchronized by tracking lowest timestamp on any active input stream.
Read more >
My Python function which shows the percentage progress ...
https://github.com/CrypticSignal/better-ffmpeg-progress # better-ffmpeg-progress A Python function that runs an FFmpeg command and shows ...
Read more >
better-ffmpeg-progress - PyPI
Runs an FFmpeg command and uses tqdm to show a progress bar. ... Add the ability to specify process_complete_handler , a function to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found