-1

I am trying to run a ffprobe command using a pre-defined by the user input file in Python. And then I will use the generated file by this command to report some parameters in a more organized view. My code is:

import subprocess
import json

cmd = "ffprobe -v quiet -print_format -show_format -show_streams /path/to/input/file.mp4 > output.json" 
subprocess.call(cmd.split())

with open('output.json') as json_data:
        data = json.load(json_data)
        json_data.close()
        d = float((data["streams"][0]["duration"]))
        t = (data["streams"][0]["time_base"])
        fps = [float(x) for x in t.split('/')]
        print "==========================General=========================="
        print "Name of the File: %s" %(data["format"]["filename"])
        print "Duration: %.2f minutes" %(d/60)
        print "Frame Rate: %d fps" %fps[1]
        print "Bitrate: %.2f Mbps" %(float(data["format"]["bit_rate"])/1000000)

I was thinking to use: input_file = ("Please enter the path to your input file: ") and then use the input_file in the ffprobe command on the second line of my code. But I am not sure how I can do it within the quotes. Please also note that the file name should also include an extension like input.mp4.

Georgi Stoyanov
  • 594
  • 1
  • 9
  • 26

2 Answers2

0

Shell redirection (>) will only work when shell=True is passed to subprocess.call(). Generally you should avoid doing that, specially if you take user input as part of the executed command, in which a case you need to make sure that the user input is properly escaped, e.g. by using shlex.qutoe().

Instead of using redirection in the shell you can open the file to write in python and pass it as stdout, or if you don't need the file you can use subprocess.check_output() instead of subprocess.call():

input_filename = raw_input("Please enter the path to your input file: ")
cmd = ['ffprobe', '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams',
       input_filename]

returned_data = subprocess.check_output(cmd)
data = json.loads(returned_data.decode('utf-8'))    # assuming the returned data is utf-8 encoded

...

Or the same with using a file to write to:

input_filename = raw_input("Please enter the path to your input file: ")
cmd = ['ffprobe', '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams',
       input_filename]

with open('output.json', 'wb') as outfile:
    subprocess.call(cmd, stdout=outfile)

with open('output.json', 'r') as infile:
    data = json.load(infile)

...

In this case the input filename doesn't need to be quoted because it is not interpreted by a shell.

mata
  • 67,110
  • 10
  • 163
  • 162
  • thanks for the hints, but it appears that both of your suggestions are returning syntax error. "Invalid Syntax" – Georgi Stoyanov Feb 06 '17 at 10:18
  • Did you copy this into a file or just paste it in an interactive interpreter? There shouldn't be a syntax error, but when pasting to the interpreter certain blocks require to be terminated by an empty lline, reformatted accordingly. Also if you paste the next line after `raw_input` will be used and can mess up things. Also I've changed `-print_format` to `-print_format json`, as that is probably what was intended. – mata Feb 06 '17 at 10:35
0

This should work:

#!/usr/bin/env python
import subprocess
import json

input_file = raw_input("Please enter the input file path: ")

returned_data = subprocess.check_output(['ffprobe', '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', input_file])
data = json.loads(returned_data.decode('utf-8'))
Georgi Stoyanov
  • 594
  • 1
  • 9
  • 26