mintermine
mintermine

Reputation: 75

Is there a way to run a subprocess that opens a window in the background in Python?

I am attempting to call ffplay in Python using subprocess. When ffplay is called, it opens a window with the video and outputs information to the console until the window is closed. I'd like to scrap the output and return to the Python script while the video continues to play (i.e., not closing the window).

Currently, I have:

# some code
subprocess.call(['ffplay', 'video.mp4'])
# some more code

How do I change this code to keep the window up and send the process output to the background to continue with the Python script?

Thanks in advance!

Upvotes: 2

Views: 1560

Answers (2)

Rotem
Rotem

Reputation: 32084

I think Popen is what you are looking for.

Here is a code sample:

import subprocess
import time

process = subprocess.Popen(['ffplay', '-hide_banner', '-nostats', '-autoexit', 'video.mp4'])

for i in range(10):
    time.sleep(1)
    print('Continue running ' + str(i))

process.wait()

subprocess.Popen opens a new-subprocess, and the sub-subprocess is executed at the background.
The Python script continue running after subprocess.Popen.

You may wait for the sub-process to finish, or terminate it (or just let it run).


Example for scraping the stdout and stderr output (reading FFplay output into Python's memory).

import subprocess
import time

process = subprocess.Popen(['ffplay', '-autoexit', '-t', '1', 'video.mp4'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdout, stderr = process.communicate()

process.wait()

print('stdout = ' + stdout.decode('utf-8'))
print('stderr = ' + stderr.decode('utf-8'))

Reading FFplay statistics "on the flight" while performing other operations, requires a thread.
In Windows it looks like we need to read byte by byte from stderr.
readline() is not working because FFplay output lines ends by LF (\r) character.

Here is a code sample:

import subprocess
import threading

# Read from stderr pipe - "draining the stderr pipe"
def drain_pipe(a_process):
    output_txt = b''
    while a_process.poll() is None:
        try:
            # Read one byte at a time, it's the only way it works in Windows, because lines ends with just \r.
            a_char = a_process.stderr.read(1)
            output_txt += a_char
            if a_char == b'\r':  # Look for line feed character.
                print(output_txt.decode('utf-8'))
                output_txt = b''
        except:
            break  # Exception may be raised because the pipe closes asynchronous

process = subprocess.Popen(['ffplay', '-stats', '-autoexit', 'video.mp4'], stderr=subprocess.PIPE)

stderr_thread = threading.Thread(target=drain_pipe, args=(process,))  # Create a thread for reading from stderr
stderr_thread.start()  # Start thread

# some more code...

process.wait()
stderr_thread.join()  # Join thread

Upvotes: 1

link
link

Reputation: 94

EDIT

Try this,

p = subprocess.Popen(['ffplay', 'sample-mp4-file.mp4', '-autoexit'],
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     universal_newlines=True) # This flag converts carriage return chars to new lines

while p.poll() is None:          # While the process p is still running
    line = p.stderr.readline()
    print(line)

My output:

ffplay version 4.2.4-1ubuntu0.1 Copyright (c) 2003-2020 the FFmpeg developers

  built with gcc 9 (Ubuntu 9.3.0-10ubuntu2)

  configuration: --prefix=/usr --extra-version=1ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared

  libavutil      56. 31.100 / 56. 31.100

  libavcodec     58. 54.100 / 58. 54.100

  libavformat    58. 29.100 / 58. 29.100

  libavdevice    58.  8.100 / 58.  8.100

  libavfilter     7. 57.100 /  7. 57.100

  libavresample   4.  0.  0 /  4.  0.  0

  libswscale      5.  5.100 /  5.  5.100

  libswresample   3.  5.100 /  3.  5.100

  libpostproc    55.  5.100 / 55.  5.100

    nan    :  0.000 fd=   0 aq=    0KB vq=    0KB sq=    0B f=0/0   

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'sample-mp4-file.mp4':

  Metadata:

    major_brand     : isom

    minor_version   : 512

    compatible_brands: isomiso2avc1mp41

    creation_time   : 1970-01-01T00:00:00.000000Z

    encoder         : Lavf53.24.2

  Duration: 00:02:05.95, start: 0.000000, bitrate: 669 kb/s

    Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 320x240 [SAR 1:1 DAR 4:3], 282 kb/s, 15 fps, 15 tbr, 15360 tbn, 30 tbc (default)

    Metadata:

      creation_time   : 1970-01-01T00:00:00.000000Z

      handler_name    : VideoHandler

    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 383 kb/s (default)

    Metadata:

      creation_time   : 1970-01-01T00:00:00.000000Z

      handler_name    : SoundHandler

  -0.01 A-V: -0.034 fd=   0 aq=  137KB vq=   93KB sq=    0B f=0/0   

   0.04 A-V: -0.027 fd=   0 aq=  135KB vq=   93KB sq=    0B f=0/0   

   0.07 A-V: -0.024 fd=   0 aq=  137KB vq=   94KB sq=    0B f=0/0   

   0.11 A-V: -0.022 fd=   0 aq=  135KB vq=   94KB sq=    0B f=0/0   

   0.14 A-V: -0.020 fd=   0 aq=  136KB vq=   94KB sq=    0B f=0/0   

   0.18 A-V: -0.020 fd=   0 aq=  136KB vq=   94KB sq=    0B f=0/0   

   0.20 A-V: -0.027 fd=   0 aq=  137KB vq=   92KB sq=    0B f=0/0   

   0.24 A-V: -0.025 fd=   0 aq=  135KB vq=   92KB sq=    0B f=0/0   

   0.27 A-V: -0.023 fd=   0 aq=  136KB vq=   93KB sq=    0B f=0/0   

   0.31 A-V: -0.020 fd=   0 aq=  134KB vq=   93KB sq=    0B f=0/0   

   0.34 A-V: -0.020 fd=   0 aq=  137KB vq=   89KB sq=    0B f=0/0   

   0.37 A-V: -0.028 fd=   0 aq=  135KB vq=   89KB sq=    0B f=0/0   

   0.41 A-V: -0.025 fd=   0 aq=  136KB vq=   89KB sq=    0B f=0/0   

   0.44 A-V: -0.023 fd=   0 aq=  134KB vq=   89KB sq=    0B f=0/0   

   0.48 A-V: -0.020 fd=   0 aq=  135KB vq=   86KB sq=    0B f=0/0   

   0.51 A-V: -0.020 fd=   0 aq=  135KB vq=   86KB sq=    0B f=0/0   

   0.54 A-V: -0.028 fd=   0 aq=  137KB vq=   83KB sq=    0B f=0/0   

   0.57 A-V: -0.025 fd=   0 aq=  134KB vq=   83KB sq=    0B f=0/0   

   0.61 A-V: -0.023 fd=   0 aq=  137KB vq=   82KB sq=    0B f=0/0   

   0.64 A-V: -0.020 fd=   0 aq=  135KB vq=   82KB sq=    0B f=0/0   

   0.68 A-V: -0.020 fd=   0 aq=  138KB vq=   78KB sq=    0B f=0/0   

   0.70 A-V: -0.027 fd=   0 aq=  136KB vq=   78KB sq=    0B f=0/0   

   0.74 A-V: -0.025 fd=   0 aq=  138KB vq=   76KB sq=    0B f=0/0   

   0.77 A-V: -0.022 fd=   0 aq=  136KB vq=   76KB sq=    0B f=0/0   

   0.81 A-V: -0.020 fd=   0 aq=  139KB vq=   73KB sq=    0B f=0/0   

   0.84 A-V: -0.020 fd=   0 aq=  137KB vq=   73KB sq=    0B f=0/0   

   0.87 A-V: -0.027 fd=   0 aq=  138KB vq=   69KB sq=    0B f=0/0   

   0.90 A-V: -0.025 fd=   0 aq=  136KB vq=   69KB sq=    0B f=0/0   

   0.94 A-V: -0.023 fd=   0 aq=  138KB vq=   67KB sq=    0B f=0/0   

   0.97 A-V: -0.023 fd=   0 aq=  138KB vq=   67KB sq=    0B f=0/0   

   1.01 A-V: -0.020 fd=   0 aq=  139KB vq=   64KB sq=    0B f=0/0   

   1.03 A-V: -0.028 fd=   0 aq=  137KB vq=   64KB sq=    0B f=0/0   

   1.07 A-V: -0.025 fd=   0 aq=  138KB vq=   62KB sq=    0B f=0/0   

   1.10 A-V: -0.025 fd=   0 aq=  138KB vq=   62KB sq=    0B f=0/0   

   1.14 A-V: -0.023 fd=   0 aq=  140KB vq=   60KB sq=    0B f=0/0   

   1.17 A-V: -0.020 fd=   0 aq=  138KB vq=   60KB sq=    0B f=0/0   

   1.20 A-V: -0.028 fd=   0 aq=  139KB vq=   57KB sq=    0B f=0/0   

   1.23 A-V: -0.028 fd=   0 aq=  139KB vq=   57KB sq=    0B f=0/0   

   1.27 A-V: -0.025 fd=   0 aq=  140KB vq=   56KB sq=    0B f=0/0   

   1.30 A-V: -0.023 fd=   0 aq=  138KB vq=   56KB sq=    0B f=0/0   

   1.34 A-V: -0.020 fd=   0 aq=  139KB vq=   54KB sq=    0B f=0/0   

I think this is what you are looking for.

Upvotes: 1

Related Questions