1

I'm trying to use ffmpeg from python. The command I need to execute is:

ffmpeg -i test_file-1kB.mp4 -i test_file.mp4 -filter_complex psnr="stats_file=test_file.mp4-1kB.psnr" -f null -

However, my output that is getting passed to subprocess looks like it is escaping the double quotes with backslashes like so:

In[1]: print(subprocess.list2cmdline(psnr_args))
ffmpeg -i test_file-1kB.mp4 -i test_file.mp4 -filter_complex psnr=\"stats_file=test_file.mp4-1kB.psnr\" -f null -

To use subprocess, I build my command line arguments one at a time into a list and then pass the list to subprocess.

    psnr_args = []
    psnr_args.append("ffmpeg")

    #add first input, the encoded video
    psnr_args.append("-i")
    psnr_args.append(full_output_file_name)

    #add second input, the original video
    psnr_args.append("-i")
    psnr_args.append(video_file)

    #Setup the psnr log file
    psnr_args.append("-filter_complex")
    psnr_args.append('psnr="stats_file=%s.psnr"' % vstats_abs_filename )

    #Output the video to null
    psnr_args.append("-f")
    psnr_args.append("null")
    psnr_args.append("-")
    print(subprocess.list2cmdline(psnr_args))
    run_info_psnr = subprocess.run(psnr_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1
  • 1
    The quotes are instructions to the shell, not to ffmpeg. If you don't have a shell, you shouldn't have literal quotes. Just leave them out. Commented Oct 20, 2017 at 17:49

3 Answers 3

1

After more fiddling, I found a solution that works in this case but may not work in all cases. If I use double quotes as the outer quotes and the single quotes as the inner quotes, the output to subprocess uses a single quote at the same location with no backslash. This is acceptable for ffmpeg. However, for others where double quotes are the only solution, it won't be a fix.

psnr_args.append("psnr='stats_file=%s.psnr'" % vstats_abs_filename )

Output to subprocess looks like this:

In[1]: print(subprocess.list2cmdline(psnr_args))
ffmpeg -i test_file-1kB.mp4 -i test_file.mp4 -filter_complex psnr='stats_file=test_file.mp4-1kB.psnr' -f null -
Sign up to request clarification or add additional context in comments.

4 Comments

list2cmdline is a Windows-ism. If you want to convert a list to a command line in a way that's meaningful on Unix-family systems, use ' '.join(pipes.quote(x) for x in psnr_args) in Python 2, or the same with shlex.quote substituted for pipes.quote in Python 3.
simple quotes have no particular meaning in windows.
@Jean-FrançoisFabre, (1) true. (2) was that directed at me?
@CharlesDuffy nope. I know you know :)
1

In shell, the argument:

psnr="stats_file=test_file.mp4-1kB.psnr"

Is absolutely identical to:

psnr=stats_file=test_file.mp4-1kB.psnr

The quotes are removed during the shell's own processing. They are not part of the command passed to ffmpeg, which doesn't expect or understand them. Because you're directly telling the Python subprocess module to invoke a literal argument vector, there's no shell involved, so shell syntax shouldn't be present.

Comments

0

This has something to do with ffmpeg AV filter chain syntax too. You need to run the command like xxxx -filter_complex "psnr='stats.txt'" xxxx. To get this, you should ensure the double quote that encapsulate the filter chain reaches inside. subproces expects a flat list as the first argument, where the command is the first entry. So ['ffmpeg', '-i', "t1.mp4", "-filter_compelx", '"psnr=\'stats.txt\'"', .... and so on ].

Comments

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.