4

I have been trying to run this ffmpeg command from python script to generate video of certain length from a static image but I keep getting No such file or directory error! Here is my code:

import subprocess

def generate_white_vid (duration):
    ffmpeg_create_vid_from_static_img = 'ffmpeg -loop 1 -i /same_path/WhiteBackground.jpg -c:v libx264 -t %f -pix_fmt yuv420p -vf scale=1920:1080 /same_path/white_vid2.mp4' % duration
    print ffmpeg_create_vid_from_static_img
    pp = subprocess.Popen(ffmpeg_create_vid_from_static_img)
    pp.communicate()

generate_white_vid(0.5)

However when I run the same exact command:

ffmpeg -loop 1 -i /same_path/WhiteBackground.jpg -t 0.500000 -pix_fmt yuv420p -vf scale=1920:1080 /same_path/white_vid2.mp4

from the cli, it works just fine. Where am I missing up? Here is the full trace:

Traceback (most recent call last):
  File "gen.py", line 10, in <module>
    generate_white_vid(0.5)
  File "gen.py", line 7, in generate_white_vid
    pp = subprocess.Popen(ffmpeg_create_vid_from_static_img)
  File "/home/ubuntu/anaconda2/lib/python2.7/subprocess.py", line 390, in __init__
    errread, errwrite)
  File "/home/ubuntu/anaconda2/lib/python2.7/subprocess.py", line 1024, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

When I use a list to pass the ffmpeg commands parameters as following ffmpeg_create_vid_from_static_img = ['ffmpeg', '-loop', '1', '-i', '/same_path/WhiteBackground.jpg', '-c:v', 'libx264', '-t', duration, '-pix_fmt', 'yuv420p', '-vf', 'scale=1920:1080', '/same_path/white_vid.mp4'] , I get a type error:

TypeError                                 Traceback (most recent call last)
<ipython-input-137-4a9e12e42310> in <module>()
----> 1 generate_white_vid(0.5)

<ipython-input-136-edfbfc017557> in generate_white_vid(duration)
      3     ffmpeg_create_vid_from_static_img = ['ffmpeg', '-loop', '1', '-i', '/home/ubuntu/matar/multispectral/WhiteBackground.jpg', '-c:v', 'libx264', '-t', duration, '-pix_fmt yuv420p', '-vf', 'scale=1920:1080', '/home/ubuntu/matar/multispectral/white_vid.mp4']
      4     print ffmpeg_create_vid_from_static_img
----> 5     pp = subprocess.Popen(ffmpeg_create_vid_from_static_img)
      6     pp.communicate()

/home/ubuntu/anaconda2/lib/python2.7/subprocess.pyc in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
    388                                 p2cread, p2cwrite,
    389                                 c2pread, c2pwrite,
--> 390                                 errread, errwrite)
    391         except Exception:
    392             # Preserve original exception in case os.close raises.

/home/ubuntu/anaconda2/lib/python2.7/subprocess.pyc in _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, to_close, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
   1022                         raise
   1023                 child_exception = pickle.loads(data)
-> 1024                 raise child_exception
   1025 
   1026 

TypeError: execv() arg 2 must contain only strings
A_Matar
  • 2,210
  • 3
  • 31
  • 53
  • 1
    Maybe missing an argument `shell=True` for `Popen`? – etopylight Nov 23 '17 at 17:09
  • @etopylight This has ridiculously worked, Thank you a lot. Do you have any idea why? – A_Matar Nov 23 '17 at 17:20
  • 2
    Since `shell=False` is default for `Popen`, you would normally need to construct the command line as a **separate list of elements** (which is more secure by the way). However, in case when you just want to pass your command as a string, then a mandatory `shell=True` would be required – etopylight Nov 23 '17 at 17:31
  • when I tried passing the command as separate list of element, I got a type error. see above for the full trace stack. Also, would u please add an answer so that I could give u ur deserved credit by accepting it. Thanks – A_Matar Nov 23 '17 at 17:44
  • 1
    Thanks, added an answer. For the type error however, I think the error message is informing you that your `duration` is not a string, so you might want to try casting it to a string. – etopylight Nov 23 '17 at 17:58
  • Does this answer your question? [Python subprocess.Popen() error (No such file or directory)](https://stackoverflow.com/questions/30010939/python-subprocess-popen-error-no-such-file-or-directory) – tripleee Feb 17 '21 at 12:38

1 Answers1

3

Since shell=False is the default value for Popen, you would normally need to construct the command line as a separate list of elements (which is more secure by the way).

However, in case when you just want to pass your command as a string, then a mandatory shell=True would be required.

etopylight
  • 1,239
  • 1
  • 10
  • 15