0

I want to use python subprocess to call ffmpeg and use crop detect to find all black in a video. The crop detect return I want to put into a string variable and put in a database. At the moment I can get the process running in terminal and but I am unsure about how to grab the specific part of the terminal (stdout) output:

the script:

def cropDetect():
    p = subprocess.Popen(["ffmpeg", "-i", "/Desktop/ffprobe_instance/Crop_detect/video_file.mpg", "-vf", "cropdetect=24:16:0", "-vframes", "10", "dummy.mp4"], stdout=subprocess.PIPE)
    result = p.communicate()[0]
    print result


# SCRIPT
cropDetect()

Result in terminal: [Parsed_cropdetect_0 @ 0x7fa1d840cb80] x1:719 x2:0 y1:575 y2:0 w:-704 h:-560 x:714 y:570 pos:432142 pts:44102 t:0.490022 crop=-704:-560:714:570

How do I take "crop=-704:-560:714:570" and put it into a variable that I can store in a database?

As per update:

def cropDetect1():
    p = subprocess.check_output(["ffmpeg", "-i", "/Desktop/ffprobe_instance/Crop_detect/video_file.mpg", "-vf", "cropdetect=24:16:0", "-vframes", "10", "dummy.mp4"])
    match = re.search("crop\S+", p)
    crop_result = None
    if match is not None:
        crop_result = match.group()
        print "hello %s" % crop_result

I can't seem to print out the "crop_result" - I am presuming that means that the variable is empty?

UPDATE: Found it:

def detectCropFile(localPath):
    fpath = "/xxx/xx/Desktop/Crop_detect/videos/USUV.mp4"
    print "File to detect crop: %s " % fpath
    p = subprocess.Popen(["ffmpeg", "-i", fpath, "-vf", "cropdetect=24:16:0", "-vframes", "500", "-f", "rawvideo", "-y", "/dev/null"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    infos = p.stderr.read()
    print infos
    allCrops = re.findall(CROP_DETECT_LINE + ".*", infos)
    print allCrops 
    mostCommonCrop = Counter(allCrops).most_common(1)
    print "most common crop: %s" % mostCommonCrop
    print mostCommonCrop[0][0]
    global crop
    crop = mostCommonCrop[0][0]
    video_rename()

Use: p = subprocess.Popen(["ffmpeg", "-i", fpath, "-vf", "cropdetect=24:16:0", "-vframes", "500", "-f", "rawvideo", "-y", "/dev/null"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) to pipe it out

6
  • Do you see the 'hello' string? I'd either step through this in a debugger, or throw in print statements to see. For instance, print p, and then print match. I suspect you won't see anything for match. Commented Apr 8, 2015 at 16:12
  • Hey - no there is no hello - but if I do "print 'hello p %s' % p" and "print 'hello match %s' % match" I do get "hello p" and "hello match" Commented Apr 8, 2015 at 16:17
  • Well, you shouldn't be seeing just 'hello p' in that situation. You should be seeing 'hello Parsed_cropdetect_0 etc p', no? Same with the match -- you should be seeing something like `hello <_sre.SRE_Match at 0xmemoryaddress> match'. It looks like your ffmpeg isn't outputting to stdout. Commented Apr 8, 2015 at 16:19
  • running the script I get full result in the terminal window: [Parsed_cropdetect_0 @ 0x7f96cb40cb80] x1:719 x2:0 y1:575 y2:0 w:-704 h:-560 x:714 y:570 pos:-1 pts:8102 t:0.090022 crop=-704:-560:714:570 [Parsed_cropdetect_0 @ 0x7f96cb40cb80] x1:719 x2:0 y1:575 y2:0 w:-704 h:-560 x:714 y:570 pos:10254 pts:11702 t:0.130022 crop=-704:-560:714:570 - I just can't seem to figure out how to take all that and parse/write out/pipe out that information Commented Apr 8, 2015 at 16:21
  • What about when you redirect the command? Run the command but redirect stderr to /dev/null like so: command 2> /dev/null. I think that terminal output is probably being sent to stderr instead of stdout, in which case the Python would need to listen on stderr instead. Commented Apr 8, 2015 at 16:23

2 Answers 2

1

It looks like you don't need to be using the lower level subprocess.Popen interface; I'd just call subprocess.check_output, which will return the value of the os call as a string. From there, just do string processing to get your value.

result = subprocess.check_output(["ffmpeg", "-i" ... ])
# this regex matches the string crop followed by one or more non-whitespace characters 
match = re.search("crop\S+", result) 
crop_result = None
if match is not None:
     crop_result = match.group()

If ffmpeg output is instead to stderr:

result = subprocess.check_output(["ffmpeg", ...], stderr=subprocess.STDOUT)
Sign up to request clarification or add additional context in comments.

3 Comments

getting: match = re.search("crop\S+", result) NameError: global name 'result' is not defined
That means the variable result isn't defined yet, which means you probably named the returned value from subprocess.check_output something different.
Can't get it to work it seems - I updated the code above
0

Ok found it

def detectCropFile(localPath):
    fpath = "/xxx/xx/Desktop/Crop_detect/videos/USUV.mp4"
    print "File to detect crop: %s " % fpath
    p = subprocess.Popen(["ffmpeg", "-i", fpath, "-vf", "cropdetect=24:16:0", "-vframes", "500", "-f", "rawvideo", "-y", "/dev/null"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    infos = p.stderr.read()
    print infos
    allCrops = re.findall(CROP_DETECT_LINE + ".*", infos)
    print allCrops 
    mostCommonCrop = Counter(allCrops).most_common(1)
    print "most common crop: %s" % mostCommonCrop
    print mostCommonCrop[0][0]
    global crop
    crop = mostCommonCrop[0][0]
    video_rename()

So use this in the subprocess call to grab the values from crop detect:

p = subprocess.Popen(["ffmpeg", "-i", fpath, "-vf", "cropdetect=24:16:0", "-vframes", "500", "-f", "rawvideo", "-y", "/dev/null"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

1 Comment

you should use stdout_value, stderr_value = p.communicate() or merged_value = check_ouptut(..., stderr=STDOUT) as @jwilner suggested

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.