6

I'm having a problem getting two subprocesses to run together.

The first subprocesss is a transcode of a video stream:

subprocess.Popen("ffmpeg -i input output", shell=True)

I need this to run in the background of my program, transcoding video from my IP camera into a mjpeg stream.

The second subprocess is the Openalpr Daemon that looks at the mjpeg stream and returns car license plates it sees in the stream.

 subprocess.Popen("alprd -f", shell=True)

Here is a sample piece of python test code that tries to run both subprocesses:

import subprocess
subprocess.Popen("ffmpeg -i input output", shell=True)
subprocess.Popen("alprd -f", shell=True)

When i do this, the ffmpeg transcoding works fine, i can view the transcoded mjpeg stream and i can see ffmpegs verbose output in the console. However, the alprd daemon seems to not return any number plates as expected. In fact, i can't see any output from alprd in the console window.

If i run the above code with just one subprocess it works e.g.

import subprocess
subprocess.Popen("ffmpeg -i input output", shell=True)

works fine, as does:

import subprocess
subprocess.Popen("alprd -f", shell=True)

If i run either of the two working code snippets above - and at the same time run the other command in a separate linux terminal, it all works.

I'm clearly not understanding something with subprocesses, They are clearly conflicting with each other, but Can anyone explain what is happening and how to resolve the problem?

Thanks!

M.Jones
  • 109
  • 7
  • See [https://stackoverflow.com/questions/23818569/run-subprocesses-in-parallel](https://stackoverflow.com/questions/23818569/run-subprocesses-in-parallel) this explain it very good. Regards – MarLei Mar 01 '19 at 15:26
  • @M.Jones: You say "I'm having a problem", but then you don't describe the problem. What goes wrong? I suspect the two processes are interfering with each other's use of stdin/stdout or the terminal, but it's hard to say for sure without knowing exactly what problem you're observing. – Daniel Pryden Mar 01 '19 at 15:35
  • Thanks MarLei, but this is a different issue - i'm using Popen, which is non -blocking. – M.Jones Mar 01 '19 at 16:02
  • @DanielPryden: The problem is that the ffmpeg command runs and shows lots of output in the console. The alprd appears to stop and i don't see any of the expected output from it in the terminal. – M.Jones Mar 01 '19 at 16:10
  • @M.Jones: I'm not familiar with the `alprd` tool, but the fact that it's described as a "daemon" indicates that running it from the command-line like this might not be well supported. If you simply write a shell script that launches both programs in the background, do you get the same result? Does either program ever read input from the terminal? Do you need both programs to write output to the terminal, or would it be acceptable to have one or both programs write output to a log file instead? – Daniel Pryden Mar 01 '19 at 16:34

1 Answers1

2

It's likely that ffmpeg and alprd are both trying to interact with the same stdin/stdout file handles. To solve this, create separate pipes for one or both subprocesses to use as stdin/stdout. Then they can interact with them without interfering with each other.

import subprocess

with open('ffmpeg-output.txt', 'w') as ffmpeg_output:
    ffmpeg = subprocess.Popen(
        ['ffmpeg', '-i', 'input', 'output'],
        stdin=subprocess.PIPE,
        stdout=ffmpeg_output,
        stderr=subprocess.STDOUT)
    # We won't be sending any input into ffmpeg's stdin, so close it.
    ffmpeg.stdin.close()

    # alprd inherits stdin, stdout, and stderr from the current process.
    alprd = subprocess.Popen(['alprd', '-f'])

    # Wait for the subprocesses to finish.
    ffmpeg.wait()
    alprd.wait()
Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
  • Thanks for the answer, this does seem to run ok. I'll go and do some testing. Is it possible to dump the output of ffmpeg, rather than pass it to the text file? Its very verbose and i think it will quickly become unmanageable. Thank you very much for your help - its much appreciated! – M.Jones Mar 01 '19 at 16:58
  • If you want to dump it, you can just use `subprocess.DEVNULL` instead of a file object. – Daniel Pryden Mar 01 '19 at 18:26