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