0

I'm trying to start and stop an ffmpeg pipeline in my Python script. I can get it to start the pipeline on command, using a subprocess, but it ties up the script, so that it no longer receives commands. What do I need to change to keep this from happening?

I'm using:

    pipeline= "ffmpeg -f video4linux2 -video_size 640x480 -framerate 15 -input_format yuyv422 -i /dev/video7 -f alsa  -i hw:0,0 -map 0:0 -map 1:0  -b:v 120k -bufsize 120k -vcodec libx264 -preset ultrafast  -acodec aac -strict -2  -f flv -metadata streamName=myStream tcp://192.168.1.20:6666 "

    p = subprocess.Popen(pipeline, shell=True,
                         stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = p.communicate()[0]
user3147697
  • 91
  • 1
  • 9

2 Answers2

1

The problem with your code is that p.communicate() reads data until end-of-file is reached. My Idea would be to use the multiprocessingmodule.

Example:

import subprocess
import multiprocessing

def ffmpeg():
    pipeline = 'ffmpeg ...'
    p = subprocess.Popen(pipeline, shell=True, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    out = p.communicate()[0]

proc = multiprocessing.Process(target=ffmpeg)

This basically moves your code into the function ffmpeg and creates a new process to run it.

You can now start the process using: proc.start() and terminate it using proc.terminate().

For more details have a look at the documentation of multiprocessing.

EDIT:

multiprocessing is maybe kinda overkill. See J.F. Sebastian's comment.

Joel Hermanns
  • 355
  • 1
  • 4
  • 11
  • 2
    you don't need `multiprocessing.Process` to get subprocess' output without blocking, you could [use threads or async.io instead](http://stackoverflow.com/a/23616229/4279) – jfs Sep 25 '14 at 10:19
  • `multiprocessing.Process` was just my first idea. But you're right, thanks! – Joel Hermanns Sep 25 '14 at 10:41
0

p.communicate() call doesn't return until the process exits and all output is read.

To avoid blocking your script, drop the p.communicate() call:

#!/usr/bin/env python3
import shlex
from subprocess import Popen, DEVNULL, STDOUT
# ...
p = Popen(shlex.split(pipeline), stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT)
# call p.terminate() any time you like, to terminate the ffmpeg process
jfs
  • 399,953
  • 195
  • 994
  • 1,670